C# 我无法理解如何使用 SendMessage 或 PostMessage 调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/808540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
I can't understand how to use SendMessage or PostMessage calls
提问by Joao Oliveira
I need to simulate a keypress in a third party application. Let's say I have a C# application that needs to send an "8" to the Calculator application. I can't use the SendKeys of .Net or the keybd_event of win32 api because they both require the window to be the top active one, which is not case in my situation.
我需要在第三方应用程序中模拟按键。假设我有一个 C# 应用程序需要向计算器应用程序发送一个“8”。我不能使用 .Net 的 SendKeys 或 win32 api 的 keybd_event,因为它们都要求窗口是最活跃的窗口,而我的情况并非如此。
So that leaves me with the calls sendMessage and postMessage. I've been trying in the last three hours trying to get some results but right now I'm completely hopeless.
这样我就剩下调用 sendMessage 和 postMessage 了。在过去的三个小时里,我一直在尝试获得一些结果,但现在我完全没有希望了。
I have the following:
我有以下几点:
[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);
}
As you can see, I make four attempts to communicate with the Calculator. Using both sendMessage and PostMessage to close the window and also to send the key 7. Nothing works. The FindWindow Method works cause I get the handler of the app (I've even tryed launching the process myself and accessing it with process.MainWindowHandler, but no luck). There are no errors or exceptions, but it just doesn't do nothing in Calculator.
如您所见,我尝试了四次与计算器进行通信。使用 sendMessage 和 PostMessage 关闭窗口并发送密钥 7. 没有任何效果。FindWindow 方法有效,因为我获得了应用程序的处理程序(我什至尝试自己启动进程并使用 process.MainWindowHandler 访问它,但没有运气)。没有错误或异常,但它在 Calculator 中什么也不做。
I've also tried the exact same things with notepad and nothing changed too.
我也用记事本尝试过完全相同的东西,也没有任何改变。
回答by Jonathan Rupp
Any chance you're running this on a 64bit machine? If so, I believe all those 'int' values that are actually hWnds (first argument to Send/Post, return value from FindWindow) need to be IntPtr.
你有机会在 64 位机器上运行它吗?如果是这样,我相信所有那些实际上是 hWnds 的“int”值(发送/发布的第一个参数,从 FindWindow 返回值)都需要是 IntPtr。
After a bit more checking, it looks like for both SendMessage and PostMessage, the 1st, 3rd, and 4th parameters should be IntPtr instead of int (as well as the return values for all of these)
经过多一点检查,对于 SendMessage 和 PostMessage,第 1、3 和 4 个参数应该是 IntPtr 而不是 int(以及所有这些的返回值)
So, the right signatures would be:
所以,正确的签名是:
[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);
回答by Simon Gillbee
There is a good article about this on CodeProject: http://www.codeproject.com/KB/cs/SendKeys.aspx
CodeProject 上有一篇关于此的好文章:http: //www.codeproject.com/KB/cs/SendKeys.aspx
SendKeys is actually the correct idea, but you need to get the HWND (window handle) of the target window. This MSDN sampleshows how to use SendKeys effectively, but not how to discover the HWND of anything other than the top-most window.
SendKeys其实是正确的思路,但是需要获取目标窗口的HWND(窗口句柄)。这个 MSDN 示例展示了如何有效地使用 SendKeys,但没有展示如何发现除最顶部窗口之外的任何其他东西的 HWND。
Combine the two techniques, using the CodeProject example to locate the HWND of the application you want to target, then use the MSDN article to use SendKeys to send the key strokes (or mouse events) to the target application.
结合这两种技术,使用 CodeProject 示例定位您要定位的应用程序的 HWND,然后使用 MSDN 文章使用 SendKeys 将击键(或鼠标事件)发送到目标应用程序。
回答by Andrew Burns
Not directly your question, but the difference between SendMessage
and PostMessage
is that Send
is a blocking call, Post
returns immediately (before the receiving application has processed it).
没有直接的问题,但之间的区别SendMessage
,并PostMessage
是Send
是阻塞调用,Post
立即返回(前接受申请已处理的话)。
MSDN explains the difference: http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx
MSDN 解释了区别:http: //msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx
Also if you are on vista but not on .NET 3.0 that could also be a problem:
此外,如果您使用的是 vista 而不是 .NET 3.0,那也可能是一个问题:
The SendKeys class has been updated for the .NET Framework 3.0 to enable its use in applications that run on Windows Vista. The enhanced security of Windows Vista (known as User Account Control or UAC) prevents the previous implementation from working as expected.
SendKeys 类已针对 .NET Framework 3.0 进行了更新,以使其能够在 Windows Vista 上运行的应用程序中使用。Windows Vista 增强的安全性(称为用户帐户控制或 UAC)可防止以前的实现按预期工作。
回答by Olgar
Because it is an Edit Child window inside the notepad window. You should send messages to the right child window. It is a working example in C:
因为它是记事本窗口内的一个编辑子窗口。您应该将消息发送到右子窗口。这是 C 语言中的一个工作示例:
#include <windows.h>
#include <stdio.h>
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);
}
}
回答by Deniz
The solution here helped me butI had to edit it, also it's now shorter:
这里的解决方案帮助了我,但我不得不编辑它,现在它更短了:
Also herea usefull list of Virtual Key Codes
这里还有一个有用的虚拟键代码列表
[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);
}