我已经设置了WH_MOUSE
挂钩,一切正常,但我无法将lparam
(指向MOUSEHOOKSTRUCT结构的指针)传递给我的HOOKPROC
函数在C#中正确翻译。
我的项目由两部分组成,一部分是C ++中的非托管部分,用于挂钩和过滤并通知我的托管代码。
问题是我得到的数据不正确,例如翻译lparam
后的奇怪X和Y坐标。 X大部分时间都是0,而Y在大多数情况下都是正确的,然后每隔一次点击我得到一个像198437245的X和-1的值等等。
请注意,我已经确认以下内容:
lparam
的值正确传递给我的C#代码(通过托管和非托管部件上的断点进行验证),例如:当鼠标事件发生时,它们都是2420528
。 lparam
的值是正确的,因为我可以使用以下方法将其成功转换为非托管部分中的有效坐标:
POINT pt = reinterpret_cast<MOUSEHOOKSTRUCT*>(lparam)->pt;
int x = pt.x; // correct, e.g. 250
int y = pt.y; // correct, e.g. 400
但是,使用以下翻译后,X和Y会出现乱码。
这是我的C ++ HOOKPROC
函数:
static LRESULT CALLBACK InternalMouseHookCallback(int code, WPARAM wparam, LPARAM lparam)
{
// filter messages
// ...
// send lparam to C# code
}
以下是我在C#中翻译lparam
的方法:
IntPtr lparam = ...; // passed from unmanaged code and confirmed to be the same value
MouseHookStruct mouseData =
(MouseHookStruct)Marshal.PtrToStructure(lparam, typeof(MouseHookStruct));
以下是我将POINT
和MOUSEHOOKSTRUCT
结构映射到C#的方式:
[StructLayout(LayoutKind.Sequential)]
public class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public class MouseHookStruct
{
public POINT pt;
public IntPtr hwnd;
public uint wHitTestCode;
public IntPtr dwExtraInfo;
}
我做错了什么?
更新
C ++中的{p>sizeof(MOUSEHOOKSTRUCT)
和C#中的Marshal.SizeOf(typeof(MouseHookStruct))
都打印20
。
我在Windows 7 64位上,但C#和C ++代码都编译并运行为32位。
答案 0 :(得分:2)
public class POINT
POINT是原生winapi中的结构。你倾向于将它声明为C#中的一个类。但不是在以下时间:
public class MouseHookStruct
{
public POINT pt;
// etc...
}
pt
字段现在是引用,而不是值。编组器将尝试取消引用MOUSEHOOKSTRUCT.pt,就像它是一个指针一样。非常值得注意的是,这不会产生更频繁的响亮btw,预计会出现AccessViolationException。也许你只是在辅助显示器上进行测试,这是不吉利的。
您必须将其声明为struct
。
答案 1 :(得分:0)
我发现,当执行流程到达我的C#代码时,多次调用Marshal.ReadInt32(lparam)
和Marshal.ReadInt32(lparam, 4)
来读取X
和Y
值并没有返回相同的值值。如果我正在快速阅读 ,我会得到正确的结果,但不会在下一次迭代中。
这让我相信,当lparam
到达我的C#代码并且我想处理它时,底层结构被释放,lparam
指向垃圾。
我不确定为什么我不幸的是大部分时间都得到正确的Y值,这真的让我失望并让我怀疑结构映射是不正确的,可能是因为它的内存后来被填充,而X的记忆立即被其他东西填满。
我通过读取C ++中的实际MOUSEHOOKSTRUCT
字节并将它们发送到我的C#代码而不是发送lparam
指针来解决我的问题。