我无法理解如何使用SendMessage或PostMessage调用

我需要在第三方应用程序中模拟按键。 假设我有一个需要向Calculator应用程序发送“8”的C#应用​​程序。 我不能使用.Net的SendKeys或win32 api的keybd_event,因为它们都要求窗口是最活跃的窗口,这在我的情况下不是这种情况。

这样我就可以调用sendMessage和postMessage。 我在过去的三个小时里一直试图获得一些结果,但现在我完全没有希望了。

我有以下内容:

[DllImport("user32.dll")] public static extern int FindWindow(string lpClassName,string lpWindowName); [DllImport("user32.dll")] public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam); [return: MarshalAs(UnmanagedType.Bool)] [DllImport("user32.dll", SetLastError = true)] public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam); private void button1_Click(object sender, EventArgs e) { const int WM_KEYDOWN = 0x100; const int WM_SYSCOMMAND = 0x018; const int SC_CLOSE = 0x053; int WindowToFind = FindWindow(null,"Calculator"); int result = SendMessage(WindowToFind, WM_SYSCOMMAND, SC_CLOSE, 0); Boolean result2 = PostMessage(WindowToFind, WM_SYSCOMMAND, SC_CLOSE, 0); int result3 = SendMessage(WindowToFind, WM_KEYDOWN,((int)Keys.NumPad7), 0); Boolean result4 = PostMessage(WindowToFind, WM_KEYDOWN, ((int)Keys.NumPad7), 0); } 

如您所见,我尝试四次与计算器进行通信。 使用sendMessage和PostMessage关闭窗口并发送密钥7.没有任何作用。 FindWindow方法的工作原因是我得到了应用程序的处理程序(我甚至尝试自己启动进程并使用process.MainWindowHandler访问它,但没有运气)。 没有错误或exception,但它在Calculator中没有任何作用。

我也用记事本尝试了完全相同的东西,也没有任何改变。

你有机会在64位机器上运行吗? 如果是这样,我相信所有那些实际上是hWnds的’int’值(发送/发布的第一个参数,从FindWindow返回值)需要是IntPtr。


经过多次检查后,看起来对于SendMessage和PostMessage,第1,第3和第4个参数应该是IntPtr而不是int(以及所有这些参数的返回值)

所以,正确的签名将是:

 [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName,string lpWindowName); [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); 

在CodeProject上有一篇很好的文章: http : //www.codeproject.com/KB/cs/SendKeys.aspx

SendKeys实际上是正确的想法,但你需要获得目标窗口的HWND(窗口句柄)。 此MSDN示例演示如何有效地使用SendKeys,但不显示如何发现除最顶层窗口之外的任何内容的HWND。

结合这两种技术,使用CodeProject示例找到要定位的应用程序的HWND,然后使用MSDN文章使用SendKeys将键击(或鼠标事件)发送到目标应用程序。

不是直接你的问题,但SendMessagePostMessage之间的区别在于Send是一个阻塞调用, Post立即返回(在接收应用程序处理它之前)。

MSDN解释了差异: http : //msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx

此外,如果你在Vista上但不在.NET 3.0上也可能是一个问题:

已针对.NET Framework 3.0更新了SendKeys类,以便在Windows Vista上运行的应用程序中使用它。 Windows Vista的增强安全性(称为用户帐户控制或UAC)可防止先前的实施按预期工作。

因为它是记事本窗口内的编辑子窗口。 您应该将消息发送到正确的子窗口。 这是C中的一个工作示例:

 #include  #include  void main(void) { STARTUPINFO si; PROCESS_INFORMATION pi; HWND mainwnd,editwnd; char c; si.cb=sizeof(si); si.lpReserved=NULL; si.lpDesktop=NULL; si.lpTitle=NULL; si.dwFlags=0; si.cbReserved2=0; si.lpReserved2=NULL; if(!CreateProcess("c:\\windows\\notepad.exe",NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi)) { printf("Failed to run app"); return; } WaitForInputIdle(pi.hProcess,INFINITE); mainwnd=FindWindow(NULL,"Untitled - Notepad"); if(!mainwnd) { printf("Main window not found"); return; } editwnd=FindWindowEx(mainwnd,NULL,"Edit",""); if(!editwnd) { printf("Edit window not found"); return; } for(c='1';c<='9';c++) { PostMessage(editwnd,WM_CHAR,c,1); Sleep(100); } } 

这里的解决方案帮助了我, 我不得不编辑它,现在它也缩短了:

此处还有一个有用的虚拟密钥代码列表

  [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam); private void button1_Click(object sender, EventArgs e) { const int WM_SYSKEYDOWN = 0x0104; IntPtr WindowToFind = FindWindow(null, "Calculator"); PostMessage(WindowToFind, WM_SYSKEYDOWN, ((int)Keys.NumPad7), 0); }