我需要自动化第三方程序,唯一的操作方法是模拟点击某些按钮。
我通过使用EnumChildWindows
查找按钮的HWND句柄来完成此操作。当我找到“窗口”(按钮)时,我尝试使用SendMessageW
向BM_CLICK
发送Marshal.GetLastWin32Error
。这有效,我的测试显示按钮确实认为它被点击了。
问题出现在我的错误处理中。 BM_CLICK
消息没有给出反馈,所以我真的不知道它是否被点击过。我认为我应该勤奋并使用{{3}}检查任何错误代码。
这会返回ERROR_PROC_NOT_FOUND
,这不是我对成功处理消息的期望。
我按如下方式导入SendMessageW
:
[DllImport("User32.dll",
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.Winapi,
SetLastError = true)]
public static extern IntPtr SendMessageW(
HandleRef hWnd,
UInt32 Msg,
UIntPtr wParam,
IntPtr lParam);
拨打电话的代码是:
User32.SendMessageW(
buttonHandle,
(uint)ButtonControlMessages.BM_CLICK, // value of BM_CLICK = 0x00F5.
UIntPtr.Zero,
IntPtr.Zero);
int error = Marshal.GetLastWin32Error();
if (error != ErrorCodes.ERROR_SUCCESS) // love the name of this error code.
throw new Win32Exception(error);
我的测试只是使用附带按钮控件的简单Windows窗体。因此,我可以通过button.Handle
获得句柄。点击它;可能是这个错误完全不相关吗?
尽管摆脱它肯定会很好,我想要一些方法来确保对SendMessageW
的调用至少没有失败。
我使用的是带有.NET 4的Windows 7 x86-32。
答案 0 :(得分:3)
调用约定应为Stdcall
,但由于这是默认设置,因此您可以将其删除。
我认为您的SendMessage P / Invoke看起来有点奇怪,但这可能不是问题的原因。在任何情况下,我都会这样做:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
我认为这里发生的事情是SendMessage()
正在运行,但没有分配最后一个错误。 documentation for SendMessage()
提到错误的唯一内容是:
当UIPI阻止某条消息时,使用GetLastError检索的最后一个错误设置为5(访问被拒绝)。
SendMessage()
的返回值取决于发送的消息。在BM_CLICK
的情况下,显然没有发送消息。换句话说,你根本就没有得到任何反馈。