如何移动窗口像我想要的WinApi

本文关键字:我想要 WinApi 窗口 何移动 移动 | 更新日期: 2023-09-27 18:17:09

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

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_MOVE, WM_MOVING, WM_WINDOWPOSCHANGING或其他移动事件必须在拖动窗口时继续触发,因为我希望每个新位置都被检查。
  • 另一个问题是Location = new Point(0, y);触发另一个移动事件(这个应该被忽略)

请帮忙!

如何移动窗口像我想要的WinApi

下面是一个使用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);
    }
}

这应该是你想要的:

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);
}