protected unsafe override LResult WindowProcedure(WindowHandle window, MessageType message, WParam wParam, LParam lParam) { switch (message) { case MessageType.Create: _baseUnits = Windows.GetDialogBaseUnits(); _btnWidth = _baseUnits.Width * 8; _btnHeight = _baseUnits.Height * 4; // Create the owner-draw pushbuttons _hwndSmaller = Windows.CreateWindow("button", "", WindowStyles.Child | WindowStyles.Visible | (WindowStyles)ButtonStyles.OwnerDrawn, ExtendedWindowStyles.Default, new Rectangle(0, 0, _btnWidth, _btnHeight), window, (MenuHandle)ID_SMALLER, ModuleInstance, IntPtr.Zero); _hwndLarger = Windows.CreateWindow("button", "", WindowStyles.Child | WindowStyles.Visible | (WindowStyles)ButtonStyles.OwnerDrawn, ExtendedWindowStyles.Default, new Rectangle(0, 0, _btnWidth, _btnHeight), window, (MenuHandle)ID_LARGER, ModuleInstance, IntPtr.Zero); return(0); case MessageType.Size: _cxClient = lParam.LowWord; _cyClient = lParam.HighWord; // Move the buttons to the new center _hwndSmaller.MoveWindow( new Rectangle(_cxClient / 2 - 3 * _btnWidth / 2, _cyClient / 2 - _btnHeight / 2, _btnWidth, _btnHeight), repaint: true); _hwndLarger.MoveWindow( new Rectangle(_cxClient / 2 + _btnWidth / 2, _cyClient / 2 - _btnHeight / 2, _btnWidth, _btnHeight), repaint: true); return(0); case MessageType.Command: Rectangle rc = window.GetWindowRectangle(); // Make the window 10% smaller or larger switch ((int)(uint)wParam) { case ID_SMALLER: rc.Inflate(rc.Width / -10, rc.Height / -10); break; case ID_LARGER: rc.Inflate(rc.Width / 10, rc.Height / 10); break; } window.MoveWindow(new Rectangle(rc.Left, rc.Top, rc.Right - rc.Left, rc.Bottom - rc.Top), repaint: true); return(0); case MessageType.DrawItem: DRAWITEMSTRUCT *pdis = (DRAWITEMSTRUCT *)lParam; // Fill area with white and frame it black using (DeviceContext dc = new DeviceContext(pdis->hDC)) { Rectangle rect = pdis->rcItem; dc.FillRectangle(rect, StockBrush.White); dc.FrameRectangle(rect, StockBrush.Black); // Draw inward and outward black triangles int cx = rect.Right - rect.Left; int cy = rect.Bottom - rect.Top; Point[] pt = new Point[3]; switch ((int)pdis->CtlID) { case ID_SMALLER: pt[0].X = 3 * cx / 8; pt[0].Y = 1 * cy / 8; pt[1].X = 5 * cx / 8; pt[1].Y = 1 * cy / 8; pt[2].X = 4 * cx / 8; pt[2].Y = 3 * cy / 8; Triangle(dc, pt); pt[0].X = 7 * cx / 8; pt[0].Y = 3 * cy / 8; pt[1].X = 7 * cx / 8; pt[1].Y = 5 * cy / 8; pt[2].X = 5 * cx / 8; pt[2].Y = 4 * cy / 8; Triangle(dc, pt); pt[0].X = 5 * cx / 8; pt[0].Y = 7 * cy / 8; pt[1].X = 3 * cx / 8; pt[1].Y = 7 * cy / 8; pt[2].X = 4 * cx / 8; pt[2].Y = 5 * cy / 8; Triangle(dc, pt); pt[0].X = 1 * cx / 8; pt[0].Y = 5 * cy / 8; pt[1].X = 1 * cx / 8; pt[1].Y = 3 * cy / 8; pt[2].X = 3 * cx / 8; pt[2].Y = 4 * cy / 8; Triangle(dc, pt); break; case ID_LARGER: pt[0].X = 5 * cx / 8; pt[0].Y = 3 * cy / 8; pt[1].X = 3 * cx / 8; pt[1].Y = 3 * cy / 8; pt[2].X = 4 * cx / 8; pt[2].Y = 1 * cy / 8; Triangle(dc, pt); pt[0].X = 5 * cx / 8; pt[0].Y = 5 * cy / 8; pt[1].X = 5 * cx / 8; pt[1].Y = 3 * cy / 8; pt[2].X = 7 * cx / 8; pt[2].Y = 4 * cy / 8; Triangle(dc, pt); pt[0].X = 3 * cx / 8; pt[0].Y = 5 * cy / 8; pt[1].X = 5 * cx / 8; pt[1].Y = 5 * cy / 8; pt[2].X = 4 * cx / 8; pt[2].Y = 7 * cy / 8; Triangle(dc, pt); pt[0].X = 3 * cx / 8; pt[0].Y = 3 * cy / 8; pt[1].X = 3 * cx / 8; pt[1].Y = 5 * cy / 8; pt[2].X = 1 * cx / 8; pt[2].Y = 4 * cy / 8; Triangle(dc, pt); break; } // Invert the rectangle if the button is selected if ((pdis->itemState & OwnerDrawStates.Selected) != 0) { dc.InvertRectangle(rect); } if ((pdis->itemState & OwnerDrawStates.Focus) != 0) { rect = Rectangle.FromLTRB( rect.Left + cx / 16, rect.Top + cy / 16, rect.Right - cx / 16, rect.Bottom - cy / 16); dc.DrawFocusRectangle(rect); } } return(0); } return(base.WindowProcedure(window, message, wParam, lParam)); }
public static unsafe void ReflectMessage(ref Message msg, out bool handled) { IntPtr hWndChild = IntPtr.Zero; if (msg.MessageId == WindowMessages.WM_COMMAND) { if (msg.LParam != IntPtr.Zero) { hWndChild = msg.LParam; } } else if (msg.MessageId == WindowMessages.WM_NOTIFY) { NMHDR *header = (NMHDR *)msg.LParam; hWndChild = header->hWndFrom; } else if (msg.MessageId == WindowMessages.WM_PARENTNOTIFY) { uint submessage = (uint)((int)msg.WParam & 0xFFFF); if (submessage == WindowMessages.WM_CREATE || submessage == WindowMessages.WM_DESTROY) { hWndChild = msg.LParam; } else { int controlId = ((int)msg.WParam >> 16) & 0xFFFF; hWndChild = NativeMethods.GetDlgItem(msg.TargetHandle, controlId); } } else if (msg.MessageId == WindowMessages.WM_DRAWITEM) { if (msg.WParam != IntPtr.Zero) { DRAWITEMSTRUCT *drawItemStruct = (DRAWITEMSTRUCT *)msg.WParam; hWndChild = drawItemStruct->hwndItem; } } else if (msg.MessageId == WindowMessages.WM_MEASUREITEM) { if (msg.WParam != IntPtr.Zero) { MEASUREITEMSTRUCT *measureItemStruct = (MEASUREITEMSTRUCT *)msg.WParam; hWndChild = NativeMethods.GetDlgItem(msg.TargetHandle, (int)measureItemStruct->CtlID); } } else if (msg.MessageId == WindowMessages.WM_COMPAREITEM) { if (msg.WParam != IntPtr.Zero) { COMPAREITEMSTRUCT *compareStruct = (COMPAREITEMSTRUCT *)msg.WParam; hWndChild = compareStruct->hwndItem; } } else if (msg.MessageId == WindowMessages.WM_DELETEITEM) { if (msg.WParam != IntPtr.Zero) { DELETEITEMSTRUCT *deleteStruct = (DELETEITEMSTRUCT *)msg.WParam; hWndChild = deleteStruct->hwndItem; } } else if (msg.MessageId == WindowMessages.WM_VKEYTOITEM || msg.MessageId == WindowMessages.WM_CHARTOITEM || msg.MessageId == WindowMessages.WM_HSCROLL || msg.MessageId == WindowMessages.WM_VSCROLL) { hWndChild = msg.LParam; } else if (msg.MessageId == WindowMessages.WM_CTLCOLORBTN || msg.MessageId == WindowMessages.WM_CTLCOLORDLG || msg.MessageId == WindowMessages.WM_CTLCOLOREDIT || msg.MessageId == WindowMessages.WM_CTLCOLORMSGBOX || msg.MessageId == WindowMessages.WM_CTLCOLORMSGBOX || msg.MessageId == WindowMessages.WM_CTLCOLORSCROLLBAR || msg.MessageId == WindowMessages.WM_CTLCOLORSTATIC) { hWndChild = msg.LParam; } if (hWndChild == IntPtr.Zero) { handled = false; return; } if (!NativeMethods.IsWindow(hWndChild)) { throw new InvalidOperationException("hwndChild not a valid HWND"); } // This code relies on the fact that NativeMethods.GetProp() returns IntPtr.Zero // if the property has not been set. This code only cares if the handled flag // was set to true. If the flag is false, this code behaves the same as if // SetReflectedMessageHandled() was never called at all. NativeMethods.RemoveProp(hWndChild, HandledProperty); // clear it out, just in case IntPtr result = NativeMethods.SendMessage(hWndChild, msg.MessageId + WM_REFLECTED_MESSAGE_BASE, msg.WParam, msg.LParam); handled = NativeMethods.GetProp(hWndChild, HandledProperty) != IntPtr.Zero; NativeMethods.RemoveProp(hWndChild, HandledProperty); if (handled) { msg.Result = result; } }
static unsafe LRESULT WindowProcedure(WindowHandle window, WindowMessage message, WPARAM wParam, LPARAM lParam) { switch (message) { case WindowMessage.Create: baseUnits = Windows.GetDialogBaseUnits(); btnWidth = baseUnits.cx * 8; btnHeight = baseUnits.cy * 4; // Create the owner-draw pushbuttons CREATESTRUCT *create = (CREATESTRUCT *)lParam; hwndSmaller = Windows.CreateWindow("button", "", WindowStyles.Child | WindowStyles.Visible | (WindowStyles)ButtonStyles.OwnerDrawn, ExtendedWindowStyles.None, 0, 0, btnWidth, btnHeight, window, (IntPtr)ID_SMALLER, create->Instance, IntPtr.Zero); hwndLarger = Windows.CreateWindow("button", "", WindowStyles.Child | WindowStyles.Visible | (WindowStyles)ButtonStyles.OwnerDrawn, ExtendedWindowStyles.None, 0, 0, btnWidth, btnHeight, window, (IntPtr)ID_LARGER, create->Instance, IntPtr.Zero); return(0); case WindowMessage.Size: cxClient = lParam.LowWord; cyClient = lParam.HighWord; // Move the buttons to the new center hwndSmaller.MoveWindow(cxClient / 2 - 3 * btnWidth / 2, cyClient / 2 - btnHeight / 2, btnWidth, btnHeight, true); hwndLarger.MoveWindow(cxClient / 2 + btnWidth / 2, cyClient / 2 - btnHeight / 2, btnWidth, btnHeight, true); return(0); case WindowMessage.Command: RECT rc = window.GetWindowRectangle(); // Make the window 10% smaller or larger switch ((int)(uint)wParam) { case ID_SMALLER: rc.left += cxClient / 20; rc.right -= cxClient / 20; rc.top += cyClient / 20; rc.bottom -= cyClient / 20; break; case ID_LARGER: rc.left -= cxClient / 20; rc.right += cxClient / 20; rc.top -= cyClient / 20; rc.bottom += cyClient / 20; break; } window.MoveWindow(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, true); return(0); case WindowMessage.DrawItem: DRAWITEMSTRUCT *pdis = (DRAWITEMSTRUCT *)lParam; // Fill area with white and frame it black using (DeviceContext dc = pdis->DeviceContext) { RECT rect = pdis->rcItem; dc.FillRectangle(rect, StockBrush.White); dc.FrameRectangle(rect, StockBrush.Black); // Draw inward and outward black triangles int cx = rect.right - rect.left; int cy = rect.bottom - rect.top; POINT[] pt = new POINT[3]; switch ((int)pdis->CtlID) { case ID_SMALLER: pt[0].x = 3 * cx / 8; pt[0].y = 1 * cy / 8; pt[1].x = 5 * cx / 8; pt[1].y = 1 * cy / 8; pt[2].x = 4 * cx / 8; pt[2].y = 3 * cy / 8; Triangle(dc, pt); pt[0].x = 7 * cx / 8; pt[0].y = 3 * cy / 8; pt[1].x = 7 * cx / 8; pt[1].y = 5 * cy / 8; pt[2].x = 5 * cx / 8; pt[2].y = 4 * cy / 8; Triangle(dc, pt); pt[0].x = 5 * cx / 8; pt[0].y = 7 * cy / 8; pt[1].x = 3 * cx / 8; pt[1].y = 7 * cy / 8; pt[2].x = 4 * cx / 8; pt[2].y = 5 * cy / 8; Triangle(dc, pt); pt[0].x = 1 * cx / 8; pt[0].y = 5 * cy / 8; pt[1].x = 1 * cx / 8; pt[1].y = 3 * cy / 8; pt[2].x = 3 * cx / 8; pt[2].y = 4 * cy / 8; Triangle(dc, pt); break; case ID_LARGER: pt[0].x = 5 * cx / 8; pt[0].y = 3 * cy / 8; pt[1].x = 3 * cx / 8; pt[1].y = 3 * cy / 8; pt[2].x = 4 * cx / 8; pt[2].y = 1 * cy / 8; Triangle(dc, pt); pt[0].x = 5 * cx / 8; pt[0].y = 5 * cy / 8; pt[1].x = 5 * cx / 8; pt[1].y = 3 * cy / 8; pt[2].x = 7 * cx / 8; pt[2].y = 4 * cy / 8; Triangle(dc, pt); pt[0].x = 3 * cx / 8; pt[0].y = 5 * cy / 8; pt[1].x = 5 * cx / 8; pt[1].y = 5 * cy / 8; pt[2].x = 4 * cx / 8; pt[2].y = 7 * cy / 8; Triangle(dc, pt); pt[0].x = 3 * cx / 8; pt[0].y = 3 * cy / 8; pt[1].x = 3 * cx / 8; pt[1].y = 5 * cy / 8; pt[2].x = 1 * cx / 8; pt[2].y = 4 * cy / 8; Triangle(dc, pt); break; } // Invert the rectangle if the button is selected if ((pdis->itemState & OwnerDrawStates.Selected) != 0) { dc.InvertRectangle(rect); } if ((pdis->itemState & OwnerDrawStates.Focus) != 0) { rect.left += cx / 16; rect.top += cy / 16; rect.right -= cx / 16; rect.bottom -= cy / 16; dc.DrawFocusRectangle(rect); } } return(0); case WindowMessage.Destroy: Windows.PostQuitMessage(0); return(0); } return(Windows.DefaultWindowProcedure(window, message, wParam, lParam)); }
public DrawItem(LParam lParam) { _drawItemStruct = (DRAWITEMSTRUCT *)lParam; }