The other day, I decided to enable visual styles on one of my winform apps and found out that doing so breaks buttons with images. To get around this, I had to write a control which would inherit from the System.Windows.Forms.Button class and then handle the WM_PAINT message and draw the image myself. Below is the code I used.
/* * Showing images on XP-styled buttons. * * Author: Andrew Ma * http://blogs.msdn.com/ajma/archive/2005/01/21/358356.aspx * * Redistribution and use in source and binary forms, with or without * modification, are permitted. * * This posting is provided "AS IS" with no warranties, and confers no rights. * Use of included code samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm */
using System;using System.Drawing;using System.Windows.Forms;
namespace ajma{ /// <summary> /// Represents a Windows button control that will use Visual Styles by default. This button will also draw images if specified. /// </summary> public class Button : System.Windows.Forms.Button { /// <summary> /// WM_PAINT message /// </summary> const int WM_PAINT = 0xF;
/// <summary> /// Initializes a new instance of the Button class. /// </summary> public Button() { FlatStyle = FlatStyle.System; }
/// <summary> /// Overridden. See <see cref="Control.WndProc"/>. /// </summary> /// <param name="m">The Windows <see cref="Message"/> to process. </param> protected override void WndProc(ref Message m) { // let base.WndProc go first base.WndProc (ref m);
// if paiting (and there is a message), draw image on top of button if(m.Msg == WM_PAINT && this.Image != null) { Graphics g = Graphics.FromHwnd(this.Handle); switch(this.ImageAlign) { case ContentAlignment.BottomCenter: g.DrawImage(this.Image, centerX(), bottom()); break; case ContentAlignment.BottomLeft: g.DrawImage(this.Image, left(), bottom()); break; case ContentAlignment.BottomRight: g.DrawImage(this.Image, right(), bottom()); break; case ContentAlignment.MiddleCenter: g.DrawImage(this.Image, centerX(), centerY()); break; case ContentAlignment.MiddleLeft: g.DrawImage(this.Image, left(), centerY()); break; case ContentAlignment.MiddleRight: g.DrawImage(this.Image, right(), centerY()); break; case ContentAlignment.TopCenter: g.DrawImage(this.Image, centerX(), top()); break; case ContentAlignment.TopLeft: g.DrawImage(this.Image, left(), top()); break; case ContentAlignment.TopRight: g.DrawImage(this.Image, right(), top()); break; } g.Dispose(); } }
#region Returns the X/Y points for the image to be drawn private int centerX() { return (this.Width - this.Image.Width) / 2; }
private int centerY() { return (this.Height - this.Image.Height) / 2; }
private int top() { return 4; }
private int left() { return 4; }
private int right() { return this.Width - this.Image.Width - left(); }
private int bottom() { return this.Height - this.Image.Width - top(); } #endregion }}
This posting is provided "AS IS" with no warranties, and confers no rights.