我想将左键单击翻译为右键单击
当我做这样的描述时:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
if(nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam && doRight) {
doRight = false;
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
mouse_event(/*right down + right up*/8 | 16, hookStruct.pt.x, hookStruct.pt.y, 0, 0);
return new IntPtr(1);
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
对mouse_event的调用因PInvokeStackImbalance-Exception而失败,我猜,我应该关心它。
因为通常PInvokeStackImbalance是由于错误的导入签名而导致的,这是我的:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
在这种情况下,我正常的隔离问题的方法失败了 - 因为mouse_event-call本身可以正常工作,而左键单击的垃圾也是如此。当结构超过各部分的总和时,我讨厌它......
答案 0 :(得分:2)
mouse_event定义为:
VOID WINAPI mouse_event(
__in DWORD dwFlags,
__in DWORD dx,
__in DWORD dy,
__in DWORD dwData,
__in ULONG_PTR dwExtraInfo
);
WINAPI表示StdCall,DWORD是uint,ULONG_PTR表示UIntPtr。所以它应该是正确的:
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, UIntPtr dwExtraInfo);
问题是long在C#中定义为64位,而(u)int是32位。 (U)IntPtr是32位或64位,具体取决于操作系统的位数。
编辑:换句话说,您向该函数传递了太多数据。由于被调用者清理堆栈,PInvoke注意到并非所有内容都从堆栈中删除。它为你做了(但你传递了错误的数据,所以函数可能做了一些不同于你想要的东西)并警告你。
答案 1 :(得分:2)
Internet上存在错误的p / invoke声明 lot 。它们通常在VB6中开始。在该语言中,Integer为16位,Long为32位。回到在16位操作系统上运行的VB1。它们在VB.NET或C#中无法正常工作。
堆栈不平衡MDA专门用于捕获此类错误声明,但它是一个选项(Debug + Exceptions)。如果只有一个参数或传递大量零,则实际调用会起作用。不幸的是,代码在通话后保持正常运行的可能性也不错。当方法返回时,堆栈指针值会自行更正。你可以得到一些非常棘手的问题。
答案 2 :(得分:1)
mouse_event签名应该是这样的
public static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, IntPtr dwExtraInfo);