使用菜单栏移动无边框窗体

4
我正在寻找一种使用menustrip移动表单的方法。
虽然有一些解决方案,但它们存在一个特定问题,我不太喜欢。为了使这些方法起作用,在拖动menustrip之前必须先将表单聚焦。
有没有一种方法来解决这个特定问题,使menustrip实际上像一个正确的Windows标题栏一样工作?

这是Winforms吗?您能列出其他解决方案,以便我们可以查看吗?谢谢。 - Jeremy Thompson
正如标题所示,是WinForms :) 我目前正在使用的方法类似于在https://dev59.com/8nI-5IYBdhLWcg3w99gH中找到的方法。 - denied66
1
请不要在标题前加上“Winforms:”等内容。这就是标签的作用。 - John Saunders
1个回答

4
最好的方法是使用pinvoke。将“mousedown”事件绑定到你想要拖动的任何控件上。
using System.Runtime.InteropServices;

public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;

[DllImportAttribute("user32.dll")]
private static extern int SendMessage(IntPtr hWnd,
                 int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
private static extern bool ReleaseCapture();

public Form1()
{
    InitializeComponent();
}

private void menuStrip1_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
    }
}

这仍然需要表单获得焦点,但是您可以通过鼠标悬停来解决。虽然不太优雅,但也能实现。

private void menuStrip1_MouseHover(object sender, EventArgs e)
{
    Focus();
}

更新:悬停有轻微延迟,mousemove更加响应。
private void menuStrip1_MouseMove(object sender, MouseEventArgs e)
{
    if (!Focused)
    {
        Focus();
    }
}

添加MouseHover事件就可以了,谢谢。不过似乎触发有点慢,所以如果你快速尝试拖动窗口可能不起作用。MouseEnter事件似乎没有这个问题。 - denied66
MouseMove比mousehover快得多,试一下。 - Du D.
MouseMove事件会触发很多次,考虑到用户的鼠标可能只是经过MenuStrip而已,这将是一个问题。MouseEnter似乎触发得足够快(到目前为止我没有遇到任何问题),而且它只会被触发一次。此外,它还消除了if语句的需要,因为开销很小。 - denied66

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接