[Mono-winforms-list] Making a funky button

Max de Lavenne max at tfbc.com
Tue Jan 23 20:13:32 EST 2007

You raised my curiousity. This code may work. It would prevent painting the
button, and instead, it would paint a transparent rectangle and then paint
your bitmap on top of it (make sure you have a full transparency outside of
the round shape).

Then, the Mouse event handled below would take care of checking the pixel
clicked for full transparency, and discard the click event on such pixels. I
haven't compiled this code. I haven't tested it, but it's a good start. 

If I were you, I would probably implement my own control inheriting from

Good Luck

Best Regards



Public class ShapeButton : System.Windows.Forms.Button {

  private Bitmap _bitmap;
  private Point _mouse = Point.Empty;
  private bool _check_pixel = false;
  private Bitmap _round_bitmap;	// <= set this to your round bitmap


// user is clicking down on this button
Protected override void OnMouseDown(object source, MouseEventArgs e) {
	_mouse = new Point(e.X,e.Y);

// if the mouse leaves the control, then clear out the coords
// because it means the user did not want to click on the button
Protected override void OnMouseLeave(object source, MouseEventArgs e) {
	_mouse = Point.Empty;

// if the user unclicked the mouse on the button, 
// then set a flag to tell that we need to check the transparency of the
pixel clicked.
// => if completely transparent, then he clicked outside your bitmap. 
// You may need some tweaking
Protected override void OnMouseUp(object source, MouseEventArgs e) {
	if ( !_mouse.Equals(Point.Empty) ) {
		_check_pixel = true;
	} else {
		_check_pixel = false;

// forward the onclick to the button if the user clicked on a
non-transparent pixel,
// that is, a pixel from your round bitmap
Protected override void OnClick(object source, EventArgs e) {
	if ( _check_pixel ) {
		if ( _bitmap != null && _round_bitmap != null ) {
			Color c = _bitmap.GetPixel(x,y);
			if ( c.A == 0 ) {
				// transparent => discard button click
				return;	// I am not sure whether this would
truly discard the Click event. 
						// This is the untested part
	// forward to base class

Protected void Dispose(bool disposing) {
		if ( _bitmap != null ) {

Protected override void OnPaintBackground(object sender, PaintEventArgs e) {
	// discard this (to avoid flickering)

Protected override void OnPaint(object sender, PaintEventArgs e) {
	if ( this.Width == 0 || this.Height == 0 ) {
		return;	// control resizing to initial state
	// lazy initialization
	if ( _bitmap == null || !Size.Equals(_bitmap.Size) ) {
		if ( _bitmap != null ) {
			_bitmap.Dispose();	// cleanup as we go.
		_bitmap = new

	// paint on bitmap
	Graphics g = Graphics.FromImage(_bitmap);

	// paint your round bitmap here

	// flush bitmap


}	// end of class
-----Original Message-----
From: mono-winforms-list-bounces at lists.ximian.com
[mailto:mono-winforms-list-bounces at lists.ximian.com] On Behalf Of Paul
Sent: Tuesday, January 23, 2007 4:39 PM
To: winforms
Subject: [Mono-winforms-list] Making a funky button


I have a need to create a button. Okay, that's the easy bit. The problem is
the button has an image on it and therefore needs to adopt the shape of the
image (rounded square).

Is mono winforms able to do it and if it is, can anyone point me in the
right direction on how to do it?


"Mmmmmmmm....Shakira geschmiert mit schokolade" sagt Homer

More information about the Mono-winforms-list mailing list