protected override void WndProc(ref Message message) { switch (message.Msg) { case WM_COMMAND: { // need to dispatch the message for the context menu if (message.LParam == IntPtr.Zero) commandDispatch.Invoke(null, new object[] { message.WParam.ToInt32() & 0xFFFF }); } break; case WM_NCHITTEST: { message.Result = (IntPtr)HitResult.Caption; if (HitTest != null) { Point p = new Point( Macros.GET_X_LPARAM(message.LParam) - location.X, Macros.GET_Y_LPARAM(message.LParam) - location.Y ); HitTestEventArgs e = new HitTestEventArgs(p, HitResult.Caption); HitTest(this, e); message.Result = (IntPtr)e.HitResult; } } break; case WM_NCLBUTTONDBLCLK: { if (MouseDoubleClick != null) { MouseDoubleClick(this, new MouseEventArgs(MouseButtons.Left, 2, Macros.GET_X_LPARAM(message.LParam) - location.X, Macros.GET_Y_LPARAM(message.LParam) - location.Y, 0)); } message.Result = IntPtr.Zero; } break; case WM_NCRBUTTONDOWN: { message.Result = IntPtr.Zero; } break; case WM_NCRBUTTONUP: { if (contextMenu != null) ShowContextMenu(new Point( Macros.GET_X_LPARAM(message.LParam), Macros.GET_Y_LPARAM(message.LParam) )); message.Result = IntPtr.Zero; } break; case WM_WINDOWPOSCHANGING: { WindowPos wp = (WindowPos)Marshal.PtrToStructure( message.LParam, typeof(WindowPos)); if (!lockPositionAndSize) { // prevent the window from leaving the screen if ((wp.flags & SWP_NOMOVE) == 0) { Rectangle rect = Screen.GetWorkingArea( new Rectangle(wp.x, wp.y, wp.cx, wp.cy)); const int margin = 16; wp.x = Math.Max(wp.x, rect.Left - wp.cx + margin); wp.x = Math.Min(wp.x, rect.Right - margin); wp.y = Math.Max(wp.y, rect.Top - wp.cy + margin); wp.y = Math.Min(wp.y, rect.Bottom - margin); } // update location and fire event if ((wp.flags & SWP_NOMOVE) == 0) { if (location.X != wp.x || location.Y != wp.y) { location = new Point(wp.x, wp.y); if (LocationChanged != null) LocationChanged(this, EventArgs.Empty); } } // update size and fire event if ((wp.flags & SWP_NOSIZE) == 0) { if (size.Width != wp.cx || size.Height != wp.cy) { size = new Size(wp.cx, wp.cy); if (SizeChanged != null) SizeChanged(this, EventArgs.Empty); } } // update the size of the layered window if ((wp.flags & SWP_NOSIZE) == 0) { NativeMethods.UpdateLayeredWindow(Handle, IntPtr.Zero, IntPtr.Zero, ref size, IntPtr.Zero, IntPtr.Zero, 0, IntPtr.Zero, 0); } // update the position of the layered window if ((wp.flags & SWP_NOMOVE) == 0) { NativeMethods.SetWindowPos(Handle, IntPtr.Zero, location.X, location.Y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSENDCHANGING); } } // do not forward any move or size messages wp.flags |= SWP_NOSIZE | SWP_NOMOVE; // suppress any frame changed events wp.flags &= ~SWP_FRAMECHANGED; Marshal.StructureToPtr(wp, message.LParam, false); message.Result = IntPtr.Zero; } break; default: { base.WndProc(ref message); } break; } }