使无边框形式可移动?

use*_*ser 101 c# border movable winforms

有没有办法使一个没有边框的表单(FormBorderStyle设置为"none")可以在窗体上单击鼠标时移动,就好像有一个边框?

Joe*_*oey 227

文章在CodeProject细节的技术.基本归结为:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

从窗口管理器的角度来看,这基本上与抓取窗口的标题栏完全相同.

  • @dbrree你可能复制了代码,这不起作用,因为`Form1_MouseDown`没有分配给`Form1`的实际`MouseDown`事件. (7认同)
  • 这对我来说根本不起作用。代码运行得很好,一切都正确,而且我的窗口仍然坐在那里。有任何想法吗? (4认同)
  • 如果您有一个标签或图标(或任何其他前景对象!),您要抓取要拖动的表单,也可以将mousedown事件添加到这些项目中.表单事件无法通过表单对象查看. (2认同)
  • 您需要将 `this.MouseDown += ...` 添加到表单的 `Main()` 函数中 (2认同)

jay*_*t55 49

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

话虽这么说,这是我的片段.我用它所有的时间.我还要注意你不应该使用this.Invalidate(); 正如其他人喜欢这样做,因为它会导致表格在某些情况下闪烁.在某些情况下,这样做.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;
    }
Run Code Online (Sandbox Code Playgroud)

  • dang winforms... 找了将近两个小时的答案.... 不过我是 C# 新手,你让我感到惊奇! (2认同)
  • 这很好。几个问题。1)被双击搞砸了。如果`e.Clicks == 1`,则仅设置`mouseDown = true`。2)如果您的表单上有控件(面板),这将不起作用。我所做的是钩住窗体上大多数控件的事件,除了一些像按钮这样没有意义的类型。 (2认同)

eli*_*mad 32

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

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 任何人都可以通过持有特定工具(例如标签)来移动表单。 (2认同)
  • 如果双击,该窗体将最大化。还要在这里和那里阅读,以免单击鼠标右键。 (2认同)

jun*_*ats 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);     
  }
}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ris 11

仅限WPF


没有准确的代码,但在最近的项目中我认为我使用了MouseDown事件并简单地说:

frmBorderless.DragMove();
Run Code Online (Sandbox Code Playgroud)

Window.DragMove方法(MSDN)

  • @Chris这对我来说是一个WPF项目.谢谢你没有删除答案. (3认同)
  • 那是WPF.好的,OP没有确切地说明这一点. (2认同)

小智 7

参考.视频链接

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

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 这段代码有效,但如何理解?除了switch语句之外,我不知道这段代码中的任何内容! (3认同)

小智 7

它对我有用。

    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);
        }
    }
Run Code Online (Sandbox Code Playgroud)


Seb*_*ian 5

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

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)