自定义 WinForm 非客户区的操作

  前一段时间一直在研究 WinForm 非客户区(NonClient Area)的相关问题。我发现当捕获 WM_NCHITTEST 事件之后,如果将 WinForm 的某个 RECT 设定为 HTCAPTION 之后,则不能正常捕获 WM_NCLBUTTONDOWN 和 WM_NCLBUTTONUP 消息。从网上搜索相关问题之后发现是因为当某个区域为 HTCAPTION 时系统将接管关于标题栏的相关操作。致使当系统释放控制权后,WM_NCLBUTTONDOWN 消息才可以被接收。(一般会在鼠标左键抬起时收到 WM_NCLBUTTONDOWN 消息,而 WM_NCLBUTTONUP 消息则无法收到。)为了捕获 WM_NCLBUTTONUP 消息,有使用 PostMessage 方法实现的。但是消息收到的顺序却变为先收到 WM_NCLBUTTONUP 消息而后收到 WM_NCLBUTTONDOWN 消息。
  
  还有没有其它的方法呢?为此我翻阅了 MSDN 中关于 WM_NCHITTEST 的相关章节。
  MSDN: WM_NCHITTEST message
  
  在这篇文章中我发现关于 WM_NCHITTEST 的返回值说明中少了一个值为 19 的枚举。那这个值为 19 的枚举是什么呢?
  
  于是我在 http://www.pinvoke.net 中查找到名为 HitTestValues 的枚举且 HTOBJECT = 19 这样的内容。于是我在代码中进行了测试,测试后发现 HTOBJECT = 19 这个返回值指示 WM_NCHITTEST 消息已命中某个对象(Object),但是不特指该对象是否是HTCAPTION、HTICON、HTBORDER或是HTCLOSE。故当返回值为 HTOBJECT 时,系统将不接管后续操作,后续操作将直接由人工实现。麻烦是麻烦了点。但是至少自己可以对后续的操作完全具有主控权,而不必去和系统抢夺控制权问题。这就好了很多啊。
  
  为了说明这个问题,下面我用 Visual Basic .NET 来描述一下代码。感觉 Visual Basic .NET 的程序员对此需求好像更大。附带一段对非客户区尺寸调整的代码。

Visual Basic .NET Code


在实际代码前你需要做一些准备工作。比如下面的代码以方便对于 Win32 消息的处理。

Public Class API

    Public Const WM_SIZE As Int32 = &H5
    Public Const WM_NCCALCSIZE As Int32 = &H83
    Public Const WM_NCHITTEST As Int32 = &H84
    Public Const WM_NCPAINT As Int32 = &H85
    Public Const WM_NCACTIVATE As Int32 = &H86
    Public Const WM_NCMOUSEMOVE As Int32 = &HA0
    Public Const WM_NCLBUTTONDOWN As Int32 = &HA1
    Public Const WM_NCLBUTTONUP As Int32 = &HA2
    Public Const WM_NCLBUTTONDBCLK As Int32 = &HA3
    Public Const WM_NCRBUTTONDOWN As Int32 = &HA4
    Public Const WM_NCRBUTTONUP As Int32 = &HA5
    Public Const WM_NCRBUTTONDBCLK As Int32 = &HA6
    Public Const WM_NCMOUSEHOVER As Int32 = &H2A0
    Public Const WM_NCMOUSELEAVE As Int32 = &H2A2

    <Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)>
    Public Structure RECT
        Private _Left As Integer, _Top As Integer, _Right As Integer, _Bottom As Integer

        ' Constructors
        Public Sub New(ByVal Rectangle As Drawing.Rectangle)
            Me.New(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom)
        End Sub
        Public Sub New(ByVal Left As Integer, ByVal Top As Integer, ByVal Right As Integer, ByVal Bottom As Integer)
            _Left = Left
            _Top = Top
            _Right = Right
            _Bottom 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值