移动没有边框的窗口

18

如何移动一个没有边框的窗口。应用程序中没有空白处,只有一个网络浏览器和一个菜单栏可用。我希望用户可以通过拖动菜单栏来移动窗口。我该如何编写代码?我已经尝试了一些在网上找到的代码块,但都没有起作用。


5
可能是因为应用程序(或用户)无法区分对 MenuStrip 的单击是意图移动应用程序还是打开菜单。窗口有边框是有原因的,重新考虑你的设计。 - Cody Gray
8个回答

37

这篇文章可以帮助你完成这个任务。我自己也使用过,没有任何问题。以下是大致思路:

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

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

private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{     
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
    }
}
这将基本上“欺骗”窗口管理器,使其认为它正在抓取winform的标题栏。要将其应用于您的项目,只需使用MenuStrip的MouseDown事件即可。

1
那非常好。你可以在任何MouseDown事件中添加方法的内容,例如一个图片... - Otiel
那几乎太容易了 :) 谢谢! - David Thielen
即使在另一个C#应用程序中运行无边框窗体时,这也适用,而Point方法会失败。谢谢。 - undefined

23

这里是 .Net 的方式

    private bool dragging = false;
    private Point dragCursorPoint;
    private Point dragFormPoint;

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        dragging = true;
        dragCursorPoint = Cursor.Position;
        dragFormPoint = this.Location;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (dragging)
        {
            Point dif = Point.Subtract(Cursor.Position, new Size(dragCursorPoint));
            this.Location = Point.Add(dragFormPoint, new Size(dif));
        }
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        dragging = false;
    }

就这样。


哇哦,完美的.NET解决方案。非常感谢你。 - Erdinç

2
只需将起始点放入一个类似于以下的 2D 数组中:
public partial class mainForm : Form
{
    //Global variables for Moving a Borderless Form
    private bool dragging = false;
    private Point startPoint = new Point(0, 0); 


    public mainForm()
    {
        InitializeComponent();
    }

    private void mainForm_MouseDown(object sender, MouseEventArgs e)
    {
        dragging = true;
        startPoint = new Point(e.X, e.Y);

    }

    private void mainForm_MouseUp(object sender, MouseEventArgs e)
    {
        dragging = false;
    }

    private void mainForm_MouseMove(object sender, MouseEventArgs e)
    {
        if (dragging)
        {
            Point p = PointToScreen(e.Location);
            Location = new Point(p.X - this.startPoint.X, p.Y - this.startPoint.Y);

        }

    }
}

0
如果您正在使用面板,您必须将此添加到其中。

YourForm.Designer.cs

this.panel1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseDown);

并且这是在

YourForm.cs

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

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

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

0
Mbithi Kioko 步入了正确的轨道,但我会这样做。
    bool dragging = false;
    int xOffset = 0;
    int yOffset = 0;

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        dragging = true;

        xOffset = Cursor.Position.X - this.Location.X;
        yOffset = Cursor.Position.Y - this.Location.Y;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (dragging)
        {
            this.Location = new Point(Cursor.Position.X - xOffset, Cursor.Position.Y - yOffset);
            this.Update();
        }
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        dragging = false;
    }

0

我不得不使用System.Runtime.InteropServices.DllImportAttribute - 只是想评论并让大家知道。


0
你可以伪造你的菜单栏,例如使用一个带标签的面板。然后你可以手动处理:当用户点击标签时,弹出菜单将打开,当用户拖动标签时,窗口将移动。但我建议不要使用这样的变通方法,因为它不是标准的GUI行为,你可能会让你的用户感到困惑。

1
请不要这样做。这不仅是一个完全非标准的用户界面,而且它仍然无法解决解释点击的问题。请记住,“拖动”发生在点击之后。点击应该打开菜单,还是应该被解释为开始拖动?时光机还没有完善。 - Cody Gray
@Cody 当你释放鼠标按钮时,就会发生点击事件。看看Windows资源管理器中的文件夹面板是如何工作的:如果你单击一个文件夹,它会在右侧窗格中打开,但如果你拖动一个文件夹,它不会打开,只会被拖动。 - Ilya Kogan
2
明白了。但是要理解,您对“单击”事件的定义与Windows中菜单控件的解释不同。只要我在Windows中的任何应用程序中按下鼠标按钮,菜单就会下拉。它不会在鼠标按钮释放时发生。我认为需要指出的重要一点是,那些极大地改变预期行为的设计决策需要特别谨慎地考虑。 - Cody Gray

0

我没有尝试过,但如果您可以处理菜单栏上的"OnMouseDown"和"onMouseUp"事件:

  • 鼠标按下时-根据鼠标移动移动窗口
  • 在鼠标松开或鼠标移出时停止跟踪鼠标移动

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