2011-08-05 72 views
13

在網上淘了文章後,我想出了這種設計的基於WinForms的觸摸屏應用程序,需要智能手機如滾動。該應用程序本身將運行在平板電腦或觸摸屏桌面上。如何讓智能手機像滾動的WinForms觸摸屏應用程序(滾動面板)

  • 我把我想要在面板上滾動的所有東西。
  • 設置自動滾屏爲true(這將顯示滾動條)
  • 現在把這個整個面板組框
  • 內收縮組框,直到滾動條隱藏的(視覺上隱藏的,不可見= FALSE)

現在,我陷入了一個有趣的部分。我想我必須處理mousedown,mouseup & mousemove在面板上設置自動滾動位置,這樣當有人觸摸面板並拖動它時,它就是滾動魔術。請幫助填寫以下方法存根的幾行代碼。自動滾動位置上的msdn doc非常令人困惑,因爲它返回負數,但需要用abs設置爲正,而不是。

Point mouseDownPoint; 
Point mouseUpPoint; 
Point mouseDragPoint; 
private void myPanel_MouseDown(object sender, MouseEventArgs e) 
{ 
    this.mouseDownPoint = e.Location; 
    Console.WriteLine("Mouse down at {0}", e.location); 
} 

private void myPanel_MouseUp(object sender, MouseEventArgs e) 
{ 
    this.mouseUpPoint = e.Location; 
    this.mouseDownPoint = new Point(); //will set for IsEmpty check 
    Console.WriteLine("Mouse Up at {0}", e.location); 
} 

private void myPanel_MouseMove(object sender, MouseEventArgs e) 
{ 
    Console.WriteLine("Mouse at {0}", e.location); 
    if (mouseDownPoint.IsEmpty()) //finger is off the touchscreen 
     return; 
    myPanel.Autocrollposition = ?? 
} 

謝謝

//更新 - 下面我有試錯的工作&測試代碼。 (不重構)。如果有人有更優雅的解決方案,請發佈。

Point mouseDownPoint; 
    private void innerpanel_MouseDown(object sender, MouseEventArgs e) 
    { 
     if (e.Button == MouseButtons.Left) 
      this.mouseDownPoint = e.Location; 
    } 

    private void innerpanel_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.Button != MouseButtons.Left) 
      return; 
     if ((mouseDownPoint.X == e.Location.X) && (mouseDownPoint.Y == e.Location.Y)) 
      return; 

     Point currAutoS = innerpanel.AutoScrollPosition; 
     if (mouseDownPoint.Y > e.Location.Y) 
     { 
      //finger slide UP 
      if (currAutoS.Y != 0) 
       currAutoS.Y = Math.Abs(currAutoS.Y) - 5; 
     } 
     else if (mouseDownPoint.Y < e.Location.Y) 
     { 
      //finger slide down 
      currAutoS.Y = Math.Abs(currAutoS.Y) + 5; 
     } 
     else 
     { 
      currAutoS.Y = Math.Abs(currAutoS.Y); 
     } 

     if (mouseDownPoint.X > e.Location.X) 
     { 
      //finger slide left 
      if (currAutoS.X != 0) 
       currAutoS.X = Math.Abs(currAutoS.X) - 5; 
     } 
     else if (mouseDownPoint.X < e.Location.X) 
     { 
      //finger slide right 
      currAutoS.X = Math.Abs(currAutoS.X) + 5; 
     } 
     else 
     { 
      currAutoS.X = Math.Abs(currAutoS.X); 
     } 
     innerpanel.AutoScrollPosition = currAutoS; 
     mouseDownPoint = e.Location; //IMPORTANT 

    } 

回答

3

這是我使用IMessageFilter的方式。對於所有正在尋找解決方案的人來說。 首先,你必須實現一個過濾器,將所有應用程序事件偵聽:

internal class MouseFilter : IMessageFilter 
{ 
    private const int WM_LBUTTONDOWN = 0x0201; 
    private const int WM_LBUTTONUP = 0x0202; 
    private const int WM_MOUSEMOVE = 0x0200; 

    /// <summary> 
    ///  Filtert eine Meldung, bevor sie gesendet wird. 
    /// </summary> 
    /// <param name="m">Die zu sendende Meldung. Diese Meldung kann nicht geändert werden.</param> 
    /// <returns> 
    ///  true, um die Meldung zu filtern und das Senden zu verhindern. false, um das Senden der Meldung bis zum nächsten Filter oder Steuerelement zu ermöglichen. 
    /// </returns> 
    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; 
    } 

    /// <summary> 
    ///  Occurs when [mouse filter up]. 
    /// </summary> 
    public event MouseFilterEventHandler MouseFilterUp; 

    /// <summary> 
    ///  Occurs when [mouse filter down]. 
    /// </summary> 
    public event MouseFilterEventHandler MouseFilterDown; 

    /// <summary> 
    ///  Occurs when [mouse filter move]. 
    /// </summary> 
    public event MouseFilterMoveEventHandler MouseFilterMove; 
} 

internal delegate void MouseFilterEventHandler(object sender, MouseFilterEventArgs args); 

internal delegate void MouseFilterMoveEventHandler(object sender, MouseFilterEventArgs args); 

internal class MouseFilterEventArgs 
{ 
    /// <summary> 
    ///  Initializes a new instance of the <see cref="MouseFilterEventArgs" /> class. 
    /// </summary> 
    /// <param name="mouseButton">The mouse button.</param> 
    /// <param name="clicks">The clicks.</param> 
    /// <param name="x">The x.</param> 
    /// <param name="y">The y.</param> 
    /// <param name="delta">The delta.</param> 
    public MouseFilterEventArgs(MouseButtons mouseButton, int clicks, int x, int y, int delta) 
    { 
     Button = mouseButton; 
     Clicks = clicks; 
     X = x; 
     Y = y; 
     Delta = delta; 
     Handled = false; 
    } 

    /// <summary> 
    ///  Gets or sets the button. 
    /// </summary> 
    /// <value> 
    ///  The button. 
    /// </value> 
    public MouseButtons Button { get; set; } 

    /// <summary> 
    ///  Gets or sets a value indicating whether this <see cref="MouseFilterEventArgs" /> is handled. 
    /// </summary> 
    /// <value> 
    ///  <c>true</c> if handled; otherwise, <c>false</c>. 
    /// </value> 
    public bool Handled { get; set; } 

    /// <summary> 
    ///  Gets or sets the X. 
    /// </summary> 
    /// <value> 
    ///  The X. 
    /// </value> 
    public int X { get; set; } 

    /// <summary> 
    ///  Gets or sets the Y. 
    /// </summary> 
    /// <value> 
    ///  The Y. 
    /// </value> 
    public int Y { get; set; } 

    /// <summary> 
    ///  Gets or sets the clicks. 
    /// </summary> 
    /// <value> 
    ///  The clicks. 
    /// </value> 
    public int Clicks { get; set; } 

    /// <summary> 
    ///  Gets or sets the delta. 
    /// </summary> 
    /// <value> 
    ///  The delta. 
    /// </value> 
    public int Delta { get; set; } 
} 

那麼你要這個過濾器註冊到你計劃:

static class Program 
{ 
    public static MouseFilter mouseFilter = new MouseFilter(); 

    /// <summary> 
    /// Der Haupteinstiegspunkt für die Anwendung. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     Application.AddMessageFilter(mouseFilter); 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new MainForm()); 
    } 
} 

現在你可以收聽全球鼠標事件並且滾動鼠標滾動面板是這樣的:

public partial class MainForm : Form 
{ 
    private bool _doTouchScroll; 
    private Point _mouseStartPoint = Point.Empty; 
    private Point _yourScrollablePanelStartPoint = Point.Empty; 

    /// <summary> 
    ///  Initializes a new instance of the <see cref="MainForm" /> class. 
    /// </summary> 
    public MainForm() 
    { 
     InitializeComponent(); 

     Program.mouseFilter.MouseFilterDown += mouseFilter_MouseFilterDown; 
     Program.mouseFilter.MouseFilterMove += mouseFilter_MouseFilterMove; 
     Program.mouseFilter.MouseFilterUp += mouseFilter_MouseFilterUp; 
    } 

    /// <summary> 
    ///  Handles the MouseFilterDown event of the mudmFilter control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e"> 
    ///  The <see cref="MouseFilterEventArgs" /> instance containing the event data. 
    /// </param> 
    private void mouseFilter_MouseFilterDown(object sender, MouseFilterEventArgs e) 
    { 
     if (!_doTouchScroll && e.Button == MouseButtons.Left) 
     { 
      _mouseStartPoint = new Point(e.X, e.Y); 
      _yourScrollablePanelStartPoint = new Point(-yourScrollablePanel.AutoScrollPosition.X, 
               -yourScrollablePanel.AutoScrollPosition.Y); 
     } 
    } 

    /// <summary> 
    ///  Handles the MouseFilterMove event of the mudmFilter control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e"> 
    ///  The <see cref="MouseFilterEventArgs" /> instance containing the event data. 
    /// </param> 
    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) 
       { 
        yourScrollablePanel.AutoScrollPosition = new Point(_yourScrollablePanelStartPoint.X - dx, 
                   _yourScrollablePanelStartPoint.Y - dy); 
       } 
       else if (Math.Abs(dx) > 10 || Math.Abs(dy) > 10) 
       { 
        _doTouchScroll = true; 
       } 
      } 
     } 
    } 

    /// <summary> 
    ///  Handles the MouseFilterUp event of the mudmFilter control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e"> 
    ///  The <see cref="MouseFilterEventArgs" /> instance containing the event data. 
    /// </param> 
    private void mouseFilter_MouseFilterUp(object sender, MouseFilterEventArgs e) 
    { 
     if (e.Button == MouseButtons.Left) 
     { 
      if (_doTouchScroll && !yourScrollablePanel.AutoScrollPosition.Equals(_yourScrollablePanelStartPoint) && 
       !_yourScrollablePanelStartPoint.Equals(Point.Empty)) 
      { 
       // dont fire Click-Event 
       e.Handled = true; 
      } 
      _doTouchScroll = false; 
      _mouseStartPoint = Point.Empty; 
      _yourScrollablePanelStartPoint = Point.Empty; 
     } 
    } 
} 
7

而作爲一個組件:

public partial class TouchableFlowLayoutPanel : FlowLayoutPanel 
{ 
    private bool _doTouchScroll; 
    private Point _mouseStartPoint = Point.Empty; 
    private Point _panelStartPoint = Point.Empty; 

    /// <summary> 
    ///  Initializes a new instance of the <see cref="TouchableFlowLayoutPanel" /> class. 
    /// </summary> 
    public TouchableFlowLayoutPanel() 
    { 
     InitializeComponent(); 

     Program.mouseFilter.MouseFilterDown += mouseFilter_MouseFilterDown; 
     Program.mouseFilter.MouseFilterMove += mouseFilter_MouseFilterMove; 
     Program.mouseFilter.MouseFilterUp += mouseFilter_MouseFilterUp; 
    } 

    /// <summary> 
    ///  Initializes a new instance of the <see cref="TouchableFlowLayoutPanel" /> class. 
    /// </summary> 
    /// <param name="container">The container.</param> 
    public TouchableFlowLayoutPanel(IContainer container) 
    { 
     container.Add(this); 

     InitializeComponent(); 

     Program.mouseFilter.MouseFilterDown += mouseFilter_MouseFilterDown; 
     Program.mouseFilter.MouseFilterMove += mouseFilter_MouseFilterMove; 
     Program.mouseFilter.MouseFilterUp += mouseFilter_MouseFilterUp; 
    } 

    /// <summary> 
    ///  Handles the MouseFilterDown event of the mouseFilter control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e"> 
    ///  The <see cref="MouseFilterEventArgs" /> instance containing the event data. 
    /// </param> 
    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); 
     } 
    } 

    /// <summary> 
    ///  Handles the MouseFilterMove event of the mouseFilter control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e"> 
    ///  The <see cref="MouseFilterEventArgs" /> instance containing the event data. 
    /// </param> 
    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; 
       } 
      } 
     } 
    } 

    /// <summary> 
    ///  Handles the MouseFilterUp event of the mouseFilter control. 
    /// </summary> 
    /// <param name="sender">The source of the event.</param> 
    /// <param name="e"> 
    ///  The <see cref="MouseFilterEventArgs" /> instance containing the event data. 
    /// </param> 
    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; 

    /// <summary> 
    ///  Filtert eine Meldung, bevor sie gesendet wird. 
    /// </summary> 
    /// <param name="m">Die zu sendende Meldung. Diese Meldung kann nicht geändert werden.</param> 
    /// <returns> 
    ///  true, um die Meldung zu filtern und das Senden zu verhindern. false, um das Senden der Meldung bis zum nächsten Filter oder Steuerelement zu ermöglichen. 
    /// </returns> 
    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; 
    } 

    /// <summary> 
    ///  Occurs when [mouse filter up]. 
    /// </summary> 
    public event MouseFilterEventHandler MouseFilterUp; 

    /// <summary> 
    ///  Occurs when [mouse filter down]. 
    /// </summary> 
    public event MouseFilterEventHandler MouseFilterDown; 

    /// <summary> 
    ///  Occurs when [mouse filter move]. 
    /// </summary> 
    public event MouseFilterMoveEventHandler MouseFilterMove; 
} 

internal delegate void MouseFilterEventHandler(object sender, MouseFilterEventArgs args); 

internal delegate void MouseFilterMoveEventHandler(object sender, MouseFilterEventArgs args); 

internal class MouseFilterEventArgs 
{ 
    /// <summary> 
    ///  Initializes a new instance of the <see cref="MouseFilterEventArgs" /> class. 
    /// </summary> 
    /// <param name="mouseButton">The mouse button.</param> 
    /// <param name="clicks">The clicks.</param> 
    /// <param name="x">The x.</param> 
    /// <param name="y">The y.</param> 
    /// <param name="delta">The delta.</param> 
    public MouseFilterEventArgs(MouseButtons mouseButton, int clicks, int x, int y, int delta) 
    { 
     Button = mouseButton; 
     Clicks = clicks; 
     X = x; 
     Y = y; 
     Delta = delta; 
     Handled = false; 
    } 

    /// <summary> 
    ///  Gets or sets the button. 
    /// </summary> 
    /// <value> 
    ///  The button. 
    /// </value> 
    public MouseButtons Button { get; set; } 

    /// <summary> 
    ///  Gets or sets a value indicating whether this <see cref="MouseFilterEventArgs" /> is handled. 
    /// </summary> 
    /// <value> 
    ///  <c>true</c> if handled; otherwise, <c>false</c>. 
    /// </value> 
    public bool Handled { get; set; } 

    /// <summary> 
    ///  Gets or sets the X. 
    /// </summary> 
    /// <value> 
    ///  The X. 
    /// </value> 
    public int X { get; set; } 

    /// <summary> 
    ///  Gets or sets the Y. 
    /// </summary> 
    /// <value> 
    ///  The Y. 
    /// </value> 
    public int Y { get; set; } 

    /// <summary> 
    ///  Gets or sets the clicks. 
    /// </summary> 
    /// <value> 
    ///  The clicks. 
    /// </value> 
    public int Clicks { get; set; } 

    /// <summary> 
    ///  Gets or sets the delta. 
    /// </summary> 
    /// <value> 
    ///  The delta. 
    /// </value> 
    public int Delta { get; set; } 
} 

static class Program 
{ 
    public static MouseFilter mouseFilter = new MouseFilter(); 

    /// <summary> 
    /// Der Haupteinstiegspunkt für die Anwendung. 
    /// </summary> 
    [STAThread] 
    static void Main() 
    { 
     Application.AddMessageFilter(mouseFilter); 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 
     Application.Run(new MainForm()); 
    } 
} 
2

我使用了OP公佈的代碼,但發現它不起作用,如果面板中有像標籤一樣的東西。爲了使這項工作更順利,我改變了。

e.Location 

PointToClient(Cursor.Position) 

,然後有在面板中的所有對象也叫鼠標按下鼠標移動和事件。這種方式不管你點擊它應該移動。

0

給原帖,考慮Cheap Funeral的答案。

這個版本更簡單,更流暢的觸摸(考慮手指移動速度,但不考慮移除手指後仍然滾動的效果,如移動但超速(可能我會這樣做,因爲我有時間))

Works的面板或FlowLayoutPanel的

創建形式並在其上插入一個FlowLayoutPanel的。

形態代碼:

Public Class Form1 

Private Function GenerateButton(pName As String) As Button 
    Dim mResult As New Button 
    With mResult 
     .Name = pName 
     .Text = pName 
     .Width = FlowPanel.Width 
     .Height = 100 
     .Margin = New Padding(0) 
     .Padding = New Padding(0) 
     .BackColor = Color.CornflowerBlue 
     AddHandler .MouseDown, AddressOf Button_MouseDown 
     AddHandler .MouseMove, AddressOf Button_MouseMove 
    End With 

    Return mResult 
End Function 



Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 
    FlowPanel.Padding = New Padding(0) 
    FlowPanel.Margin = New Padding(0) 
    Dim i As Integer 
    For i = 1 To 100 
     FlowPanel.Controls.Add(GenerateButton("btn" & i.ToString)) 
    Next 
End Sub 

Dim myMouseDownPoint As Point 
Dim myCurrAutoSMouseDown As Point 
Private Sub Button_MouseDown(sender As Object, e As MouseEventArgs) Handles FlowPanel.MouseDown 
    myMouseDownPoint = PointToClient(Cursor.Position) 
    myCurrAutoSMouseDown = FlowPanel.AutoScrollPosition 
End Sub 

Private Sub Button_MouseMove(sender As Object, e As MouseEventArgs) Handles FlowPanel.MouseMove 
    If e.Button = Windows.Forms.MouseButtons.Left Then 
     Dim mLocation As Point = PointToClient(Cursor.Position) 
     If myMouseDownPoint <> mLocation Then 
      Dim mCurrAutoS As Point 
      Dim mDeslocation As Point = myMouseDownPoint - mLocation 
      mCurrAutoS.X = Math.Abs(myCurrAutoSMouseDown.X) + mDeslocation.X 
      mCurrAutoS.Y = Math.Abs(myCurrAutoSMouseDown.Y) + mDeslocation.Y 

      FlowPanel.AutoScrollPosition = mCurrAutoS 

     End If 
    End If 
End Sub 

TIP: 要隱藏FlowLayoutPanel的(或面板)的卷軸,創建從FlowLayoutPanel的(或面板)繼承一個用戶控件和:

Imports System.Runtime.InteropServices 

Public Class FlowLayoutPanelExt 
Inherits FlowLayoutPanel 


<DllImport("user32.dll")> _ 
Private Shared Function ShowScrollBar(hWnd As IntPtr, wBar As Integer, bShow As Boolean) As <MarshalAs(UnmanagedType.Bool)> Boolean 
End Function 

Private Enum ScrollBarDirection 
    SB_HORZ = 0 
    SB_VERT = 1 
    SB_CTL = 2 
    SB_BOTH = 3 
End Enum 

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 
    If Me.Visible Then 
     ShowScrollBar(Me.Handle, CInt(ScrollBarDirection.SB_BOTH), False) 
     MyBase.WndProc(m) 
    End If 
End Sub 

Public Sub New() 

    ' This call is required by the designer. 
    InitializeComponent() 

    ' Add any initialization after the InitializeComponent() call. 
    Me.AutoScroll = True 
End Sub 

End Class 
0

這解決方案似乎是那裏最好的解決方案,也是最常被接受的解決方案 - 但是,如果您滾動到底部並觸摸按鈕後面的實際流量控制(我試圖將其設置爲空白),那麼您必須雙擊並按住滾動恢復的按鈕。重新啓動應用程序將恢復類似手機的滾動功能。我想知道是否有其他人看過這個或想出來 - 用你的應用程序試一下,看看是否也是如此。我修改了上面的代碼片段,以便您可以開始一個新項目,將其複製並粘貼到form1的代碼中,然後運行。

Public Class Form1 
     Dim FlowPanel As New FlowLayoutPanel 
     Private Function GenerateButton(ByVal pName As String) As Button 
      Dim mResult As New Button 
      With mResult 
       .Name = pName 
       .Text = pName 
       .Width = 128 
       .Height = 128 
       .Margin = New Padding(0) 
       .Padding = New Padding(0) 
       .BackColor = Color.CornflowerBlue 
       AddHandler .MouseDown, AddressOf Button_MouseDown 
       AddHandler .MouseMove, AddressOf Button_MouseMove 
      End With 

      Return mResult 
     End Function 



     Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load 

      Me.Width = 806 
      Me.Height = 480 
      FlowPanel.Padding = New Padding(0) 
      FlowPanel.Margin = New Padding(0) 
      ' FlowPanel.ColumnCount = Me.Width/(128 + 6) 
      FlowPanel.Dock = DockStyle.Fill 
      FlowPanel.AutoScroll = True 
      Me.Controls.Add(FlowPanel) 
      Dim i As Integer 
      For i = 1 To 98 
       FlowPanel.Controls.Add(GenerateButton("btn" & i.ToString)) 
      Next 
     End Sub 

     Dim myMouseDownPoint As Point 
     Dim myCurrAutoSMouseDown As Point 
     Private Sub Button_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) 
      myMouseDownPoint = PointToClient(Cursor.Position) 
      myCurrAutoSMouseDown = FlowPanel.AutoScrollPosition 
     End Sub 

     Private Sub Button_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) 
      If e.Button = Windows.Forms.MouseButtons.Left Then 
       Dim mLocation As Point = PointToClient(Cursor.Position) 
       If myMouseDownPoint <> mLocation Then 
        Dim mCurrAutoS As Point 
        Dim mDeslocation As Point = myMouseDownPoint - mLocation 
        mCurrAutoS.X = Math.Abs(myCurrAutoSMouseDown.X) + mDeslocation.X 
        mCurrAutoS.Y = Math.Abs(myCurrAutoSMouseDown.Y) + mDeslocation.Y 

        FlowPanel.AutoScrollPosition = mCurrAutoS 

       End If 
      End If 
     End Sub 
    End Class 
+0

對於訪問該網站的任何人如何解決代碼問題,發佈答案不應該提出一個新問題。如果您在使用代碼段時遇到問題,請嘗試提問。 –