How do you draw a custom button next to the minimize, maximize and close buttons within the Titlebar of the Form?
I know you need to use Win32 API calls and override the WndProc procedure, but I haven't been able to figure out a solution that works right.
Does anyone know how to do this? More specifically, does anyone know a way to do this that works in Vista?
In addition, the Title Bar has the three buttons familiar to Windows ® users: Minimize, Maximize, and Close.
Adjusting the Title bar Text SizeClick the Cortana button on the taskbar and enter Control Panel in the search box to open it. Then click Display to open the options shown below. There you can customize the font sizes in Windows. Click the drop-down menu on the left and select Title bars.
Basic features of the title bar As illustrated in the picture above, the standard title bar has a minimize, maximize, and close button, usually on the right side.
At the top of every window is the title bar, which displays the name of the application. It also has buttons that are clicked to minimize and restore the window and exit the application (see Win Minimize windows).
The following will work in XP, I have no Vista machine handy to test it, but I think your issues are steming from an incorrect hWnd somehow. Anyway, on with the poorly commented code.
// The state of our little button
ButtonState _buttState = ButtonState.Normal;
Rectangle _buttPosition = new Rectangle();
[DllImport("user32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int GetWindowRect(IntPtr hWnd,
ref Rectangle lpRect);
[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
protected override void WndProc(ref Message m)
{
int x, y;
Rectangle windowRect = new Rectangle();
GetWindowRect(m.HWnd, ref windowRect);
switch (m.Msg)
{
// WM_NCPAINT
case 0x85:
// WM_PAINT
case 0x0A:
base.WndProc(ref m);
DrawButton(m.HWnd);
m.Result = IntPtr.Zero;
break;
// WM_ACTIVATE
case 0x86:
base.WndProc(ref m);
DrawButton(m.HWnd);
break;
// WM_NCMOUSEMOVE
case 0xA0:
// Extract the least significant 16 bits
x = ((int)m.LParam << 16) >> 16;
// Extract the most significant 16 bits
y = (int)m.LParam >> 16;
x -= windowRect.Left;
y -= windowRect.Top;
base.WndProc(ref m);
if (!_buttPosition.Contains(new Point(x, y)) &&
_buttState == ButtonState.Pushed)
{
_buttState = ButtonState.Normal;
DrawButton(m.HWnd);
}
break;
// WM_NCLBUTTONDOWN
case 0xA1:
// Extract the least significant 16 bits
x = ((int)m.LParam << 16) >> 16;
// Extract the most significant 16 bits
y = (int)m.LParam >> 16;
x -= windowRect.Left;
y -= windowRect.Top;
if (_buttPosition.Contains(new Point(x, y)))
{
_buttState = ButtonState.Pushed;
DrawButton(m.HWnd);
}
else
base.WndProc(ref m);
break;
// WM_NCLBUTTONUP
case 0xA2:
// Extract the least significant 16 bits
x = ((int)m.LParam << 16) >> 16;
// Extract the most significant 16 bits
y = (int)m.LParam >> 16;
x -= windowRect.Left;
y -= windowRect.Top;
if (_buttPosition.Contains(new Point(x, y)) &&
_buttState == ButtonState.Pushed)
{
_buttState = ButtonState.Normal;
// [[TODO]]: Fire a click event for your button
// however you want to do it.
DrawButton(m.HWnd);
}
else
base.WndProc(ref m);
break;
// WM_NCHITTEST
case 0x84:
// Extract the least significant 16 bits
x = ((int)m.LParam << 16) >> 16;
// Extract the most significant 16 bits
y = (int)m.LParam >> 16;
x -= windowRect.Left;
y -= windowRect.Top;
if (_buttPosition.Contains(new Point(x, y)))
m.Result = (IntPtr)18; // HTBORDER
else
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
private void DrawButton(IntPtr hwnd)
{
IntPtr hDC = GetWindowDC(hwnd);
int x, y;
using (Graphics g = Graphics.FromHdc(hDC))
{
// Work out size and positioning
int CaptionHeight = Bounds.Height - ClientRectangle.Height;
Size ButtonSize = SystemInformation.CaptionButtonSize;
x = Bounds.Width - 4 * ButtonSize.Width;
y = (CaptionHeight - ButtonSize.Height) / 2;
_buttPosition.Location = new Point(x, y);
// Work out color
Brush color;
if (_buttState == ButtonState.Pushed)
color = Brushes.LightGreen;
else
color = Brushes.Red;
// Draw our "button"
g.FillRectangle(color, x, y, ButtonSize.Width, ButtonSize.Height);
}
ReleaseDC(hwnd, hDC);
}
private void Form1_Load(object sender, EventArgs e)
{
_buttPosition.Size = SystemInformation.CaptionButtonSize;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With