C# 如何使用WinApi移动窗口

C# 如何使用WinApi移动窗口,c#,winapi,move,messages,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)

当我尝试用此按钮拖动窗口时,窗口会跳跃并闪烁:

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);
}
受保护的覆盖无效WndProc(参考消息m)
{
如果(m.Msg==WM_MOVE)
{
intx=(m.LParam.ToInt32()&0xffff);
int y=((m.LParam.ToInt32()>>16)和0xffff);
如果(x<500)
位置=新点(0,y);
其他的
基准WndProc(参考m);
}
其他的
基准WndProc(参考m);
}
  • 我们必须停止跳跃
  • WM_MOVE
    WM_MOVING
    WM_WINDOWPOSCHANGING
    或其他移动事件必须在拖动窗口时继续触发,因为我希望检查每个新位置
  • 另一个问题是
    位置=新点(0,y)触发另一个移动事件(应忽略此事件)

请帮忙

这应该可以满足您的要求:

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
位置,直到鼠标指针离开
500500
框:

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

下面是使用WM_WINDOWPOS更改和修改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);
    }

}

您只是想通过拖动来阻止移动窗口吗?窗口从何处开始(您是否在开始时设置了0,0)?您忘记了WM_移动消息。为什么需要使用“winapi”是非常不清楚的,LocationChanged事件工作得很好。听起来你应该使用。您可以更改WINDOWPOS结构以修改窗口位置和/或大小。使用Marshal.PtrToStructure()将其取出,并使用Marshal.StructureToPtr()将其放回;与我对WM_GETMINMAXINFO所做的非常相似。@Idle_介意我修改windowpos结构而不会触发移动/位置更改事件吗?您能否回答并帮助解决此问题(赢取积分)?初始移动和“捕捉”将触发一个move()事件,但之后不会生成任何移动事件…它只会粘在原地。此事件通常不会在您开始移动窗口时触发一次。我不希望它一直停留在
(0,0)
,而是决定何时让它移动或将其保留在一个位置。您没有提供任何建议来说明这种逻辑。如果你想让它成为答案的一部分,你必须解释一下。那么这个决策过程是什么呢?搬家、搬迁和无所事事的标准是什么?将其放入
if
块中,并相应地设置
Left
Top
。例如
Left=MousePostion.X
而不是零。对不起,这可能是一个误解。请注意问题中的大编辑。误解是我们不知道你想要它做什么。你抓住窗口,开始移动它,让它跳到
0,0
…然后呢?如果您不想让它保持在
0,0
,那么什么时候它不保持不变?