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
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());
}
}