so I just expanded the glass area of my form into the client area with DwmExtendFrameIntoClientArea (Vista / 7 Aero stuff).
I have already sent a Windows message in the override Form class method OnMouseDown() causing the window to be movable with the glass area, as explained here Make a borderless form movable?.
However because of this, I am not receiving any form Click / MouseClick / DoubleClick etc. events when clicking on the expanded glass area.
I actually want the form to maximize when I double click the top expanded glass area, like normal titlebars do.
Here's the code of the Form-inheriting class:
protected override void OnMouseDown(MouseEventArgs e)
{
// Fensterverschiebung in Glass-Regionen
if (_glassMovable && e.Button == MouseButtons.Left
&& (e.X < _glassPadding.Left || e.X > Width - _glassPadding.Right
|| e.Y < _glassPadding.Top || e.Y > Height - _glassPadding.Bottom))
{
NativeMethods.ReleaseCapture();
NativeMethods.SendMessage(Handle, NativeMethods.WM_NCLBUTTONDOWN,
NativeMethods.HT_CAPTION, 0);
}
base.OnMouseDown(e);
}
protected override void OnMouseDoubleClick(MouseEventArgs e)
{
// Fenstermaximierung / Minimierung in Glass-Regionen
if (MaximizeBox && e.Button == MouseButtons.Left && e.Y < _glassPadding.Top)
{
if (WindowState == FormWindowState.Normal)
{
WindowState = FormWindowState.Maximized;
}
else if (WindowState == FormWindowState.Maximized)
{
WindowState = FormWindowState.Normal;
}
}
base.OnMouseDoubleClick(e);
}
Is there any way to get this to work?
BoltClocks link to a solution for WPF inspired me for the following, similar code for WinForms.
I now override WndProc instead of the OnMouse* events.
The glass region behaves exactly like a title bar, e.g. drag'n'drop with dock support in Windows 7 and double click for maximizing / restoring. Additionally, this solution now supports the system window context menu when right clicking the glass area.
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
private const int WM_NCHITTEST = 0x0084;
private const int WM_NCRBUTTONDOWN = 0x00A4;
private const int WM_SYSCOMMAND = 0x0112;
private const int HT_CAPTION = 0x02;
private const int TPM_RIGHTBUTTON = 0x0002;
private const int TPM_RETURNCMD = 0x0100;
[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
private static extern int TrackPopupMenu(int hMenu, int wFlags, int x, int y,
int nReserved, int hwnd, ref RECT lprc);
[DllImport("user32.dll")]
private static extern int PostMessage(int hWnd, int Msg, int wParam,
int lParam);
protected override void WndProc(ref Message m)
{
if (!DesignMode)
{
switch (m.Msg)
{
case WM_NCHITTEST:
if (MouseInClientArea())
{
if (MouseInGlassArea())
{
m.Result = (IntPtr)HT_CAPTION;
}
else
{
m.Result = IntPtr.Zero;
}
return;
}
break;
case WM_NCRBUTTONDOWN:
if (MouseInClientArea())
{
IntPtr menuHandle = GetSystemMenu(Handle, false);
RECT rect = new RECT();
int menuItem = TrackPopupMenu(menuHandle.ToInt32(),
TPM_RIGHTBUTTON | TPM_RETURNCMD,
Cursor.Position.X, Cursor.Position.Y, 0,
Handle.ToInt32(), ref rect);
if (menuItem != 0)
{
PostMessage(Handle.ToInt32(), WM_SYSCOMMAND,
menuItem, 0);
}
}
break;
}
}
base.WndProc(ref m);
}
private bool MouseInClientArea()
{
Point p = PointToClient(Cursor.Position);
return (p.X > 0 && p.X < ClientRectangle.Width
&& p.Y > 0 && p.Y < ClientRectangle.Height);
}
private bool MouseInGlassArea()
{
if (_glassPadding.Left == -1 || _glassPadding.Right == -1
|| _glassPadding.Top == -1 || _glassPadding.Bottom == -1)
{
return true;
}
else
{
Point p = PointToClient(Cursor.Position);
return (p.X < _glassPadding.Left
|| p.X > ClientRectangle.Width - _glassPadding.Right
|| p.Y < _glassPadding.Top
|| p.Y > ClientRectangle.Height - _glassPadding.Bottom);
}
}