WM_MOUSEMOVE LParam低阶溢出

时间:2013-12-12 09:20:37

标签: .net vb.net winforms windows-ce compact-framework2.0

当我在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_LPARAMGET_Y_LPARAM宏而不是HI / LO WORD宏。但是在vb.net中没有这样的功能。

那该怎么办?

1 个答案:

答案 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