【发布时间】:2009-06-28 14:08:09
【问题描述】:
是否可以控制表单的移动位置?
所以如果我移动一个表单,它只能在垂直轴上移动,当我尝试水平移动它时,什么也没有发生。
我不想要一个错误的实现,比如 locationchanged 或 move 事件并将其弹出回内联。我没有办法使用 WndProc 覆盖之类的东西,但搜索了一段时间后,我找不到任何东西。请帮忙
【问题讨论】:
标签: c# user-interface move wndproc
是否可以控制表单的移动位置?
所以如果我移动一个表单,它只能在垂直轴上移动,当我尝试水平移动它时,什么也没有发生。
我不想要一个错误的实现,比如 locationchanged 或 move 事件并将其弹出回内联。我没有办法使用 WndProc 覆盖之类的东西,但搜索了一段时间后,我找不到任何东西。请帮忙
【问题讨论】:
标签: c# user-interface move wndproc
例如:
using System.Runtime.InteropServices;
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x216) // WM_MOVING = 0x216
{
Rectangle rect =
(Rectangle) Marshal.PtrToStructure(m.LParam, typeof (Rectangle));
if (rect.Left < 100)
{
// compensates for right side drift
rect.Width = rect.Width + (100 - rect.Left);
// force left side to 100
rect.X = 100;
Marshal.StructureToPtr(rect, m.LParam, true);
}
}
base.WndProc(ref m);
}
上面的代码设置了最小左手位置 100。
无需像 driis 那样重新创建 RECT 结构,.NET 原生 Rectangle 可以正常工作。但是,您必须通过 X 属性设置位置,因为 Left 是一个仅限获取的属性。
【讨论】:
您很可能希望覆盖 WndProc 并处理 WM_MOVING 消息。 According to MSDN:
WM_MOVING 消息被发送到 用户正在移动的窗口。经过 处理此消息,一个 应用程序可以监控位置 拖动矩形,如果需要, 改变它的位置。
这是一种方法,但是,您显然需要根据需要调整它:
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace VerticalMovingForm
{
public partial class Form1 : Form
{
private const int WM_MOVING = 0x0216;
private readonly int positionX;
private readonly int positionR;
public Form1()
{
Left = 400;
Width = 500;
positionX = Left;
positionR = Left + Width;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOVING)
{
var r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
r.Left = positionX;
r.Right = positionR;
Marshal.StructureToPtr(r, m.LParam, false);
}
base.WndProc(ref m);
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
}
}
【讨论】:
VB.NET 版本:
Protected Overloads Overrides Sub WndProc(ByRef m As Message)
If m.Msg = &H216 Then
' WM_MOVING = 0x216
Dim rect As Rectangle = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(Rectangle)), Rectangle)
If rect.Left < 100 Then
' compensates for right side drift
rect.Width = rect.Width + (100 - rect.Left)
' force left side to 100
rect.X = 100
Marshal.StructureToPtr(rect, m.LParam, True)
End If
End If
MyBase.WndProc(m)
End Sub
【讨论】: