【发布时间】:2015-11-05 13:50:48
【问题描述】:
我已经设置了一个WH_MOUSE 钩子,一切正常,除了我无法将lparam(指向MOUSEHOOKSTRUCT 结构的指针)传递给我的HOOKPROC 函数,用C# 正确翻译。
我的项目由两部分组成,C++ 中的非托管部分执行挂钩、过滤和通知我的托管代码。
问题是我得到不正确的数据,例如翻译 lparam 后奇怪的 X 和 Y 坐标。 X 大部分时间是 0,而 Y 大部分时间是正确的,然后每隔一次点击我会得到一个值,比如 X 为 198437245,Y 为 -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++ 中的sizeof(MOUSEHOOKSTRUCT) 和C# 中的Marshal.SizeOf(typeof(MouseHookStruct)) 都打印20。
我使用的是 64 位的 Windows 7,但 C# 和 C++ 代码均已编译并以 32 位运行。
【问题讨论】:
-
您是否正在处理 InternalMouseHookCallback 中 nCode 小于零的情况?
-
@IInspectable,是的,在这种情况下,我只是
return CallNextHookEx(...), -
这应该是真正的问题。您是否比较了非托管
MOUSEHOOKSTRUCT和您的MouseHookStruct的大小?他们应该是一样的。同样,所有成员的偏移量应该相同。 -
@IInspectable,为什么
nCode会相关?如果 C++ 代码能够在同一个调用中正确翻译它,那么 C# 代码也应该能够做到这一点,而不管nCode的值如何。 -
@IInspectable,这是我不确定的部分,可能是翻译不正确的原因,我可能没有正确映射结构。我会检查运行时大小并稍后更新。
标签: c# c++ winapi hook marshalling