• C# 移动无标题栏窗体的几种方法


    第一种,手工移动。

    该方法根据鼠标位置实现窗体的移动。网上有很多相关的例子,这里不再多讲。

    第二种,调用系统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)这三个常量。

    这里是采用 SendMessage这个函数,当鼠标左键在客户区按下的时候,我们用这个函数发出一个鼠标左键在标题栏按下的消息来代替。该函数的原型为:

    LRESULT SendMessage(      

        HWND hWnd,     UINT Msg,     WPARAM wParam,     LPARAM lParam );
    我这们在C#中导入这个API:
            [DllImport("user32.dll")]
            public static extern IntPtr SendMessage(IntPtr hWnd,int msg,int wparam,int lparam);
    然后重写鼠标事件:
            protected override void OnMouseDown(MouseEventArgs e)
            {
                base.OnMouseDown(e);
                if (e.Button == MouseButtons.Left)//按下的是鼠标左键
                {
                    Capture = false;//释放鼠标,使能够手动操作
                    SendMessage(Handle, 0x00A1, 2, 0);//拖动窗体
                }
            }
    说明:SendMessage(Handle, 0x00A1, 2, 0);
    Handle为窗体的属性,表示当前窗口句柄。0x00A1表示消息ID,这个为非客户区域鼠标左键按下时的消息。2表示
    鼠标在标题栏的空白位置。注意,在调用SendMessage之前,我们用Capture释放鼠标。只要设置成false就可以了。这样就可以实现在客户区窗体的拖动了。

    第三种,重写 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);
            }

    小结

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

  • 相关阅读:
    自定义类型转换器之TypeConverter
    python测试工具nosetests
    算法练习之相同的树,对称二叉树
    算法练习之x的平方根,爬楼梯,删除排序链表中的重复元素, 合并两个有序数组
    算法练习之报数, 最大子序和,最后一个单词的长度,加一,二进制求和
    java.sql.SQLException: Zero date value prohibited
    java打包小记
    修改jar的.class文件,并重新打包
    算法练习之合并两个有序链表, 删除排序数组中的重复项,移除元素,实现strStr(),搜索插入位置,无重复字符的最长子串
    解决GitHub访问速度慢的问题
  • 原文地址:https://www.cnblogs.com/researcher/p/4989292.html
Copyright © 2020-2023  润新知