예제 #1
0
        protected override void WndProc(ref Message m)
        {
            if (DesignMode)
            {
                base.WndProc(ref m);
                return;
            }

            switch ((Window.Msg)m.Msg)
            {
            case Window.Msg.WM_NCCALCSIZE:

                // Check WPARAM
                if (m.WParam != IntPtr.Zero)
                {
                    // When TRUE, LPARAM Points to a NCCALCSIZE_PARAMS structure
                    var nccsp = (WinApi.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(WinApi.NCCALCSIZE_PARAMS));
                    ApplyPreferedSize(_preferedSize, nccsp.rectProposed.Size);
                    AdjustClientArea(ref nccsp.rectProposed);
                    Marshal.StructureToPtr(nccsp, m.LParam, true);
                }
                else
                {
                    // When FALSE, LPARAM Points to a RECT structure
                    var clnRect = (WinApi.RECT)Marshal.PtrToStructure(m.LParam, typeof(WinApi.RECT));
                    ApplyPreferedSize(_preferedSize, clnRect.Size);
                    AdjustClientArea(ref clnRect);
                    Marshal.StructureToPtr(clnRect, m.LParam, true);
                }

                //Return Zero
                m.Result = IntPtr.Zero;
                break;

            case Window.Msg.WM_NCPAINT:
                PaintScrollBars(null);
                // we handled everything
                m.Result = IntPtr.Zero;
                break;

            case Window.Msg.WM_NCHITTEST:
                // we need to correctly handle this if we want the non client area events (WM_NC*) to fire properly!
                var point = PointToClient(new Point(m.LParam.ToInt32()));
                if (!ClientRectangle.Contains(point))
                {
                    m.Result = (IntPtr)WinApi.HitTest.HTBORDER;
                }
                else
                {
                    base.WndProc(ref m);
                }

                break;

            case Window.Msg.WM_MOUSEWHEEL:
                if (HasScroll)
                {
                    // delta negative when scrolling up
                    var delta       = (short)(m.WParam.ToInt64() >> 16);
                    var mouseEvent1 = new MouseEventArgs(MouseButtons.None, 0, 0, 0, delta);
                    if (HorizontalScroll.IsHovered)
                    {
                        HorizontalScroll.HandleScroll(null, mouseEvent1);
                    }
                    else
                    {
                        VerticalScroll.HandleScroll(null, mouseEvent1);
                    }
                }
                else
                {
                    // propagate the event
                    base.WndProc(ref m);
                }

                break;

            case Window.Msg.WM_MOUSEMOVE:
                if (VerticalScroll.IsThumbPressed)
                {
                    VerticalScroll.HandleMouseMove(null, null);
                }
                if (HorizontalScroll.IsThumbPressed)
                {
                    HorizontalScroll.HandleMouseMove(null, null);
                }
                base.WndProc(ref m);
                break;

            case Window.Msg.WM_NCMOUSEMOVE:
                // track mouse leaving (otherwise the WM_NCMOUSELEAVE message would not fire)
                WinApi.TRACKMOUSEEVENT tme = new WinApi.TRACKMOUSEEVENT();
                tme.cbSize    = (uint)Marshal.SizeOf(tme);
                tme.dwFlags   = (uint)(WinApi.TMEFlags.TME_LEAVE | WinApi.TMEFlags.TME_NONCLIENT);
                tme.hwndTrack = Handle;
                WinApi.TrackMouseEvent(tme);

                // PointToClient(new Point(m.LParam.ToInt32()));
                VerticalScroll.HandleMouseMove(null, null);
                HorizontalScroll.HandleMouseMove(null, null);
                base.WndProc(ref m);
                break;

            case Window.Msg.WM_NCLBUTTONDOWN:
                VerticalScroll.HandleMouseDown(null, null);
                HorizontalScroll.HandleMouseDown(null, null);
                Focus();
                // here we forward to base button down because it has a internal focus mecanism that we want to exploit
                // if we don't do that, the mouse MOVE events are not fired outside the bounds of this control!
                m.Msg = (int)Window.Msg.WM_LBUTTONDOWN;
                base.WndProc(ref m);
                break;

            case Window.Msg.WM_NCLBUTTONUP:
            case Window.Msg.WM_LBUTTONUP:
                VerticalScroll.HandleMouseUp(null, null);
                HorizontalScroll.HandleMouseUp(null, null);
                // here we forward this message to base WM_LBUTTONUP to release the internal focus on this control
                m.Msg = (int)Window.Msg.WM_LBUTTONUP;
                base.WndProc(ref m);
                break;

            case Window.Msg.WM_NCMOUSELEAVE:
                VerticalScroll.HandleMouseLeave(null, null);
                HorizontalScroll.HandleMouseLeave(null, null);
                base.WndProc(ref m);
                break;

            default:
                base.WndProc(ref m);
                break;
            }
        }
 protected virtual void MouseLDownClientArea(MouseEventArgs mouseEventArgs)
 {
     Focus();
     VerticalScroll.HandleMouseDown(null, null);
     HorizontalScroll.HandleMouseDown(null, null);
 }