处理 ListView 中的 MouseMove、MouseDown、MouseUp 事件以拖动无边框窗体
Handle MouseMove, MouseDown, MouseUp Events in a ListView to drag a borderless Form
我正在使用 MouseMove
、MouseUp
、MouseDown
事件来移动无边界表单(如在此处找到的示例)。
效果很好,但对于 ListView,它只有在我单击列表中的项目(其文本)时才有效。如果我单击不包含项目的 ListView 的 space,它不起作用。
有没有办法解决这个问题?
private bool mouseDown;
private Point lastLocation;
private void ListView1_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
lastLocation = e.Location;
}
private void ListView1_MouseMove(object sender, MouseEventArgs e)
{
if(mouseDown)
{
this.Location = new Point(
(this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);
this.Update();
}
}
private void ListView1_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
要移动窗体,单击并拖动任何控件,您可以实现IMessageFilter Interface。在将消息发送到目标控件之前,您会收到消息(可以选择抑制它们,返回 true
)。
该实施要求您实施 PreFilterMessage.
当消息为WM_LBUTTONDOWN
时存储当前鼠标位置,当消息为WM_MOUSEMOVE
时移动表单,如果左按钮仍被按下(当前按下的按钮在[=14=中指定) ],请参阅有关此内容的文档)。
使用Application.AddMessageFilter注册实现接口的class(本例中为Form本身)。在这里,它在 OnHandleCreated
.
中调用
调用 Application.RemoveMessageFilter 删除过滤器。在这里,调用 OnHandleDestroyed
.
请注意,我在 WM_MOUSEMOVE
中使用了 Capture = true;
,因此按下鼠标左键并拖动(例如,按钮控件)不会导致 - 在本例中 - Click 事件.
不喜欢就修改吧
注意:
正如 Reza Aghaei 所建议的那样,如果将 ListView 设置为 MultiSelect = false
,则可以单击它的任意位置来拖动表单。
public partial class SomeForm : Form, IMessageFilter
{
private const int WM_MOUSEMOVE = 0x0200;
private const int WM_LBUTTONDOWN = 0x0201;
Point mouseDownPos = Point.Empty;
public bool PreFilterMessage(ref Message m) {
switch (m.Msg) {
case WM_LBUTTONDOWN:
mouseDownPos = PointToClient(MousePosition);
break;
case WM_MOUSEMOVE:
if ((m.WParam.ToInt32() & 1) != 1) break;
Capture = true;
var p = PointToClient(MousePosition);
Location = new Point(Left + p.X - mouseDownPos.X, Top + p.Y - mouseDownPos.Y);
break;
}
return false;
}
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
if (!DesignMode) Application.AddMessageFilter(this);
}
protected override void OnHandleDestroyed(EventArgs e) {
if (!DesignMode) Application.RemoveMessageFilter(this);
base.OnHandleDestroyed(e);
}
}
我正在使用 MouseMove
、MouseUp
、MouseDown
事件来移动无边界表单(如在此处找到的示例)。
效果很好,但对于 ListView,它只有在我单击列表中的项目(其文本)时才有效。如果我单击不包含项目的 ListView 的 space,它不起作用。
有没有办法解决这个问题?
private bool mouseDown;
private Point lastLocation;
private void ListView1_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
lastLocation = e.Location;
}
private void ListView1_MouseMove(object sender, MouseEventArgs e)
{
if(mouseDown)
{
this.Location = new Point(
(this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);
this.Update();
}
}
private void ListView1_MouseUp(object sender, MouseEventArgs e)
{
mouseDown = false;
}
要移动窗体,单击并拖动任何控件,您可以实现IMessageFilter Interface。在将消息发送到目标控件之前,您会收到消息(可以选择抑制它们,返回 true
)。
该实施要求您实施 PreFilterMessage.
当消息为WM_LBUTTONDOWN
时存储当前鼠标位置,当消息为WM_MOUSEMOVE
时移动表单,如果左按钮仍被按下(当前按下的按钮在[=14=中指定) ],请参阅有关此内容的文档)。
使用Application.AddMessageFilter注册实现接口的class(本例中为Form本身)。在这里,它在 OnHandleCreated
.
中调用
调用 Application.RemoveMessageFilter 删除过滤器。在这里,调用 OnHandleDestroyed
.
请注意,我在 WM_MOUSEMOVE
中使用了 Capture = true;
,因此按下鼠标左键并拖动(例如,按钮控件)不会导致 - 在本例中 - Click 事件.
不喜欢就修改吧
注意:
正如 Reza Aghaei 所建议的那样,如果将 ListView 设置为 MultiSelect = false
,则可以单击它的任意位置来拖动表单。
public partial class SomeForm : Form, IMessageFilter
{
private const int WM_MOUSEMOVE = 0x0200;
private const int WM_LBUTTONDOWN = 0x0201;
Point mouseDownPos = Point.Empty;
public bool PreFilterMessage(ref Message m) {
switch (m.Msg) {
case WM_LBUTTONDOWN:
mouseDownPos = PointToClient(MousePosition);
break;
case WM_MOUSEMOVE:
if ((m.WParam.ToInt32() & 1) != 1) break;
Capture = true;
var p = PointToClient(MousePosition);
Location = new Point(Left + p.X - mouseDownPos.X, Top + p.Y - mouseDownPos.Y);
break;
}
return false;
}
protected override void OnHandleCreated(EventArgs e) {
base.OnHandleCreated(e);
if (!DesignMode) Application.AddMessageFilter(this);
}
protected override void OnHandleDestroyed(EventArgs e) {
if (!DesignMode) Application.RemoveMessageFilter(this);
base.OnHandleDestroyed(e);
}
}