void StartPeekMessageLoop() { // Create an object for storing windows message information Win32.MSG msg = new Win32.MSG(); bool leaveMsg = false; // Process messages until exit condition recognised while(!exitLoop) { // Suspend thread until a windows message has arrived if (WindowsAPI.WaitMessage()) { // Take a peek at the message details without removing from queue while(!exitLoop && WindowsAPI.PeekMessage(ref msg, 0, 0, 0, (int)Win32.PeekMessageFlags.PM_NOREMOVE)) { //Console.WriteLine("Track {0} {1}", this.Handle, ((Msg)msg.message).ToString()); //Console.WriteLine("Message is for {0 }", msg.hwnd); // Mouse was pressed in a window of this application if ((msg.message == (int)Msg.WM_LBUTTONDOWN) || (msg.message == (int)Msg.WM_MBUTTONDOWN) || (msg.message == (int)Msg.WM_RBUTTONDOWN) || (msg.message == (int)Msg.WM_NCLBUTTONDOWN) || (msg.message == (int)Msg.WM_NCMBUTTONDOWN) || (msg.message == (int)Msg.WM_NCRBUTTONDOWN)) { // Is the mouse event for this popup window? if (msg.hwnd != this.Handle && !IsChild(msg.hwnd) ) { // No, then we need to exit the popup menu tracking exitLoop = true; // DO NOT process the message, leave it on the queue // and let the real destination window handle it. leaveMsg = true; } } else { // Mouse move occured if ( msg.message == (int)Msg.WM_MOUSEMOVE ) { // Is the mouse event for this popup window? if ((msg.hwnd != this.Handle && !IsChild(msg.hwnd)) ) { // Eat the message to prevent the destination getting it Win32.MSG eat = new Win32.MSG(); WindowsAPI.GetMessage(ref eat, 0, 0, 0); // Do not attempt to pull a message off the queue as it has already // been eaten by us in the above code leaveMsg = true; } } } // Should the message we pulled from the queue? if (!leaveMsg) { if (WindowsAPI.GetMessage(ref msg, 0, 0, 0)) { WindowsAPI.TranslateMessage(ref msg); WindowsAPI.DispatchMessage(ref msg); } } else leaveMsg = false; } } } }
void ProcessItemHit(int index, Point pt) { bool itemPressed = true; Capture = true; using (Graphics g = Graphics.FromHwnd(Handle)) { Rectangle itemRect = GetItemRect(g, bands[currentBandIndex], index, Rectangle.Empty); DrawItem(g, index, itemRect, true, true, Rectangle.Empty, null); bool dragging = false; int deltaX = 0; int deltaY = 0; bool itemHighlighted = false; int dragItemIndex = -1; bool doLoop = true; while (doLoop) { // Check messages until we find a condition to break out of the loop Win32.MSG msg = new Win32.MSG(); WindowsAPI.GetMessage(ref msg, 0, 0, 0); Point point = new Point(0, 0); if (msg.message == (int)Msg.WM_MOUSEMOVE || msg.message == (int)Msg.WM_LBUTTONUP) { point = WindowsAPI.GetPointFromLPARAM((int)msg.lParam); if (msg.message == (int)Msg.WM_MOUSEMOVE) { deltaX = pt.X - point.X; deltaY = pt.Y - point.Y; } } switch (msg.message) { case (int)Msg.WM_MOUSEMOVE: { int currentIndex; HitTestType hit = HitTest(point, out currentIndex, dragging); if (dragging) { if (hit == HitTestType.DropLine || hit == HitTestType.DropLineLastItem) { Cursor.Current = dragCursor; // Draw the Dragline DrawDropLine(g, currentIndex, true, hit); } else { Cursor.Current = Cursors.No; // Erase the Dragline DrawDropLine(g, index, false, hit); } if (hit == HitTestType.Item && currentIndex == index) { if (itemHighlighted == false) { DrawItem(g, index, itemRect, true, false, Rectangle.Empty, null); itemHighlighted = true; } } else { if (hit == HitTestType.Item) { // Erase previous highlighting first if (itemHighlighted) { DrawItem(g, index, itemRect, false, false, Rectangle.Empty, null); } // Highlight new item itemRect = GetItemRect(g, bands[currentBandIndex], currentIndex, Rectangle.Empty); index = currentIndex; DrawItem(g, index, itemRect, true, false, Rectangle.Empty, null); } else { // the mouse did not hit an item if (itemHighlighted) { DrawItem(g, index, itemRect, false, false, Rectangle.Empty, null); itemHighlighted = false; } } } } else { if (hit == HitTestType.Item && currentIndex == index) { // Set no drag cursor if there have been at least // a 5 pixel movement int pixelmov = 5; if (bands[currentBandIndex].IconView == IconView.Small) pixelmov = 2; bool unpressed = false; if (Math.Abs(deltaX) >= pixelmov || Math.Abs(deltaY) >= pixelmov) { unpressed = true; Cursor.Current = Cursors.No; dragging = true; dragItemIndex = index; } if (itemPressed && unpressed) { DrawItem(g, index, itemRect, true, false, Rectangle.Empty, null); itemPressed = false; itemHighlighted = true; } } } break; } case (int)Msg.WM_LBUTTONUP: { // Highlight the item if (itemPressed) { DrawItem(g, index, itemRect, true, false, Rectangle.Empty, null); itemPressed = false; } int newIndex; HitTestType ht = HitTest(point, out newIndex, true); bool doDrop = false; if (dragging && (ht == HitTestType.DropLine || ht == HitTestType.DropLineLastItem)) { // Delete dropline Cursor.Current = Cursors.Default; // Erase the Dragline DrawDropLine(g, index, false, ht); // Move the dragged item to the new location // only if the new location is not contiguous to its // own location if (dragItemIndex > droppedPosition && Math.Abs(dragItemIndex - droppedPosition) > 0) doDrop = true; else if (dragItemIndex < droppedPosition && Math.Abs(dragItemIndex - droppedPosition) > 1) doDrop = true; if (doDrop) { // Remove item from its old location OutlookBarItem dragItem = bands[currentBandIndex].Items[dragItemIndex]; bands[currentBandIndex].Items.RemoveAt(dragItemIndex); // Insert item in its new location if (dragItemIndex < droppedPosition) droppedPosition--; bands[currentBandIndex].Items.Insert(droppedPosition, dragItem); } } // Repaint the bar just in case we had a dropline painted Invalidate(); // Highlight item if (!dragging) { // do not highlight if we are dropping forceHightlight = true; forceHightlightIndex = index; // Fire item clicked property FireItemClicked(index); } else { // Fire item dropped event if (droppedPosition != -1 && doDrop) FireItemDropped(droppedPosition); } doLoop = false; break; } case (int)Msg.WM_KEYDOWN: { if ((int)msg.wParam == (int)VirtualKeys.VK_ESCAPE) doLoop = false; break; } default: WindowsAPI.DispatchMessage(ref msg); break; } } } Capture = false; }
protected void SimulateGrabFocus() { if (!_manualFocus) { _manualFocus = true; _animateFirst = true; Form parentForm = this.FindForm(); // Want notification when user selects a different Form parentForm.Deactivate += new EventHandler(OnParentDeactivate); // Must hide caret so user thinks focus has changed bool hideCaret = User32.HideCaret(IntPtr.Zero); // Create an object for storing windows message information Win32.MSG msg = new Win32.MSG(); _exitLoop = false; // Process messages until exit condition recognised while(!_exitLoop) { // Suspend thread until a windows message has arrived if (User32.WaitMessage()) { // Take a peek at the message details without removing from queue while(!_exitLoop && User32.PeekMessage(ref msg, 0, 0, 0, (int)Win32.PeekMessageFlags.PM_NOREMOVE)) { // Console.WriteLine("Loop {0} {1}", this.Handle, ((Win32.Msgs)msg.message).ToString()); if (User32.GetMessage(ref msg, 0, 0, 0)) { // Should this method be dispatched? if (!ProcessInterceptedMessage(ref msg)) { User32.TranslateMessage(ref msg); User32.DispatchMessage(ref msg); } } } } } // Remove notification when user selects a different Form parentForm.Deactivate -= new EventHandler(OnParentDeactivate); // If caret was hidden then show it again now if (hideCaret) User32.ShowCaret(IntPtr.Zero); // We lost the focus _manualFocus = false; } }
void ProcessArrowScrolling(Rectangle arrowButton, ref bool arrowVisible, ref bool arrowPressed, ref bool timerTicking) { // Capture the mouse Capture = true; // Draw the arrow button pushed timerTicking = true; // Draw pushed button buttonPushed = true; DrawArrowButton(arrowButton, ButtonState.Pushed); // Start timer using (System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer()) { timer.Tick += new EventHandler(ScrollingTick); timer.Interval = 300; timer.Start(); doScrollingLoop = true; while (doScrollingLoop) { // Check messages until we find a condition to break out of the loop Win32.MSG msg = new Win32.MSG(); WindowsAPI.GetMessage(ref msg, 0, 0, 0); Point point = new Point(0, 0); if (msg.message == (int)Msg.WM_MOUSEMOVE || msg.message == (int)Msg.WM_LBUTTONUP) { point = WindowsAPI.GetPointFromLPARAM((int)msg.lParam); } switch (msg.message) { case (int)Msg.WM_MOUSEMOVE: { if (arrowButton.Contains(point)) { if (!buttonPushed) { DrawArrowButton(arrowButton, ButtonState.Pushed); arrowVisible = true; arrowPressed = true; buttonPushed = true; } } else { if (buttonPushed) { DrawArrowButton(arrowButton, ButtonState.Normal); arrowVisible = false; arrowPressed = false; buttonPushed = false; } } break; } case (int)Msg.WM_LBUTTONUP: { if (buttonPushed) { if (!flatArrowButtons) { // Only if using regular buttons DrawArrowButton(arrowButton, ButtonState.Normal); } buttonPushed = false; } arrowVisible = false; if (arrowButton.Contains(point)) { if (arrowButton.Equals(upArrowRect)) { if (firstItem > 0) { firstItem--; Rectangle rc = GetViewPortRect(); Invalidate(rc); } } else if (arrowButton.Equals(downArrowRect)) { using (Graphics g = Graphics.FromHwnd(Handle)) { // Get the last item rectangle OutlookBarBand band = bands[currentBandIndex]; if (band != null) { Rectangle rcItem = GetItemRect(g, band, band.Items.Count - 1, Rectangle.Empty); Rectangle rc = GetViewPortRect(); if (rcItem.Bottom > rc.Bottom) { firstItem++; Invalidate(rc); } } } } } doScrollingLoop = false; break; } case (int)Msg.WM_KEYDOWN: { if ((int)msg.wParam == (int)VirtualKeys.VK_ESCAPE) doScrollingLoop = false; break; } default: WindowsAPI.DispatchMessage(ref msg); break; } } // Release the capture Capture = false; // Stop timer timer.Stop(); } // Reset flags arrowVisible = false; arrowPressed = false; timerTicking = false; Rectangle viewPortRect = GetViewPortRect(); Invalidate(viewPortRect); }
void ProcessHeaderHit(int index) { Capture = true; Rectangle rc = GetHeaderRect(index); // Draw header pressed using (Graphics g = Graphics.FromHwnd(Handle)) { DrawHeader(g, index, rc, Border3DStyle.Sunken); #if !__MonoCS__ bool headerPressed = true; bool doLoop = true; while (doLoop) { // Check messages until we find a condition to break out of the loop Win32.MSG msg = new Win32.MSG(); WindowsAPI.GetMessage(ref msg, 0, 0, 0); Point point = new Point(0,0); if ( msg.message == (int)Msg.WM_MOUSEMOVE || msg.message == (int)Msg.WM_LBUTTONUP ) { point = WindowsAPI.GetPointFromLPARAM((int)msg.lParam); } switch(msg.message) { case (int)Msg.WM_MOUSEMOVE: { int currentIndex; HitTestType hit = HitTest(point, out currentIndex, false); if (hit == HitTestType.Header && currentIndex == index) { if (!headerPressed) { DrawHeader(g, index, rc, Border3DStyle.Sunken); headerPressed = true; } } else { if (headerPressed) { DrawHeader(g, index, rc, Border3DStyle.RaisedInner); headerPressed = false; } } break; } case (int)Msg.WM_LBUTTONUP: { if (headerPressed) { DrawHeader(g, index, rc, Border3DStyle.RaisedInner); headerPressed = false; } int newIndex; HitTestType ht = HitTest(point, out newIndex, false); if ( ht == HitTestType.Header && newIndex != selectedHeader ) SetCurrentBand(newIndex); doLoop = false; break; } case (int)Msg.WM_KEYDOWN: { if ( (int)msg.wParam == (int)VirtualKeys.VK_ESCAPE) doLoop = false; break; } default: WindowsAPI.DispatchMessage(ref msg); break; } } #else // TODO-Linux: Windows dependant code. #endif // Reset flags Capture = false; } }
protected bool ProcessKeyRight() { // Are we the first submenu of a parent control? bool autoRight = (_parentControl != null); bool checkKeys = false; bool ret = false; // Is an item currently selected? if (_trackItem != -1) { DrawCommand dc = _drawCommands[_trackItem] as DrawCommand; // Does this item have a submenu? if (dc.SubMenu) { // Consume the keyboard message to prevent the submenu immediately // processing the same message again. Remember this routine is called // after PeekMessage but the message is still on the queue at this point Win32.MSG msg = new Win32.MSG(); WindowsAPI.GetMessage(ref msg, 0, 0, 0); // Handle the submenu OperateSubMenu(_trackItem, true); ret = true; } else { // Grab the current column/row values int col = dc.Col; int row = dc.Row; // If not in the first column then move left one int newItem = -1; int newRow = -1; int findCol = col + 1; DrawCommand newDc = null; for(int i=0; i<_drawCommands.Count; i++) { DrawCommand listDc = _drawCommands[i] as DrawCommand; // Interesting in cells in the required column if (listDc.Col == findCol) { // Is this Row nearer to the one required than those found so far? if ((listDc.Row <= row) && (listDc.Row > newRow) && !listDc.Separator && listDc.Enabled) { // Remember this item newRow = listDc.Row; newDc = listDc; newItem = i; } } } if (newDc != null) { // Track the new item // Modify the display of the two items SwitchSelection(_trackItem, newItem, false, false); } else checkKeys = true; } } else { if (_parentMenu != null) { if (!ProcessKeyDown()) checkKeys = true; } else checkKeys = true; } // If we have a parent control and nothing to move right into if (autoRight && checkKeys) { _returnCommand = null; // Finish processing messages _timer.Stop(); _exitLoop = true; _returnDir = 1; } return ret; }
protected MenuCommand InternalTrackPopup(bool selectFirst) { // MenuCommand to return as method result _returnCommand = null; // No item is being tracked _trackItem = -1; // Flag to indicate when to exit the message loop _exitLoop = false; // Assume the mouse does not start over our window _mouseOver = false; // Direction of key press if this caused dismissal _returnDir = 0; // Flag to indicate if the message should be dispatched bool leaveMsg = false; // Create and show the popup window (without taking the focus) CreateAndShowWindow(); // Create an object for storing windows message information Win32.MSG msg = new Win32.MSG(); // Draw everything now... //RefreshAllCommands(); // Pretend user pressed key down to get the first valid item selected if (selectFirst) ProcessKeyDown(); // Process messages until exit condition recognised while(!_exitLoop) { // Suspend thread until a windows message has arrived if (WindowsAPI.WaitMessage()) { // Take a peek at the message details without removing from queue while(!_exitLoop && WindowsAPI.PeekMessage(ref msg, 0, 0, 0, (int)Win32.PeekMessageFlags.PM_NOREMOVE)) { //Console.WriteLine("Track {0} {1}", this.Handle, ((Msg)msg.message).ToString()); //Console.WriteLine("Message is for {0 }", msg.hwnd); // Leave messages for children IntPtr hParent = WindowsAPI.GetParent(msg.hwnd); bool child = hParent == Handle; bool combolist = IsComboBoxList(msg.hwnd); // Mouse was pressed in a window of this application if ((msg.message == (int)Msg.WM_LBUTTONDOWN) || (msg.message == (int)Msg.WM_MBUTTONDOWN) || (msg.message == (int)Msg.WM_RBUTTONDOWN) || (msg.message == (int)Msg.WM_NCLBUTTONDOWN) || (msg.message == (int)Msg.WM_NCMBUTTONDOWN) || (msg.message == (int)Msg.WM_NCRBUTTONDOWN)) { // Is the mouse event for this popup window? if (msg.hwnd != this.Handle) { // Let the parent chain of PopupMenu's decide if they want it if (!ParentWantsMouseMessage(ref msg)&& !child && !combolist) { // No, then we need to exit the popup menu tracking _exitLoop = true; // DO NOT process the message, leave it on the queue // and let the real destination window handle it. leaveMsg = true; // Is a parent control specified? if (_parentControl != null) { // Is the mouse event destination the parent control? if (msg.hwnd == _parentControl.Handle) { // Then we want to consume the message so it does not get processed // by the parent control. Otherwise, pressing down will cause this // popup to disappear but the message will then get processed by // the parent and cause a popup to reappear again. When we actually // want the popup to disappear and nothing more. leaveMsg = false; } } } } } else { // Mouse move occured if (msg.message == (int)Msg.WM_MOUSEMOVE) { // Is the mouse event for this popup window? if (msg.hwnd != this.Handle) { // Do we still think the mouse is over our window? if (_mouseOver) { // Process mouse leaving situation OnWM_MOUSELEAVE(); } // Let the parent chain of PopupMenu's decide if they want it if (!ParentWantsMouseMessage(ref msg) && !child && !combolist) { // Eat the message to prevent the destination getting it Win32.MSG eat = new Win32.MSG(); WindowsAPI.GetMessage(ref eat, 0, 0, 0); // Do not attempt to pull a message off the queue as it has already // been eaten by us in the above code leaveMsg = true; } } } else { // Was the alt key pressed? if (msg.message == (int)Msg.WM_SYSKEYDOWN) { // Alt key pressed on its own if((int)msg.wParam == (int)Win32.VirtualKeys.VK_MENU) // ALT key { // Then we should dimiss ourself _exitLoop = true; } } // Was a key pressed? if (msg.message == (int)Msg.WM_KEYDOWN) { switch((int)msg.wParam) { case (int)Win32.VirtualKeys.VK_UP: ProcessKeyUp(); break; case (int)Win32.VirtualKeys.VK_DOWN: ProcessKeyDown(); break; case (int)Win32.VirtualKeys.VK_LEFT: ProcessKeyLeft(); break; case (int)Win32.VirtualKeys.VK_RIGHT: if(ProcessKeyRight()) { // Do not attempt to pull a message off the queue as the // ProcessKeyRight has eaten the message for us leaveMsg = true; } break; case (int)Win32.VirtualKeys.VK_RETURN: // Is an item currently selected if (_trackItem != -1) { DrawCommand dc = _drawCommands[_trackItem] as DrawCommand; // Does this item have a submenu? if (dc.SubMenu) { // Consume the keyboard message to prevent the submenu immediately // processing the same message again. Remember this routine is called // after PeekMessage but the message is still on the queue at this point Win32.MSG eat = new Win32.MSG(); WindowsAPI.GetMessage(ref eat, 0, 0, 0); // Handle the submenu OperateSubMenu(_trackItem, false); // Do not attempt to pull a message off the queue as it has already // been eaten by us in the above code leaveMsg = true; } else { // Is this item the expansion command? if (dc.Expansion) { RegenerateExpansion(); } else { // Define the selection to return to caller _returnCommand = dc.MenuCommand; // Finish processing messages _exitLoop = true; } } } break; case (int)Win32.VirtualKeys.VK_ESCAPE: // User wants to exit the menu, so set the flag to exit the message loop but // let the message get processed. This way the key press is thrown away. _exitLoop = true; break; default: // Any other key is treated as a possible mnemonic int selectItem = ProcessMnemonicKey((char)msg.wParam); if (selectItem != -1) { DrawCommand dc = _drawCommands[selectItem] as DrawCommand; // Define the selection to return to caller _returnCommand = dc.MenuCommand; // Finish processing messages _exitLoop = true; } break; } } } } // Should the message we pulled from the queue? if (!leaveMsg) { if (WindowsAPI.GetMessage(ref msg, 0, 0, 0)) { WindowsAPI.TranslateMessage(ref msg); WindowsAPI.DispatchMessage(ref msg); } } else leaveMsg = false; } } } // Do we have a focus we need to restore? if (_oldFocus != IntPtr.Zero) ReturnTheFocus(); // Need to unset this window as the parent of the comboboxes // -- if any -- otherwise the combobox use in an toolbar would get "sick" UnsetComboBoxesParent(); // Hide the window from view before killing it, as sometimes there is a // short delay between killing it and it disappearing because of the time // it takes for the destroy messages to get processed WindowsAPI.ShowWindow(this.Handle, (short)Win32.ShowWindowStyles.SW_HIDE); // Commit suicide DestroyHandle(); // Was a command actually selected? if ((_parentMenu == null) && (_returnCommand != null)) { // Pulse the selected event for the command _returnCommand.OnClick(EventArgs.Empty); } return _returnCommand; }
protected MenuCommand InternalTrackPopup(bool selectFirst) { // MenuCommand to return as method result _returnCommand = null; // No item is being tracked _trackItem = -1; // Flag to indicate when to exit the message loop _exitLoop = false; // Assume the mouse does not start over our window _mouseOver = false; // Direction of key press if this caused dismissal _returnDir = 0; // Flag to indicate if the message should be dispatched bool leaveMsg = false; // First time a submenu is shown we pass in our value _animateFirst = true; // Create and show the popup window (without taking the focus) CreateAndShowWindow(); // Create an object for storing windows message information Win32.MSG msg = new Win32.MSG(); // Pretend user pressed key down to get the first valid item selected if (selectFirst) ProcessKeyDown(); // Always use the arrow cursor User32.SetCursor(User32.LoadCursor(IntPtr.Zero, (uint)Win32.Cursors.IDC_ARROW)); // Must hide caret so user thinks focus has changed bool hideCaret = User32.HideCaret(IntPtr.Zero); // Process messages until exit condition recognised while(!_exitLoop) { // Suspend thread until a windows message has arrived if (User32.WaitMessage()) { // Take a peek at the message details without removing from queue while(!_exitLoop && User32.PeekMessage(ref msg, 0, 0, 0, (int)Win32.PeekMessageFlags.PM_NOREMOVE)) { // Console.WriteLine("Track {0} {1}", this.Handle, ((Win32.Msgs)msg.message).ToString()); bool eatMessage = false; int localWidth = _currentSize.Width - _position[(int)_style, (int)PI.ShadowWidth]; int localHeight = _currentSize.Height - _position[(int)_style, (int)PI.ShadowHeight]; // Mouse was pressed in a window of this application if ((msg.message == (int)Win32.Msgs.WM_LBUTTONUP) || (msg.message == (int)Win32.Msgs.WM_MBUTTONUP) || (msg.message == (int)Win32.Msgs.WM_RBUTTONUP) || (msg.message == (int)Win32.Msgs.WM_XBUTTONUP) || (msg.message == (int)Win32.Msgs.WM_NCLBUTTONUP) || (msg.message == (int)Win32.Msgs.WM_NCMBUTTONUP) || (msg.message == (int)Win32.Msgs.WM_NCRBUTTONUP) || (msg.message == (int)Win32.Msgs.WM_NCXBUTTONUP)) { Win32.POINT screenPos = MousePositionToScreen(msg); // Is the POINT inside the Popup window rectangle if ((screenPos.x >= _currentPoint.X) && (screenPos.x <= (_currentPoint.X + localWidth)) && (screenPos.y >= _currentPoint.Y) && (screenPos.y <= (_currentPoint.Y + localHeight))) { OnWM_YBUTTONUP(screenPos.x, screenPos.y); // Eat the message to prevent the intended destination getting it eatMessage = true; } else { PopupMenu target = ParentPopupMenuWantsMouseMessage(screenPos, ref msg); // Let the parent chain of PopupMenu's decide if they want it if (target != null) { target.OnWM_YBUTTONUP(screenPos.x, screenPos.y); // Eat the message to prevent the intended destination getting it eatMessage = true; } } } // Mouse was pressed in a window of this application if ((msg.message == (int)Win32.Msgs.WM_LBUTTONDOWN) || (msg.message == (int)Win32.Msgs.WM_MBUTTONDOWN) || (msg.message == (int)Win32.Msgs.WM_RBUTTONDOWN) || (msg.message == (int)Win32.Msgs.WM_XBUTTONDOWN) || (msg.message == (int)Win32.Msgs.WM_NCLBUTTONDOWN) || (msg.message == (int)Win32.Msgs.WM_NCMBUTTONDOWN) || (msg.message == (int)Win32.Msgs.WM_NCRBUTTONDOWN) || (msg.message == (int)Win32.Msgs.WM_NCXBUTTONDOWN)) { Win32.POINT screenPos = MousePositionToScreen(msg); // Is the POINT inside the Popup window rectangle if ((screenPos.x >= _currentPoint.X) && (screenPos.x <= (_currentPoint.X + localWidth)) && (screenPos.y >= _currentPoint.Y) && (screenPos.y <= (_currentPoint.Y + localHeight))) { // Eat the message to prevent the intended destination getting it eatMessage = true; } else { // Let the parent chain of PopupMenu's decide if they want it if (ParentPopupMenuWantsMouseMessage(screenPos, ref msg) == null) { if (ParentControlWantsMouseMessage(screenPos, ref msg)) { // Let the MenuControl do its business _parentControl.OnWM_MOUSEDOWN(screenPos); // Eat the message to prevent the intended destination getting it eatMessage = true; } else { // No, then we need to exit the popup menu tracking _exitLoop = true; // DO NOT process the message, leave it on the queue // and let the real destination window handle it. leaveMsg = true; // Is a parent control specified? if (_parentControl != null) { // Is the mouse event destination the parent control? if (msg.hwnd == _parentControl.Handle) { // Then we want to consume the message so it does not get processed // by the parent control. Otherwise, pressing down will cause this // popup to disappear but the message will then get processed by // the parent and cause a popup to reappear again. When we actually // want the popup to disappear and nothing more. leaveMsg = false; } } } } else { // Eat the message to prevent the intended destination getting it eatMessage = true; } } } // Mouse move occured if (msg.message == (int)Win32.Msgs.WM_MOUSEMOVE) { Win32.POINT screenPos = MousePositionToScreen(msg); // Is the POINT inside the Popup window rectangle if ((screenPos.x >= _currentPoint.X) && (screenPos.x <= (_currentPoint.X + localWidth)) && (screenPos.y >= _currentPoint.Y) && (screenPos.y <= (_currentPoint.Y + localHeight))) { OnWM_MOUSEMOVE(screenPos.x, screenPos.y); } else { // Do we still think the mouse is over our window? if (_mouseOver) { // Process mouse leaving situation OnWM_MOUSELEAVE(); } // Let the parent chain of PopupMenu's decide if they want it PopupMenu target = ParentPopupMenuWantsMouseMessage(screenPos, ref msg); if (target != null) { // Let parent target process the message target.OnWM_MOUSEMOVE(screenPos.x, screenPos.y); } else { if (ParentControlWantsMouseMessage(screenPos, ref msg)) { // Let the MenuControl do its business _parentControl.OnWM_MOUSEMOVE(screenPos); } } } // Eat the message to prevent the intended destination getting it eatMessage = true; } if (msg.message == (int)Win32.Msgs.WM_SETCURSOR) { OnWM_SETCURSOR(); // Eat the message to prevent the intended destination getting it eatMessage = true; } // Was the alt key pressed? if (msg.message == (int)Win32.Msgs.WM_SYSKEYDOWN) { // Alt key pressed on its own if((int)msg.wParam == (int)Win32.VirtualKeys.VK_MENU) // ALT key { // Then we should dimiss ourself _exitLoop = true; } else { // Pretend it is a normal keypress for processing msg.message = (int)Win32.Msgs.WM_KEYDOWN; } } // Was a non-alt key pressed? if (msg.message == (int)Win32.Msgs.WM_KEYDOWN) { switch((int)msg.wParam) { case (int)Win32.VirtualKeys.VK_UP: ProcessKeyUp(); break; case (int)Win32.VirtualKeys.VK_DOWN: ProcessKeyDown(); break; case (int)Win32.VirtualKeys.VK_LEFT: ProcessKeyLeft(); break; case (int)Win32.VirtualKeys.VK_RIGHT: if(ProcessKeyRight()) { // Do not attempt to pull a message off the queue as the // ProcessKeyRight has eaten the message for us leaveMsg = true; } break; case (int)Win32.VirtualKeys.VK_RETURN: // Is an item currently selected if (_trackItem != -1) { DrawCommand dc = _drawCommands[_trackItem] as DrawCommand; // Does this item have a submenu? if (dc.SubMenu) { // Handle the submenu OperateSubMenu(_trackItem, false); // Do not attempt to pull a message off the queue as it has already // been eaten by us in the above code leaveMsg = true; } else { // Is this item the expansion command? if (dc.Expansion) { RegenerateExpansion(); } else { // Define the selection to return to caller _returnCommand = dc.MenuCommand; // Finish processing messages _exitLoop = true; } } } break; case (int)Win32.VirtualKeys.VK_ESCAPE: // User wants to exit the menu, so set the flag to exit the message loop but // let the message get processed. This way the key press is thrown away. _exitLoop = true; break; default: // Any other key is treated as a possible mnemonic int selectItem = ProcessMnemonicKey((char)msg.wParam); if (selectItem != -1) { DrawCommand dc = _drawCommands[selectItem] as DrawCommand; // Define the selection to return to caller _returnCommand = dc.MenuCommand; // Finish processing messages _exitLoop = true; // Do not attempt to pull a message off the queue as it has already // been eaten by us in the above code leaveMsg = true; } break; } } // We consume all keyboard input if ((msg.message == (int)Win32.Msgs.WM_KEYDOWN) || (msg.message == (int)Win32.Msgs.WM_KEYUP) || (msg.message == (int)Win32.Msgs.WM_SYSKEYDOWN) || (msg.message == (int)Win32.Msgs.WM_SYSKEYUP)) { // Eat the message to prevent the intended destination getting it eatMessage = true; } // Should the message be eaten to prevent intended destination getting it? if (eatMessage) { Win32.MSG eat = new Win32.MSG(); User32.GetMessage(ref eat, 0, 0, 0); } else { // Should the message we pulled from the queue? if (!leaveMsg) { if (User32.GetMessage(ref msg, 0, 0, 0)) { User32.TranslateMessage(ref msg); User32.DispatchMessage(ref msg); } } else leaveMsg = false; } } } } // If caret was hidden then show it again now if (hideCaret) User32.ShowCaret(IntPtr.Zero); // Remove tracking of any item, this ensure 'Deselected' event is generated if required SwitchSelection(_trackItem, -1, false, false); // Hide the window from view before killing it, as sometimes there is a // short delay between killing it and it disappearing because of the time // it takes for the destroy messages to get processed HideMenuWindow(); // Commit suicide DestroyHandle(); // Was a command actually selected in a top level PopupMenu AND we // are not here at the request of a MenuControl if ((_parentMenu == null) && (_returnCommand != null) && (_parentControl == null)) { // Pulse the selected event for the command _returnCommand.OnClick(EventArgs.Empty); } return _returnCommand; }
/// <summary> /// Abort resetting if the user types anything, anywhere. /// Also sets the flag (if it returns true) to indicate the search WAS aborted. /// </summary> /// <returns></returns> private bool ShouldAbort() { Win32.MSG msg = new Win32.MSG(); if (Win32.PeekMessage(ref msg, IntPtr.Zero, (uint)Win32.WinMsgs.WM_KEYDOWN, (uint)Win32.WinMsgs.WM_KEYDOWN, (uint)Win32.PeekFlags.PM_NOREMOVE)) { m_fResetSearchAborted = true; if (m_resetTimer == null) { m_resetTimer = new System.Windows.Forms.Timer(); m_resetTimer.Interval = 100; // try again in 1/10 second. m_resetTimer.Tick += new EventHandler(m_resetTimer_Tick); m_resetTimer.Start(); } return true; } return false; }
public override IntPtr Call16from32(Machine machine, bool hook, bool dlgproc, ref Win32.MSG msg32, ref Win16.MSG msg16, Func <uint> callback) { // Convert info var info32 = Marshal.PtrToStructure <Win32.MDINEXTMENU>(msg32.lParam); var info16 = info32.Convert(); // Setup message msg16.wParam = msg32.lParam.Loword(); msg16.lParam = machine.SysAlloc(info16); try { // Do it return(BitUtils.DWordToIntPtr(callback())); } finally { // Clean up machine.SysFree(msg16.lParam); } }
public override IntPtr Call16from32(Machine machine, bool hook, bool dlgproc, ref Win32.MSG msg32, ref Win16.MSG msg16, Func <uint> callback) { var di32 = Marshal.PtrToStructure <Win32.DRAWITEMSTRUCT>(msg32.lParam); var di16 = di32.Convert(); var saveSP = machine.sp; try { // NB: This needs to be on stack - Wordzap incorrectly uses near pointer from lParam and won't work // if drawitemstruct is in a different segment (see red bar in Skill -> Handcap, comms options) var ptr = machine.StackAlloc(di16); msg16.wParam = (ushort)msg32.wParam.ToInt32(); msg16.lParam = ptr; var retv = callback(); return((IntPtr)retv); } finally { machine.sp = saveSP; } }
public override uint Call32from16(Machine machine, bool hook, bool dlgproc, ref Win16.MSG msg16, ref Win32.MSG msg32, Func <IntPtr> callback) { var di16 = machine.ReadStruct <Win16.DRAWITEMSTRUCT>(msg16.lParam); unsafe { Win16.DRAWITEMSTRUCT *ptr = &di16; msg32.wParam = (IntPtr)msg16.wParam; msg32.lParam = (IntPtr)ptr; var retv = callback(); return((uint)retv.ToInt32()); } }