Home > OS >  C# Winforms How to Understand Form object is moved
C# Winforms How to Understand Form object is moved

Time:12-16

I want to trigger an event only when the form is moved via the mouse click over the title bar. I could not find proper event for this.

Currently I implemented a move event for my forms in winform. I only want the move event to be triggered when the user drags the form via clicking on the title bar. However, this event is triggered also when form is tried to be resized by mouse or minimized/maximized. How can I disable this? I only want to trigger an event only when the form is moved. I am trying to implement my own floating forms and I want to catch this specific event to change the MDiParent of the form.

CodePudding user response:

You can check if the form is resized in the Move event and the Form's FormWindowState is changed, if not so, you can decide that Form is moving.

To do so, you should cache both the window state and size each time when Move event is triggered.

Note: The Move event is triggered even when you change the location of the form via the Location property, not only using the title bar. So, the event FromDragged will be triggered in the case. This is a "false positive".

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WhenDraggingUsingCaptionBar
{
    public partial class CustomForm : Form
    {
        public CustomForm()
        {
            InitializeComponent();
            FormDragged  = Form1_FormDragged;
        }

        private void Form1_FormDragged(object sender, EventArgs e)
        {
            MessageBox.Show("Test");
        }

        public event EventHandler FormDragged;
        private Size _cachedSize = new Size(0, 0);
        private FormWindowState _cachedState = FormWindowState.Normal; 
        private void Form1_Move(object sender, EventArgs e)
        {
            if (_cachedSize == Size && _cachedState == WindowState)
                if (FormDragged != null)
                    FormDragged(this, new EventArgs());

            _cachedSize = Size;
            _cachedState = WindowState;
        }
    }
}

As an addition, there is a low-level solution using Win32 API. This solution eliminates the "false-positive" issues in the approach above.

You can handle the WM_NCLBUTTONDOWN message. This message is sent when you down the mouse left button in the non-client area of the window. When we get the message, we set a variable to true. We also catch another message WM_EXITSIZEMOVE to understand when the dragging the window is stopped and set the variable to false.

If the variable is set to true when the move event is triggered, we can say the window is dragging using the title bar.

using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;

namespace WhenDraggingUsingCaptionBar
{
    public partial class CustomForm : Form
    {
        public CustomForm()
        {
            InitializeComponent();
            FormDragged  = Form1_FormDragged;
        } 
        private void Form1_FormDragged(object sender, EventArgs e)
        {
            Debug.WriteLine("{1}: Move:{0}", _ncbuttonDown, DateTime.Now);
        }

        public event EventHandler FormDragged; 
        private const int WM_NCLBUTTONDOWN = 0x00A1; 
        private const int WM_EXITSIZEMOVE = 0x0232; 
         
        private bool _ncbuttonDown = false;
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_NCLBUTTONDOWN)
                _ncbuttonDown = true;
            else if (m.Msg == WM_EXITSIZEMOVE) 
                _ncbuttonDown = false;  
            base.WndProc(ref m);
        }

        private void CustomForm_Move(object sender, EventArgs e)
        {
            if (_ncbuttonDown)
                if (FormDragged != null)
                    FormDragged(this, new EventArgs());
        }
    }
}


  • Related