目录

第一种:手工移动

第二种:调用系统API

1.引入下面代码 前提需要引入命名空间using System.Runtime.InteropServices

2.增加鼠标按下事件发送消息,让系统误以为按下是标题栏

第三种,重写 WndProc


第一种:手工移动

直接通过修改窗体位置从而达到移动窗体的效果

        //定义一个位置信息Point用于存储鼠标位置
        private Point mPoint;
        /// <summary>
        /// 鼠标按下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            mPoint = new Point(e.X, e.Y);
        }

        /// <summary>
        /// 鼠标移动
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Location = new Point(this.Location.X + e.X - mPoint.X, this.Location.Y + e.Y - mPoint.Y);
            }
        }

第二种:调用系统API

原理:是当鼠标左键按下时,让系统认为是在标题栏按下的。

这里我们用到了winapi里的WM_LBUTTONDOWN(客户区鼠标左键按下,值:0x0201)和WM_NCLBUTTONDOWN(非客户区鼠标左键按下,值:0x00A1)及HTCAPTION(鼠标位置在标题栏,值:2,为什么是2,请参照https://msdn.microsoft.com/en-us/library/windows/desktop/ms645618(v=vs.85).aspx)这三个常量。

1.引入下面代码 前提需要引入命名空间using System.Runtime.InteropServices

        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();
 
        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
 
        private const int VM_NCLBUTTONDOWN = 0XA1;//定义鼠标左键按下
        private const int HTCAPTION = 2;

2.增加鼠标按下事件发送消息,让系统误以为按下是标题栏

        /// <summary>
        /// 鼠标按下
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void panel1_MouseDown(object sender, MouseEventArgs e)
        {
            //为当前应用程序释放鼠标捕获
            ReleaseCapture();
            //发送消息 让系统误以为在标题栏上按下鼠标
            SendMessage((IntPtr)this.Handle, VM_NCLBUTTONDOWN, HTCAPTION, 0);
        }

第三种,重写 WndProc

这个方法是用来处理消息的,包括鼠标的各种消息。前一种方法中讲到了非客户区的鼠标消息,但我在msdn里找了半天,没找到相关的非客户区的鼠标事件。但WndProc里可以处理。

原理:将鼠标在客户区按下的消息更改为在非客户区的标题栏按下。

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case 0x0201://鼠标左键按下的消息
                    m.Msg = 0x00A1;//更改消息为非客户区按下鼠标
                    m.LParam = IntPtr.Zero;//默认值
                    m.WParam = new IntPtr(2);//鼠标放在标题栏内
                    break;
            }
            base.WndProc(ref m);
        }

小结

除了第一种方法外,后两种都是用了模拟鼠标在标题的动作。这里我是实现了在非标题栏位置移动窗体。
由此我们可以引申开来,我们还可以模拟标题栏图标、关闭、最大化、最小化等操作。这样在一些无标题栏窗体中使用是很方便的。大家不仿尝试一下。


参考:C# 移动无标题栏窗体的几种方法 - Researcher - 博客园 (cnblogs.com)

WinForm无边框窗体移动方法 - 小石头山 - 博客园 (cnblogs.com)

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐