Winforms-单击/拖动表单中的任何位置以将其移动,就像在表单标题中单击一样

时间:2020-03-05 18:43:51  来源:igfitidea点击:

我正在创建一个用于Winforms应用程序的小型模式窗体。它基本上是一种进度条。但是我希望用户能够单击表单中的任何位置并将其拖动以在桌面上仍在显示时将其移动。

如何实现这种行为?

解决方案

回答

Microsoft KB文章320687对此问题有详细的解答。

基本上,我们要覆盖WndProc方法,以便在要测试的点位于表单的客户区域中时将HTCAPTION返回到WM_NCHITTEST消息-实际上,这是告诉Windows将单击与单击该单击时完全相同一样。表格的标题。

private const int WM_NCHITTEST = 0x84;
private const int HTCLIENT = 0x1;
private const int HTCAPTION = 0x2;

protected override void WndProc(ref Message m)
{
  switch(m.Msg)
  {
    case WM_NCHITTEST:
      base.WndProc(ref m);
      if ((int)m.Result == HTCLIENT)
      {
        m.Result = (IntPtr)HTCAPTION;
      }

      return;
  }

  base.WndProc(ref m);
}

回答

下面的代码假定ProgressBarForm表单具有一个ProgressBar控件,且Dock属性设置为Fill

public partial class ProgressBarForm : Form
{
    private bool mouseDown;
    private Point lastPos;

    public ProgressBarForm()
    {
        InitializeComponent();
    }

    private void progressBar1_MouseMove(object sender, MouseEventArgs e)
    {
        if (mouseDown)
        {
            int xoffset = MousePosition.X - lastPos.X;
            int yoffset = MousePosition.Y - lastPos.Y;
            Left += xoffset;
            Top += yoffset;
            lastPos = MousePosition;
        }
    }

    private void progressBar1_MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        lastPos = MousePosition;
    }

    private void progressBar1_MouseUp(object sender, MouseEventArgs e)
    {
        mouseDown = false;
    }
}

回答

这是使用P / Invoke进行操作的方法。

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HTCAPTION = 0x2;
[DllImport("User32.dll")]
public static extern bool ReleaseCapture();
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

void Form_Load(object sender, EventArgs e)
{
   this.MouseDown += new MouseEventHandler(Form_MouseDown);  
}

void Form_MouseDown(object sender, MouseEventArgs e)
{                        
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
    }
}