使无边框表格可移动?

问题描述 投票:0回答:21

有没有办法让没有边框(FormBorderStyle 设置为“none”)的窗体在鼠标在窗体上单击时可移动,就像有边框一样?

c# winforms border movable
21个回答
296
投票
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);
    }
}

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


77
投票

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

话虽这么说,这是我的片段。我用它所有的时间。我还想指出,您不应该使用 this.Invalidate();正如其他人喜欢做的那样,因为它在某些情况下会导致表格闪烁。在某些情况下,这也是如此。刷新。使用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;
    }

43
投票

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

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;
}

20
投票

使用 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);     
  }
}

13
投票

仅限 WPF


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

frmBorderless.DragMove();

Window.DragMove方法(MSDN)


12
投票

它对我有用。

    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);
        }
    }

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);
}

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);
        }
    }
}

4
投票

没有任何属性可以让这一切神奇地发生。查看表单的事件,通过设置

this.Top
this.Left
来实现这一点变得相当简单。具体来说,您需要查看
MouseDown
MouseUp
MouseMove


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;
  }
}

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


4
投票

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

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

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);
      }
}

4
投票

我找到的最好的方法(当然修改过)

// 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);

2
投票

对于 .NET Framework 4,

您可以将

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

private void mainLayout_MouseDown(object sender, MouseButtonEventArgs e)
{
    this.DragMove();
}

2
投票

最简单的方法是:

首先创建一个名为label1的标签。 转到 label1 的事件 > 鼠标事件 > Label1_Mouse Move 并写入以下内容:

if (e.Button == MouseButtons.Left){
    Left += e.X;
    Top += e.Y;`
}

2
投票

我试图制作一个可移动的无边框窗口窗体,其中包含一个 WPF Element Host 控件和一个 WPF User 控件。

我最终在 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);

2
投票

我正在用另一种方法

ToolStrip1_MouseLeave
扩展 jay_t55 的解决方案,该方法可以处理鼠标快速移动并离开该区域的事件。

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;
}

1
投票

此外,如果您需要 DoubleClick 并使表单更大/更小,您可以使用第一个答案,创建一个全局 int 变量,每次用户单击您用于拖动的组件时添加 1。如果

variable == 2
则使您的表格变大/变小。还可以每半秒或一秒使用一个计时器,让您的
variable = 0
;


1
投票

向主窗口添加

MouseLeftButtonDown
事件处理程序对我有用。

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

base.OnMouseLeftButtonDown(e);
this.DragMove();

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; }
                }
            };
        }
    }
}

0
投票

只需使用硅酮,它使您的表格更容易制作并且更专业


-2
投票

我尝试了以下方法,很快就改变了,我的透明窗口不再冻结在原地,而是可以移动! (扔掉上面所有其他复杂的解决方案......)

   private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);
        // Begin dragging the window
        this.DragMove();
    }
© www.soinside.com 2019 - 2024. All rights reserved.