我正在创建一个小的模态表单,用于Winforms应用程序。它基本上是一种进度条。但我希望用户能够在窗体中的任何地方单击并拖动它,以便在桌面上移动它,同时它仍在显示。
如何实现此行为?
发布于 2008-08-27 14:16:51
Microsoft KB Article 320687对这个问题有一个详细的答案。
基本上,当要测试的点位于窗体的工作区时,您可以重写WndProc方法以将HTCAPTION返回到WM_NCHITTEST消息--这实际上是告诉Window将单击完全视为发生在窗体标题上的单击。
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);
}
发布于 2008-08-27 14:29:06
以下是使用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);
}
}
发布于 2014-02-01 01:20:21
公认的答案是一个很酷的技巧,但是如果窗体被一个填充停靠的子控件覆盖,例如Panel (或派生的),它并不总是有效,因为这个控件将吃掉所有的Windows消息。
这里有一个简单的方法,也适用于这种情况:派生有问题的控件(使用这个类而不是标准的),并像这样处理鼠标消息:
private class MyTableLayoutPanel : Panel // or TableLayoutPanel, etc.
{
private Point _mouseDown;
private Point _formLocation;
private bool _capture;
// NOTE: we cannot use the WM_NCHITTEST / HTCAPTION trick because the table is in control, not the owning form...
protected override void OnMouseDown(MouseEventArgs e)
{
_capture = true;
_mouseDown = e.Location;
_formLocation = ((Form)TopLevelControl).Location;
}
protected override void OnMouseUp(MouseEventArgs e)
{
_capture = false;
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (_capture)
{
int dx = e.Location.X - _mouseDown.X;
int dy = e.Location.Y - _mouseDown.Y;
Point newLocation = new Point(_formLocation.X + dx, _formLocation.Y + dy);
((Form)TopLevelControl).Location = newLocation;
_formLocation = newLocation;
}
}
}
https://stackoverflow.com/questions/30184
复制相似问题