コード例 #1
0
        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == WinApi.WM_MOUSEMOVE && autoHideCursor)
            {
                Point p = new Point(m.LParam.ToInt32());
                WinApi.ClientToScreen(m.HWnd, ref p);
                if (p != lastMousePoint)
                {
                    lastMousePoint = p;
                    ShowCursor();
                    hideCursorTimer.Reset();
                }
                return(false);                  // Don't block this message
            }
            else if (m.Msg == WinApi.WM_MOUSEWHEEL && dispatchMouseWheel)
            {
                Point p = new Point(m.LParam.ToInt32());

                // First, see whether there's an open combobox list popup that must be handled differently
                WindowProperties prop = new WindowProperties();
                prop.ProcessId = new Window(m.HWnd).ProcessId;
                prop.ClassName = "ComboLBox";
                prop.Visible   = true;
                Window popup;
                if (Window.TryFind(prop, out popup))
                {
                    // Found a combobox popup window, check coordinates
                    if (popup.Rectangle.Contains(p))
                    {
                        // Mouse cursor is over visible combo listbox popup, let the message pass
                        return(false);
                    }
                    // Mouse cursor is outside the popup, block the message
                    // (Do not scroll the popup because the mouse is not in it;
                    // but also do not scroll anything else outside the popup)
                    return(true);
                }

                // Regular window surface: find the deepest control below the mouse cursor
                Control control = Form.ActiveForm;
                while (control != null)
                {
                    Point   clientPoint = control.PointToClient(p);
                    Control subControl  = control.GetChildAtPoint(clientPoint, GetChildAtPointSkip.Invisible);
                    if (subControl == null || subControl is ScrollBar || subControl is ComboBox)
                    {
                        break;
                    }
                    //System.Diagnostics.Debug.WriteLine("Found control in " + control.Name + " at " + clientPoint + ": " + subControl.Name);
                    control = subControl;
                }
                if (control != null)
                {
                    if (control.Handle == m.HWnd)
                    {
                        return(false);                                                // The message already arrived for this control, let it pass
                    }
                    // Search up the parents for a scrollable panel
                    Control c = control;
                    while (!(c is Form))
                    {
                        Panel panel = c as Panel;
                        if (panel != null && panel.AutoScroll)
                        {
                            Point scrollPos = panel.AutoScrollPosition;
                            // Position report is always negative, but new values must be set positive...
                            scrollPos.X = -scrollPos.X;
                            scrollPos.Y = -scrollPos.Y;
                            int delta = m.WParam.ToInt32() >> 16;
                            delta       /= 120;                         // Convert to number of wheel notches
                            scrollPos.Y += -delta * 20;                 // Delta value is "negative" (neg is downwards, pos is upwards)
                            panel.AutoScrollPosition = scrollPos;

                            return(true);                              // Block this message
                        }
                        NumericUpDown numericControl = c as NumericUpDown;
                        if (numericControl != null)
                        {
                            decimal value = numericControl.Value;
                            int     delta = m.WParam.ToInt32() >> 16;
                            delta /= 120;                               // Convert to number of wheel notches
                            value += delta * numericControl.Increment;
                            if (value < numericControl.Minimum)
                            {
                                value = numericControl.Minimum;
                            }
                            if (value > numericControl.Maximum)
                            {
                                value = numericControl.Maximum;
                            }
                            numericControl.Value = value;

                            return(true);                              // Block this message
                        }

                        c = c.Parent;
                    }

                    // NOTE: Possible performance improvement: Flag the re-posted message so that we can
                    //       recognise it faster when it re-arrives here and we can let it pass.
                    //       Use either a very high delta value (HIWORD(wParam)) or one of the modifier
                    //       keys MK_* (LOWORD(wParam)) or an unassigned bit of lParam.

                    //System.Diagnostics.Debug.WriteLine("Re-posting message to " + control.Name);
                    WinApi.PostMessage(control.Handle, WinApi.WM_MOUSEWHEEL, m.WParam, m.LParam);

                    // If IMessageModifyAndFilter wasn't System.Windows.Form's internal, we could just
                    // implement that interface, modify the message and let it pass changed. But so we
                    // need to block the message and send a new one that we're going to let pass then.
                }
                return(true);           // Block this message
            }
            return(false);              // Don't block this message
        }