当我在WndProc中收到WM_MOUSEMOVE消息时,lParam包含光标坐标。我将此参数转换为Point
结构:
Friend Shared Function LParamToPoint(ByVal lParam As IntPtr) As Point
Return New Point(LOWORD(lParam.ToInt32()), HIWORD(lParam.ToInt32()))
End Function
Friend Shared Function HIWORD(ByVal value As Integer) As Short
Return CShort((value >> 16))
End Function
Friend Shared Function LOWORD(ByVal value As Integer) As Short
Return CShort((value And UShort.MaxValue))
End Function
我的问题是,当光标的x坐标变为负数时,LOWORD函数会因溢出异常而失败。根据MSDN,您应该使用GET_X_LPARAM和GET_Y_LPARAM宏而不是HI / LO WORD宏。但是在vb.net中没有这样的功能。
那该怎么办?
答案 0 :(得分:1)
溢出检查确实妨碍了这里。解决此问题的最佳方法是声明 union 。联合是一种具有重叠值的结构。优雅地允许您将IntPtr叠加在具有Short类型的结构成员之上。转换非常快,不会引发溢出异常。
将新模块添加到项目中,将其命名为NativeMethods并使其如下所示:
Imports System.Runtime.InteropServices
Imports System.Drawing
Module NativeMethods
<StructLayout(LayoutKind.Explicit)> _
Public Structure LParamMap
Public Sub New(value As IntPtr)
lparam = value
End Sub
Public Shared Widening Operator CType(value As LParamMap) As Point
Return New Point(value.loword, value.hiword)
End Operator
<FieldOffset(0)> Public lparam As IntPtr
<FieldOffset(0)> Public loword As Short
<FieldOffset(2)> Public hiword As Short
End Structure
End Module
我为Point投入了一个转换运算符,因为那是你真正想要的那个。一些测试代码可以解决这个问题:
Imports System.Drawing
Imports System.Diagnostics
Module Module1
Sub Main()
Debug.Assert(BitConverter.IsLittleEndian)
Dim test As New LParamMap(New IntPtr(-1))
Debug.Assert(test.loword = -1)
Debug.Assert(test.hiword = -1)
Dim pos As Point = test
Debug.Assert(pos = New Point(-1, -1))
End Sub
End Module
现在它变成了一个非常简单的单行,例如,覆盖了窗体的WndProc()方法:
Protected Overrides Sub WndProc(ByRef m As Windows.Forms.Message)
If m.Msg = &H200 Then
Dim pos As Point = New LParamMap(m.LParam)
'' etc...
End If
MyBase.WndProc(m)
End Sub