【问题标题】:Move form without border through a panel通过面板移动无边框表单
【发布时间】:2013-11-29 15:46:44
【问题描述】:

我一直在为我的问题寻找解决方案,但目前我无法获得任何我想做的成功代码。所以,我有一个没有边框的表单,里面有 2 个自定义面板,所以用户无法点击框架,我想,我实现了一个代码,当用户点击面板时,这将调用一个函数在我的表单上,通过参数接收鼠标事件。 这是我的面板的代码(请注意,我在框架中的两个面板都是同一个类,它只是 2 个不同的实例)

 public class MyPanel : System.Windows.Forms.Panel{

                       (...)

     private void MyPanel_MouseDown(object sender, MouseEventArgs e)
     {
         BarraSms.getInstance().mouseDown(e);
     }

     private void MyPanel_MouseMove(object sender, MouseEventArgs e)
     {
         BarraSms.getInstance().mouseMove(e);
     }

}

这是我的表单代码:

 public partial class BarraSms : Form
{
  private Point mousePoint;

             (...)

   public void mouseDown(MouseEventArgs e) {

        mousePoint = new Point(-e.X, -e.Y);

    }

    public void mouseMove(MouseEventArgs e) {

        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            Point mousePos = Control.MousePosition;
            mousePos.Offset(mousePoint .X, mousePoint .Y);
            this.Location = mousePos;
        }

    }
}

我有什么遗漏的吗? 提前感谢您的帮助。

工作代码(更新),问题解决:x4rf41

MyPanel 类

MouseMove += MyPanel_MouseMove; // added in class constructer

BarraSms 类(表单)

public partial class BarraSms : Form
{
    public const int WM_NCLBUTTONDOWN = 0xA1;
    public const int HT_CAPTION = 0x2;


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

     public void mouseMove(MouseEventArgs e) {

        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            ReleaseCapture();
            SendMessage(this.Handle, WM_NCLBUTTONDOWN, new IntPtr(HT_CAPTION), IntPtr.Zero);
            Point loc = this.Location;

            writeCoordToBin(loc.X, loc.Y);

        }

    }

}

【问题讨论】:

    标签: c# forms mousemove


    【解决方案1】:

    使用 windows api 函数有更好的解决方案。 你使用它的方式,当你快速移动表单并且鼠标离开面板时,你会遇到问题。我遇到了完全相同的问题。

    试试这个:

    using System.Runtime.InteropServices;
    

    在你的 Form 类中

    public const int WM_NCLBUTTONDOWN = 0xA1;
    public const int HT_CAPTION = 0x2;
    
    [DllImportAttribute("user32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
    [DllImportAttribute("user32.dll")]
    public static extern bool ReleaseCapture();        
    
    public void mouseMove(MouseEventArgs e) 
    {
       if (e.Button == System.Windows.Forms.MouseButtons.Left)
       {
          ReleaseCapture();
          SendMessage(this.Handle,  WM_NCLBUTTONDOWN, new IntPtr(HT_CAPTION), IntPtr.Zero);
       }
    }
    

    这个不需要 mouseDown 事件

    【讨论】:

    • 那么你做错了,在你发布的代码中看不到。有什么错误吗?我将它与无边框表单和面板完全一样使用,没有问题
    • 您是在点击表单还是面板?我没有收到任何错误或警告
    • 在面板中单击。你确定事件被触发了吗?
    • 你分配了鼠标事件吗? MouseMove += MyPanel_MouseMove;MyPanel 类中?顺便提一句。最好在表单本身中分配事件,实例调用有点不必要
    • 这就是我会这样做的方式,使用表单中的面板事件:pastebin.com/YAkvfw4g 你可以与设计师一起做,当然只要确保事件被调用
    【解决方案2】:

    框架不能调用您在 MyPanel 中的私有方法。您需要按如下方式声明它们:

    protected override void OnMouseDown(MouseEventArgs e)
    {
        var parent = this.Parent as BarraSms;
        parent.mouseDown(e);
    }
    
    protected override void OnMouseMove(MouseEventArgs e)
    {
        var parent = this.Parent as BarraSms;
        parent.mouseMove(e);
    }
    

    【讨论】:

    • 当我点击面板时出现错误,可能是因为我的面板是静态只读类? 私有静态只读 BarraSms 实例 = new BarraSms();
    • 对不起。我假设面板是表单的子控件。如果面板的父级不是您的表单,那么parent.mouseDown(e) 显然不起作用。
    • 没问题,如果你想看答案 x4rf41 回答问题,我猜是windows事件上的问题
    • var form = this.FindForm() as BarraSms; form.mouseMove(e);
    【解决方案3】:

    试试这个:

    public void mouseMove(MouseEventArgs e) {
    
        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            Point currentPos = Location;
            currentPos.Offset(e.X + mousePoint.X, e.Y + mousePoint.Y);
            this.Location = currentPos;
        }
        //Or simply use Location.Offset(e.X + mousePoint.X, e.Y + mousePoint.Y);
    }
    

    您必须使用Location(表单的当前位置),而不是Control.MousePosition,这是鼠标在屏幕上的位置。

    更新:看起来您甚至不知道如何注册事件处理程序,尝试像这样修改您的面板类:

    public class MyPanel : System.Windows.Forms.Panel{
      //(...)
     protected override void OnMouseDown(MouseEventArgs e)
     {
         base.OnMouseDown(e);
         BarraSms.getInstance().mouseDown(e);
     }
    
     protected override void OnMouseMove(MouseEventArgs e)
     {
         base.OnMouseMove(e);
         BarraSms.getInstance().mouseMove(e);
     }
    
    }
    

    【讨论】:

    • @JoãoSilva 确实很奇怪,你确定你完全复制了我的代码吗?
    • 是的,我做了,但答案与 x4rf41 答案和 cmets 一样,我必须在使用 windows 事件的步骤中创建事件...
    • @JoãoSilva 从您的评论中,我很确定您没有正确附加您的处理程序,您可以尝试我更新的代码(对您的 MyPanel 类进行一些重要修改)。
    • 我更新了我的代码,它现在可以工作了,问题,我不知道为什么,是在鼠标事件中。我不得不手动创建事件,因为 windows 事件不起作用。
    猜你喜欢
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 2011-08-25
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多