how to get smartphone like scrolling for a winforms touchscreen app ( scrolling panel )

前端 未结 6 972
暖寄归人
暖寄归人 2020-12-30 04:15

After scouring the articles online I have come up with this design for a winforms based touchscreen app that needs smartphone like scrolling. The app itself will run on a ta

6条回答
  •  天涯浪人
    2020-12-30 04:44

    And as a Component:

    public partial class TouchableFlowLayoutPanel : FlowLayoutPanel
    {
        private bool _doTouchScroll;
        private Point _mouseStartPoint = Point.Empty;
        private Point _panelStartPoint = Point.Empty;
    
        /// 
        ///     Initializes a new instance of the  class.
        /// 
        public TouchableFlowLayoutPanel()
        {
            InitializeComponent();
    
            Program.mouseFilter.MouseFilterDown += mouseFilter_MouseFilterDown;
            Program.mouseFilter.MouseFilterMove += mouseFilter_MouseFilterMove;
            Program.mouseFilter.MouseFilterUp += mouseFilter_MouseFilterUp;
        }
    
        /// 
        ///     Initializes a new instance of the  class.
        /// 
        /// The container.
        public TouchableFlowLayoutPanel(IContainer container)
        {
            container.Add(this);
    
            InitializeComponent();
    
            Program.mouseFilter.MouseFilterDown += mouseFilter_MouseFilterDown;
            Program.mouseFilter.MouseFilterMove += mouseFilter_MouseFilterMove;
            Program.mouseFilter.MouseFilterUp += mouseFilter_MouseFilterUp;
        }
    
        /// 
        ///     Handles the MouseFilterDown event of the mouseFilter control.
        /// 
        /// The source of the event.
        /// 
        ///     The  instance containing the event data.
        /// 
        private void mouseFilter_MouseFilterDown(object sender, MouseFilterEventArgs e)
        {
            if (!_doTouchScroll && e.Button == MouseButtons.Left)
            {
                _mouseStartPoint = new Point(e.X, e.Y);
                _panelStartPoint = new Point(-AutoScrollPosition.X,
                                                     -AutoScrollPosition.Y);
            }
        }
    
        /// 
        ///     Handles the MouseFilterMove event of the mouseFilter control.
        /// 
        /// The source of the event.
        /// 
        ///     The  instance containing the event data.
        /// 
        private void mouseFilter_MouseFilterMove(object sender, MouseFilterEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (!_mouseStartPoint.Equals(Point.Empty))
                {
                    int dx = (e.X - _mouseStartPoint.X);
                    int dy = (e.Y - _mouseStartPoint.Y);
    
                    if (_doTouchScroll)
                    {
                        AutoScrollPosition = new Point(_panelStartPoint.X - dx,
                                                       _panelStartPoint.Y - dy);
                    }
                    else if (Math.Abs(dx) > 10 || Math.Abs(dy) > 10)
                    {
                        _doTouchScroll = true;
                    }
                }
            }
        }
    
        /// 
        ///     Handles the MouseFilterUp event of the mouseFilter control.
        /// 
        /// The source of the event.
        /// 
        ///     The  instance containing the event data.
        /// 
        private void mouseFilter_MouseFilterUp(object sender, MouseFilterEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (_doTouchScroll && !AutoScrollPosition.Equals(_panelStartPoint) &&
                    !_panelStartPoint.Equals(Point.Empty))
                {
                    // don't fire Click-Event
                    e.Handled = true;
                }
                _doTouchScroll = false;
                _mouseStartPoint = Point.Empty;
                _panelStartPoint = Point.Empty;
            }
        }
    }
    
    internal class MouseFilter : IMessageFilter
    {
        private const int WM_LBUTTONDOWN = 0x0201;
        private const int WM_LBUTTONUP = 0x0202;
        private const int WM_MOUSEMOVE = 0x0200;
    
        /// 
        ///     Filters a message before sending it
        /// 
        /// The message to be sent.This message can not be changed.
        /// 
        ///     true to filter the message and prevent it from being sent. false to allow the message to be sent to the next filter or control.
        /// 
        public bool PreFilterMessage(ref Message m)
        {
            Point mousePosition = Control.MousePosition;
            var args = new MouseFilterEventArgs(MouseButtons.Left, 0, mousePosition.X, mousePosition.Y, 0);
    
            switch (m.Msg)
            {
                case WM_MOUSEMOVE:
                    if (MouseFilterMove != null)
                    {
                        MouseFilterMove(Control.FromHandle(m.HWnd), args);
                    }
                    break;
    
                case WM_LBUTTONDOWN:
                    if (MouseFilterDown != null)
                    {
                        MouseFilterDown(Control.FromHandle(m.HWnd), args);
                    }
                    break;
    
                case WM_LBUTTONUP:
                    if (MouseFilterUp != null)
                    {
                        MouseFilterUp(Control.FromHandle(m.HWnd), args);
                    }
                    break;
            }
    
            // Always allow message to continue to the next filter control
            return args.Handled;
        }
    
        /// 
        ///     Occurs when [mouse filter up].
        /// 
        public event MouseFilterEventHandler MouseFilterUp;
    
        /// 
        ///     Occurs when [mouse filter down].
        /// 
        public event MouseFilterEventHandler MouseFilterDown;
    
        /// 
        ///     Occurs when [mouse filter move].
        /// 
        public event MouseFilterMoveEventHandler MouseFilterMove;
    }
    
    internal delegate void MouseFilterEventHandler(object sender, MouseFilterEventArgs args);
    
    internal delegate void MouseFilterMoveEventHandler(object sender, MouseFilterEventArgs args);
    
    internal class MouseFilterEventArgs
    {
        /// 
        ///     Initializes a new instance of the  class.
        /// 
        /// The mouse button.
        /// The clicks.
        /// The x.
        /// The y.
        /// The delta.
        public MouseFilterEventArgs(MouseButtons mouseButton, int clicks, int x, int y, int delta)
        {
            Button = mouseButton;
            Clicks = clicks;
            X = x;
            Y = y;
            Delta = delta;
            Handled = false;
        }
    
        /// 
        ///     Gets or sets the button.
        /// 
        /// 
        ///     The button.
        /// 
        public MouseButtons Button { get; set; }
    
        /// 
        ///     Gets or sets a value indicating whether this  is handled.
        /// 
        /// 
        ///     true if handled; otherwise, false.
        /// 
        public bool Handled { get; set; }
    
        /// 
        ///     Gets or sets the X.
        /// 
        /// 
        ///     The X.
        /// 
        public int X { get; set; }
    
        /// 
        ///     Gets or sets the Y.
        /// 
        /// 
        ///     The Y.
        /// 
        public int Y { get; set; }
    
        /// 
        ///     Gets or sets the clicks.
        /// 
        /// 
        ///     The clicks.
        /// 
        public int Clicks { get; set; }
    
        /// 
        ///     Gets or sets the delta.
        /// 
        /// 
        ///     The delta.
        /// 
        public int Delta { get; set; }
    }
    
    static class Program
    {
        public static MouseFilter mouseFilter = new MouseFilter();
    
        /// 
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// 
        [STAThread]
        static void Main()
        {
            Application.AddMessageFilter(mouseFilter);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
    }
    

提交回复
热议问题