The code i am looking at (if this helps) is attached below (from
http://www.codeproject.com/cs/combob...ears_flat.asp).
In the WM_NC_PAINT message handler, a graphics object is already
created, but then SendPrintClient Msg() is called which seems to do the
same work again (in reverse - getting the hDC from
this.CreateGrap hics). Is this mad, or more likely, am i missing
something?
....
using System;
using System.Windows. Forms;
using System.Drawing;
using System.Drawing. Drawing2D;
using System.Runtime. InteropServices ;
namespace DrawFlat
{
[ToolboxBitmap(t ypeof(System.Wi ndows.Forms.Com boBox))]
public class FlatComboBox: ComboBox
{
#region ComboInfoHelper
internal class ComboInfoHelper
{
[DllImport("user 32")]
private static extern bool GetComboBoxInfo (IntPtr hwndCombo, ref
ComboBoxInfo info);
#region RECT struct
[StructLayout(La youtKind.Sequen tial)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
#endregion
#region ComboBoxInfo Struct
[StructLayout(La youtKind.Sequen tial)]
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 GetComboDropDow nWidth()
{
ComboBox cb = new ComboBox();
int width = GetComboDropDow nWidth(cb.Handl e);
cb.Dispose();
return width;
}
public static int GetComboDropDow nWidth(IntPtr handle)
{
ComboBoxInfo cbi = new ComboBoxInfo();
cbi.cbSize = Marshal.SizeOf( cbi);
GetComboBoxInfo (handle, ref cbi);
int width = cbi.rcButton.Ri ght - cbi.rcButton.Le ft;
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 DropDownButtonW idth = 17;
[DllImport("user 32.dll", EntryPoint="Sen dMessageA")]
public static extern int SendMessage (IntPtr hwnd, int wMsg, IntPtr
wParam, object lParam);
[DllImport("user 32")]
public static extern IntPtr GetWindowDC (IntPtr hWnd );
[DllImport("user 32")]
public static extern int ReleaseDC(IntPt r hWnd, IntPtr hDC );
static FlatComboBox()
{
DropDownButtonW idth = ComboInfoHelper .GetComboDropDo wnWidth() + 2;
}
public FlatComboBox()
: base()
{
this.SetStyle(C ontrolStyles.Do ubleBuffer, true);
}
protected override void OnSelectedValue Changed(EventAr gs e)
{
base.OnSelected ValueChanged (e);
this.Invalidate ();
}
protected override void WndProc(ref Message m)
{
if (this.DropDownS tyle == ComboBoxStyle.S imple)
{
base.WndProc(re f m);
return;
}
IntPtr hDC = IntPtr.Zero;
Graphics gdc = null;
switch (m.Msg)
{
case WM_NC_PAINT:
hDC = GetWindowDC(thi s.Handle);
gdc = Graphics.FromHd c(hDC);
SendMessage(thi s.Handle, WM_ERASEBKGND, hDC, 0);
SendPrintClient Msg(); // send to draw client area
PaintFlatContro lBorder(this, gdc);
m.Result = (IntPtr) 1; // indicate msg has been processed
ReleaseDC(m.HWn d, hDC);
gdc.Dispose();
break;
case WM_PAINT:
base.WndProc(re f m);
// flatten the border area again
hDC = GetWindowDC(thi s.Handle);
gdc = Graphics.FromHd c(hDC);
Pen p = new Pen((this.Enabl ed? BackColor:Syste mColors.Control ),
2);
gdc.DrawRectang le(p, new Rectangle(2, 2, this.Width-3,
this.Height-3));
PaintFlatDropDo wn(this, gdc);
PaintFlatContro lBorder(this, gdc);
ReleaseDC(m.HWn d, hDC);
gdc.Dispose();
break;
default:
base.WndProc(re f m);
break;
}
}
private void SendPrintClient Msg()
{
// We send this message for the control to redraw the client area
Graphics gClient = this.CreateGrap hics();
IntPtr ptrClientDC = gClient.GetHdc( );
SendMessage(thi s.Handle, WM_PRINTCLIENT, ptrClientDC, 0);
gClient.Release Hdc(ptrClientDC );
gClient.Dispose ();
}
private void PaintFlatContro lBorder(Control ctrl, Graphics g)
{
Rectangle rect = new Rectangle(0, 0, ctrl.Width, ctrl.Height);
if (ctrl.Focused == false || ctrl.Enabled == false )
ControlPaint.Dr awBorder(g, rect, SystemColors.Co ntrolDark,
ButtonBorderSty le.Solid);
else
ControlPaint.Dr awBorder(g, rect, Color.Black,
ButtonBorderSty le.Solid);
}
public static void PaintFlatDropDo wn(Control ctrl, Graphics g)
{
Rectangle rect = new Rectangle(ctrl. Width-DropDownButtonW idth, 0,
DropDownButtonW idth, ctrl.Height);
ControlPaint.Dr awComboButton(g , rect, ButtonState.Fla t);
}
protected override void OnLostFocus(Sys tem.EventArgs e)
{
base.OnLostFocu s(e);
this.Invalidate ();
}
protected override void OnGotFocus(Syst em.EventArgs e)
{
base.OnGotFocus (e);
this.Invalidate ();
}
protected override void OnResize(EventA rgs e)
{
base.OnResize (e);
this.Invalidate ();
}
}
}