C# 使无边框形式可移动?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1592876/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:07:47  来源:igfitidea点击:

Make a borderless form movable?

c#winformsbordermovable

提问by user

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?

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

采纳答案by Joey

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

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

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

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

回答by Matthew Scharley

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.Topand this.Left. Specifically you'll want to look at MouseDown, MouseUpand MouseMove.

没有任何属性可以翻转来使这神奇地发生。查看表单的事件,通过设置this.Top和来实现它变得相当简单this.Left。具体来说,您需要查看MouseDown,MouseUpMouseMove

回答by Chris

WPF only

仅 WPF



don't have the exact code to hand, but in a recent project I think I used MouseDown event and simply put this:

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

frmBorderless.DragMove();

Window.DragMove Method (MSDN)

Window.DragMove 方法 (MSDN)

回答by junmats

use MouseDown, MouseMove and MouseUp. You can set a variable flag for that. I have a sample, but I think you need to revise.

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

I am coding the mouse action to a panel. Once you click the panel, your form will move with it.

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

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

回答by Syed Ali

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

this can solve ur problem....

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

回答by jay_t55

Let's not make things any more difficult than they need to be. I've come across so many snippets of code that allow you to drag a form around (or another Control). And many of them have their own drawbacks/side effects. Especially those ones where they trick Windows into thinking that a Control on a form is the actual form.

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

That being said, here is my snippet. I use it all the time. I'd also like to note that you should not use this.Invalidate(); as others like to do because it causes the form to flicker in some cases. And in some cases so does this.Refresh. Using this.Update, I have not had any flickering issues:

话虽如此,这是我的片段。我用它所有的时间。我还想指出,你不应该使用 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;
    }

回答by elimad

Another simpler way to do the same thing.

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

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

回答by Gnana Akilan

Ref. video Link

参考 视频链接

This is tested and easy to understand.

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

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

回答by Neeraj Kumar Das

For .NET Framework 4,

对于 .NET Framework 4,

You can use this.DragMove()for the MouseDownevent of the component (mainLayout in this example) you are using to drag.

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

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

回答by Mike Sage

I was trying to make a borderless windows form movable which contained a WPF Element Host control and a WPF User control.

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

I ended up with a stack panel called StackPanel in my WPF user control which seemed the logical thing to try click on to move. Trying junmats's code worked when I moved the mouse slowly, but if I moved the mouse faster, the mouse would move off the form and the form would be stuck somewhere mid move.

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

This improved on his answer for my situation using CaptureMouse and ReleaseCaptureMouse and now the mouse does not move off the form while moving it even if I move it quickly.

这改进了他对我使用 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);