qt中单击按钮打开新窗口_通过单击窗口中的任意位置移动表单

qt中单击按钮打开新窗口

Normally a window is moved by clicking on the caption bar and dragging. You may want your user to be able to move borderless forms or move a form by clicking anywhere in the form without the limitation to the caption bar. There are many ways to do it. Two of the most commonly-seen solutions are:

通常,通过单击标题栏并拖动来移动窗口。 您可能希望用户能够移动无边界表单或通过单击表单中的任意位置来移动表单,而不受标题栏的限制。 有很多方法可以做到这一点。 两种最常见的解决方案是:

Standard Three-Event Handling

标准三事件处理

Handle the mousedown, mouseup, mousemove events. You can set a "dragging now" flag in mousedown and record the initial mouse coordinates as the start point.   In mousemove event, calculate the delta between the current mouse position and the start point. Set the window's new location using this delta as deviation value so the window will follow the mouse movement.  Finally, set the "dragging now" flag to false to turn off the dragging.

处理

It's a functional technique. But you need to handle three events and use flags and variables to accomplish the work.

这是一项功能性技术。 但是您需要处理三个事件,并使用标志和变量来完成工作。

Re-target Form-Dragging Events

重新定位表单拖动事件

A simpler way is to intercept the message loop of a form and re-target the mouse events hitting the client area and send them to the caption bar, as shown in the following code snippet:

一种更简单的方法是拦截表单的消息循环,然后重新定位击中客户区域的鼠标事件并将其发送到标题栏,如以下代码片段所示:

private const int WM_NCHITTEST = 0x0084;
    private const int HTCLIENT = 1;
    private const int HTCAPTION = 2;
    protected override void WndProc(ref Message m)
    {
      base.WndProc(ref m);
      switch (m.Msg)
      {
        case WM_NCHITTEST:
          if (m.Result == (IntPtr)HTCLIENT)
          {
            m.Result = (IntPtr)HTCAPTION;
          }
          break;
      }
    }
public class InterceptProcForm:Form
Form with InterceptProcForm for all your forms:    
public partial class Form1 : InterceptProcForm

Handling User-Controls

处理用户控件

The question now comes up:  "What if a form is completely covered by a user control?" Now the message in WndProc() that originated from controls will be redirected to the control's caption which is meaningless to a control and the form will stay there quietly.

现在出现问题:“如果用户控件完全覆盖了表单,该怎么办?” 现在,WndProc()中源自控件的消息将被重定向到控件的标题,这对控件没有意义,并且窗体将安静地停留在该位置。

The solution is to handle the mousemove event and flood it to its owner form, as shown in this link: C# borderless form move by usercontrol.

解决方案是处理mousemove事件并将其泛洪到其所有者表单,如此链接所示: C#无边界表单由usercontrol移动

Once again we need to take code reuse into consideration. In the above link, a generic type FormDragPanel is used and user panels can inherit from it to move the underlying form. It's an improvement but not enough. There are tens (if not tons) of various types of user control; for some of them we may want the dragging capability and for others we would just keep them as it is. A common type derived from UserControl is not feasible because C# does not support multiple inheritance. A quick thought is to create a separate FormDragXxxx for each type of control: FormDragLabel, FormDragPictureBox, FormDragProgressBar, etc. But your work does not end here. You need to touch the Designer-generated code and add an event chain in your form for each of the controls.

再一次,我们需要考虑

Inspired by Marcel, here's a kind of "adapter" pattern I've used to resolve the scenario. Simply add the following class FormDragBase in your project.

在Marcel的启发下,这是我用来解决方案的一种“适配器”模式。 只需在项目中添加以下类

public class FormDragBase : System.Windows.Forms.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, int wParam, int lParam);
        [DllImportAttribute("user32.dll")]
        public static extern bool ReleaseCapture();

        protected override void OnMouseMove(System.Windows.Forms.MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (WindowState == FormWindowState.Normal)
                {
                    ReleaseCapture();
                    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
                }
            }
        }

        public void AddDraggingControl(System.Windows.Forms.Control theControl)
        {
            theControl.MouseMove += new System.Windows.Forms.MouseEventHandler(OnControlMouseMove);
        }

        private void OnControlMouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (WindowState == FormWindowState.Normal)
                {
                    ReleaseCapture();
                    SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
                }
            }
        }
    }
public partial class Form1 : FormDragBase
    {
        public Form1()
        {
            InitializeComponent();
            AddDraggingControl(this.label1);
            AddDraggingControl(this.pictureBox1);
            AddDraggingControl(this.progressBar1);
        }
    }

翻译自: https://www.experts-exchange.com/articles/4146/Moving-a-Form-by-Clicking-Anywhere-in-the-Window.html

qt中单击按钮打开新窗口

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值