Click here to Skip to main content
11,573,227 members (69,211 online)
Click here to Skip to main content
Add your own
alternative version

Making Standard ComboBox appear flat

, 18 May 2005 305.4K 4.2K 73
A simple and easy class that draws the standard ComboBox as flat control.
flatcombobox_src.zip
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;

namespace DrawFlat
{
	[ToolboxBitmap(typeof(System.Windows.Forms.ComboBox))]
	public class FlatComboBox: ComboBox
	{	
		#region ComboInfoHelper
		internal class ComboInfoHelper
		{
			[DllImport("user32")] 
			private static extern bool GetComboBoxInfo(IntPtr hwndCombo, ref ComboBoxInfo info);

			#region RECT struct
			[StructLayout(LayoutKind.Sequential)]
				private struct RECT 
			{
				public int Left;
				public int Top;
				public int Right;
				public int Bottom;
			}
			#endregion

			#region ComboBoxInfo Struct
			[StructLayout(LayoutKind.Sequential)]
				private struct ComboBoxInfo 
			{
				public int cbSize;
				public RECT rcItem;
				public RECT rcButton;
				public IntPtr stateButton;
				public IntPtr hwndCombo;
				public IntPtr hwndEdit;
				public IntPtr hwndList;
			}
			#endregion

			public static int GetComboDropDownWidth()
			{
				ComboBox cb = new ComboBox();
				int width = GetComboDropDownWidth(cb.Handle);
				cb.Dispose();
				return width;
			}
			public static int GetComboDropDownWidth(IntPtr handle)
			{
				ComboBoxInfo cbi = new ComboBoxInfo();
				cbi.cbSize = Marshal.SizeOf(cbi);
				GetComboBoxInfo(handle, ref cbi);
				int width = cbi.rcButton.Right - cbi.rcButton.Left;
				return width;
			}
		}
		#endregion

		public const int WM_ERASEBKGND = 0x14;
		public const int WM_PAINT = 0xF;
		public const int WM_NC_PAINT = 0x85;
		public const int WM_PRINTCLIENT = 0x318;
		private static int DropDownButtonWidth = 17;

		[DllImport("user32.dll", EntryPoint="SendMessageA")]
		public static extern int SendMessage (IntPtr hwnd, int wMsg, IntPtr wParam, object lParam);

		[DllImport("user32")]
		public static extern IntPtr GetWindowDC (IntPtr hWnd );

		[DllImport("user32")]
		public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC );

		static FlatComboBox()
		{
			DropDownButtonWidth = ComboInfoHelper.GetComboDropDownWidth() + 2;
		}

        public FlatComboBox()
			: base()
		{
			this.SetStyle(ControlStyles.DoubleBuffer, true);
		}

		protected override void OnSelectedValueChanged(EventArgs e)
		{
			base.OnSelectedValueChanged (e);
			this.Invalidate();
		}

		protected override void WndProc(ref Message m)
		{
			if (this.DropDownStyle == ComboBoxStyle.Simple)
			{
				base.WndProc(ref m);
				return;
			}

			IntPtr hDC = IntPtr.Zero;
			Graphics gdc = null;
			switch (m.Msg)
			{
				case WM_NC_PAINT:	
					hDC = GetWindowDC(this.Handle);
					gdc = Graphics.FromHdc(hDC);
					SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
					SendPrintClientMsg();	// send to draw client area
					PaintFlatControlBorder(this, gdc);
					m.Result = (IntPtr) 1;	// indicate msg has been processed			
					ReleaseDC(m.HWnd, hDC);
					gdc.Dispose();	

					break;
				case WM_PAINT:	
					base.WndProc(ref m);
					// flatten the border area again
					hDC = GetWindowDC(this.Handle);
					gdc = Graphics.FromHdc(hDC);
					Pen p = new Pen((this.Enabled? BackColor:SystemColors.Control), 2);	
					gdc.DrawRectangle(p, new Rectangle(2, 2, this.Width-3, this.Height-3));
					PaintFlatDropDown(this, gdc);
					PaintFlatControlBorder(this, gdc);
					ReleaseDC(m.HWnd, hDC);
					gdc.Dispose();	

					break;
				default:
					base.WndProc(ref m);
					break;
			}
		}
		private void SendPrintClientMsg()
		{
			// We send this message for the control to redraw the client area
			Graphics gClient = this.CreateGraphics();
			IntPtr ptrClientDC = gClient.GetHdc();
			SendMessage(this.Handle, WM_PRINTCLIENT, ptrClientDC, 0);
			gClient.ReleaseHdc(ptrClientDC);
			gClient.Dispose();
		}

		private void PaintFlatControlBorder(Control ctrl, Graphics g)
		{
			Rectangle rect = new Rectangle(0, 0, ctrl.Width, ctrl.Height);
			if (ctrl.Focused == false || ctrl.Enabled == false )
				ControlPaint.DrawBorder(g, rect, SystemColors.ControlDark, ButtonBorderStyle.Solid);
			else
				ControlPaint.DrawBorder(g, rect, Color.Black, ButtonBorderStyle.Solid);
		}
		public static void PaintFlatDropDown(Control ctrl, Graphics g)
		{
			Rectangle rect = new Rectangle(ctrl.Width-DropDownButtonWidth, 0, DropDownButtonWidth, ctrl.Height);
			ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);
		}

		protected override void OnLostFocus(System.EventArgs e)
		{
			base.OnLostFocus(e);
			this.Invalidate();
		}

		protected override void OnGotFocus(System.EventArgs e)
		{
			base.OnGotFocus(e);
			this.Invalidate();
		}		
		protected override void OnResize(EventArgs e)
		{
			base.OnResize (e);
			this.Invalidate();
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Fadrian Sudaman
Architect SMS Management and Technology
Australia Australia
Fadrian Sudaman is an experienced IT professional who has worked with .NET technology since the early beta. His background stems from a strong C/C++ development experience in building large commercial applications and great appreciation for best practice and modern approaches for building quality software. Currently, Fadrian works as a senior consultant specialises in .NET technology involved in variety of roles including project management, solution architecture, presales and application development. Fadrian is also completing his PhD part time at Monash University, Australia.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150624.2 | Last Updated 18 May 2005
Article Copyright 2004 by Fadrian Sudaman
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid