如何使用WinApi移动窗口

时间:2013-06-06 13:13:50

标签: c# winapi move messages

当我尝试用这个窗口拖动时,窗口会跳跃并闪烁:

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_MOVE)
    {
        int x = (m.LParam.ToInt32() & 0xffff);
        int y = ((m.LParam.ToInt32() >> 16) & 0xffff);

        if (x < 500)
            Location = new Point(0, y);
        else
            base.WndProc(ref m);
    }
    else
        base.WndProc(ref m);
}
  • 必须停止跳跃
  • WM_MOVEWM_MOVINGWM_WINDOWPOSCHANGING或其他移动事件必须在拖动窗口时继续触发,因为我希望检查每个新位置。
  • 另一个问题是Location = new Point(0, y);触发了另一个移动事件(应忽略​​此事件)

请帮忙!

2 个答案:

答案 0 :(得分:3)

以下是使用WM_WINDOWPOSCHANGING并修改WINDOWPOS结构的示例:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    public struct WINDOWPOS
    {
        public IntPtr hwnd;
        public IntPtr hwndInsertAfter;
        public int x;
        public int y;
        public int cx;
        public int cy;
        public uint flags;
    }

    public const int WM_WINDOWPOSCHANGING = 0x46;

    protected override void WndProc(ref Message m)
    {
        switch (m.Msg)
        {
            case WM_WINDOWPOSCHANGING:
                WINDOWPOS wp = (WINDOWPOS)System.Runtime.InteropServices.Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS));
                if (true) // ... if somecondition ...
                {
                    // modify the location with x,y:
                    wp.x = 0;
                    wp.y = 0;
                }
                System.Runtime.InteropServices.Marshal.StructureToPtr(wp, m.LParam, true);
                break;
        }

        base.WndProc(ref m);
    }

}

答案 1 :(得分:0)

这应该做你想要的:

protected override void WndProc(ref Message message)
{
    const Int32 WM_SYSCOMMAND = 0x0112;
    const Int32 SC_MOVE = 0xF010;

    switch (message.Msg)
    {
        case WM_SYSCOMMAND:
            Int32 command = message.WParam.ToInt32() & 0xfff0;
            if (command == SC_MOVE)
            {
                Left = 0;
                Top = 0;
                return;
            }
            break;
    }

    base.WndProc(ref message);
}

Hans Passant建议LocationChanged事件,它可以很好地工作。在此示例中,窗口在0, 0处冻结,直到鼠标指针超出500, 500框:

private void Form1_LocationChanged(Object sender, EventArgs e)
{
    if (MousePosition.X > 500 || MousePosition.Y > 500)
        Location = MousePosition;
    else
        Location = new Point(0, 0);
}