125

Is there a way to make a form that has no border (FormBorderStyle is set to "none") movable when the mouse is clicked down on the form just as if there was a border?

4

20 回答 20

280

This article on CodeProject details a technique. Is basically boils down to:

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

[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImport("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);
    }
}

This essentially does exactly the same as grabbing the title bar of a window, from the window manager's point of view.

于 2009-10-20T06:58:52.347 回答
66

让我们不要让事情变得比他们需要的更困难。我遇到了很多代码片段,它们允许您拖动表单(或另一个控件)。他们中的许多人都有自己的缺点/副作用。尤其是那些他们欺骗 Windows 认为窗体上的控件是实际窗体的那些。

话虽如此,这是我的片段。我用它所有的时间。我还要注意你不应该使用 this.Invalidate(); 就像其他人喜欢做的那样,因为它在某些情况下会导致表单闪烁。在某些情况下,this.Refresh 也是如此。使用this.Update,我没有任何闪烁的问题:

private bool mouseDown;
private Point lastLocation;

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        mouseDown = true;
        lastLocation = e.Location;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if(mouseDown)
        {
            this.Location = new Point(
                (this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);

            this.Update();
        }
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        mouseDown = false;
    }
于 2014-07-03T19:32:24.167 回答
41

另一种更简单的方法来做同样的事情。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        // set this.FormBorderStyle to None here if needed
        // if set to none, make sure you have a way to close the form!
    }
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_NCHITTEST)
            m.Result = (IntPtr)(HT_CAPTION);
    }

    private const int WM_NCHITTEST = 0x84;
    private const int HT_CLIENT = 0x1;
    private const int HT_CAPTION = 0x2;
}
于 2014-07-11T06:10:15.870 回答
19

使用 MouseDown、MouseMove 和 MouseUp。您可以为此设置一个变量标志。我有一个样本,但我认为你需要修改。

我正在将鼠标操作编码到面板。单击面板后,您的表单将随之移动。

//Global variables;
private bool _dragging = false;
private Point _offset;
private Point _start_point=new Point(0,0);


private void panel1_MouseDown(object sender, MouseEventArgs e)
{
   _dragging = true;  // _dragging is your variable flag
   _start_point = new Point(e.X, e.Y);
}

private void panel1_MouseUp(object sender, MouseEventArgs e)
{
   _dragging = false; 
}

private void panel1_MouseMove(object sender, MouseEventArgs e)
{
  if(_dragging)
  {
     Point p = PointToScreen(e.Location);
     Location = new Point(p.X - this._start_point.X,p.Y - this._start_point.Y);     
  }
}
于 2009-10-20T07:30:46.990 回答
13

仅 WPF


手头没有确切的代码,但在最近的一个项目中,我想我使用了 MouseDown 事件并简单地说:

frmBorderless.DragMove();

Window.DragMove 方法 (MSDN)

于 2009-10-20T07:05:16.780 回答
9

参考。视频链接

这是经过测试且易于理解的。

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case 0x84:
            base.WndProc(ref m);
            if((int)m.Result == 0x1)
                m.Result = (IntPtr)0x2;
            return;
    }

    base.WndProc(ref m);
}
于 2015-02-10T17:19:56.140 回答
9

它对我有用。

    private Point _mouseLoc;

    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        _mouseLoc = e.Location;
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            int dx = e.Location.X - _mouseLoc.X;
            int dy = e.Location.Y - _mouseLoc.Y;
            this.Location = new Point(this.Location.X + dx, this.Location.Y + dy);
        }
    }
于 2019-08-11T17:05:57.057 回答
4
public Point mouseLocation;
private void frmInstallDevice_MouseDown(object sender, MouseEventArgs e)
{
  mouseLocation = new Point(-e.X, -e.Y);
}

private void frmInstallDevice_MouseMove(object sender, MouseEventArgs e)
{
  if (e.Button == MouseButtons.Left)
  {
    Point mousePos = Control.MousePosition;
    mousePos.Offset(mouseLocation.X, mouseLocation.Y);
    Location = mousePos;
  }
}

这可以解决你的问题....

于 2013-02-21T07:41:55.633 回答
4

There's no property you can flip to make this just happen magically. Look at the events for the form and it becomes fairly trivial to implement this by setting this.Top and this.Left. Specifically you'll want to look at MouseDown, MouseUp and MouseMove.

于 2009-10-20T06:56:56.293 回答
4

由于某些答案不允许子控件可拖动,因此我创建了一个小助手类。它应该通过顶级表单。如果需要,可以变得更通用。

class MouseDragger
{
    private readonly Form _form;
    private Point _mouseDown;

    protected void OnMouseDown(object sender, MouseEventArgs e)
    {
        _mouseDown = e.Location;
    }

    protected void OnMouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left)
        {
            int dx = e.Location.X - _mouseDown.X;
            int dy = e.Location.Y - _mouseDown.Y;
            _form.Location = new Point(_form.Location.X + dx, _form.Location.Y + dy);
        }
    }
    public MouseDragger(Form form)
    {
        _form = form;

        MakeDraggable(_form);            
    }

    private void MakeDraggable(Control control)
    {
        var type = control.GetType();
        if (typeof(Button).IsAssignableFrom(type))
        {
            return;
        }

        control.MouseDown += OnMouseDown;
        control.MouseMove += OnMouseMove;

        foreach (Control child in control.Controls)
        {
            MakeDraggable(child);
        }
    }
}
于 2018-06-20T09:54:21.340 回答
4

https://social.msdn.microsoft.com/Forums/vstudio/en-US/d803d869-68e6-46ff-9ff1-fabf78d6393c/how-to-make-a-borderless-form-in-c?forum=csharpgeneral

上面链接中的这段代码在我的案例中起到了作用:)

protected override void OnMouseDown(MouseEventArgs e)  

{
      base.OnMouseDown(e);
      if (e.Button == MouseButtons.Left)
      {
        this.Capture = false;
        Message msg = Message.Create(this.Handle, 0XA1, new IntPtr(2), IntPtr.Zero);
        this.WndProc(ref msg);
      }
}
于 2016-09-26T06:44:49.647 回答
3

我找到的最佳方式(当然修改)

// This adds the event handler for the control
private void AddDrag(Control Control) { Control.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DragForm_MouseDown); }
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();

private void DragForm_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        ReleaseCapture();
        SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
        // Checks if Y = 0, if so maximize the form
        if (this.Location.Y == 0) { this.WindowState = FormWindowState.Maximized; }
    }
}

要将拖动应用到控件,只需在 InitializeComponent() 之后插入它

AddDrag(NameOfControl);
于 2017-07-20T14:15:16.137 回答
2

最简单的方法是:

首先创建一个名为 label1 的标签。转到 label1 的事件 > 鼠标事件 > Label1_Mouse 移动并写下这些:

if (e.Button == MouseButtons.Left){
    Left += e.X;
    Top += e.Y;`
}
于 2017-02-01T13:00:31.500 回答
2

对于 .NET Framework 4,

您可以使用this.DragMove()用于MouseDown拖动的组件的事件(本示例中为 mainLayout)。

private void mainLayout_MouseDown(object sender, MouseButtonEventArgs e)
{
    this.DragMove();
}
于 2016-04-23T13:57:09.633 回答
2

我试图制作一个可移动的无边框窗口窗体,其中包含一个 WPF 元素主机控件和一个 WPF 用户控件。

我最终在我的 WPF 用户控件中使用了一个名为 StackPanel 的堆栈面板,这似乎是尝试单击移动的合乎逻辑的事情。当我缓慢移动鼠标时,尝试 junmats 的代码有效,但如果我更快地移动鼠标,鼠标会从表单上移开,并且表单会卡在移动中间的某个地方。

这改进了他使用 CaptureMouse 和 ReleaseCaptureMouse 对我的情况的回答,现在即使我快速移动鼠标,鼠标在移动时也不会离开表单。

private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
    _start_point = e.GetPosition(this);
    StackPanel.CaptureMouse();
}

private void StackPanel_MouseUp(object sender, MouseButtonEventArgs e)
{
    StackPanel.ReleaseMouseCapture();
}

private void StackPanel_MouseMove(object sender, MouseEventArgs e)
{
    if (StackPanel.IsMouseCaptured)
    {
        var p = _form.GetMousePositionWindowsForms();
        _form.Location = new System.Drawing.Point((int)(p.X - this._start_point.X), (int)(p.Y - this._start_point.Y));
    }
}

    //Global variables;
    private Point _start_point = new Point(0, 0);
于 2016-08-09T21:22:32.537 回答
2

我正在使用另一种方法扩展 jay_t55 的解决方案,以ToolStrip1_MouseLeave处理鼠标快速移动并离开该区域的事件。

private bool mouseDown;
private Point lastLocation;

private void ToolStrip1_MouseDown(object sender, MouseEventArgs e) {
    mouseDown = true;
    lastLocation = e.Location;
}

private void ToolStrip1_MouseMove(object sender, MouseEventArgs e) {
    if (mouseDown) {
        this.Location = new Point(
            (this.Location.X - lastLocation.X) + e.X, (this.Location.Y - lastLocation.Y) + e.Y);

        this.Update();
    }
}

private void ToolStrip1_MouseUp(object sender, MouseEventArgs e) {
    mouseDown = false;
}

private void ToolStrip1_MouseLeave(object sender, EventArgs e) {
    mouseDown = false;
}
于 2019-06-04T07:50:25.380 回答
1

向 MainWindow添加MouseLeftButtonDown事件处理程序对我有用。

在自动生成的事件函数中,添加以下代码:

base.OnMouseLeftButtonDown(e);
this.DragMove();
于 2018-06-19T07:45:05.847 回答
1

此外,如果您需要 DoubleClick 并使您的 Form 更大/更小,您可以使用第一个答案,创建一个全局 int 变量,每次用户单击您用于拖动的组件时添加 1。如果variable == 2然后使您的表格更大/更小。也可以每隔半秒或一秒使用一个计时器来制作你的variable = 0;

于 2016-11-16T20:10:03.647 回答
0

表格1():new Moveable(control1, control2, control3);

班级:

using System;
using System.Windows.Forms;

class Moveable
{
    public const int WM_NCLBUTTONDOWN = 0xA1;
    public const int HT_CAPTION = 0x2;
    [System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    [System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
    public static extern bool ReleaseCapture();
    public Moveable(params Control[] controls)
    {
        foreach (var ctrl in controls)
        {
            ctrl.MouseDown += (s, e) =>
            {
                if (e.Button == MouseButtons.Left)
                {
                    ReleaseCapture();
                    SendMessage(ctrl.FindForm().Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
                    // Checks if Y = 0, if so maximize the form
                    if (ctrl.FindForm().Location.Y == 0) { ctrl.FindForm().WindowState = FormWindowState.Maximized; }
                }
            };
        }
    }
}
于 2020-04-11T14:11:03.683 回答
-2

我尝试了以下和 presto changeo,我的透明窗口不再被冻结,但可以移动!(扔掉上面所有其他复杂的解决方案......)

   private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);
        // Begin dragging the window
        this.DragMove();
    }
于 2018-07-20T16:04:00.087 回答