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 Se
The solution here helped me but I had to edit it, also it's now shorter:
Also here a 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);
}
There is a good article about this on 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 sample shows how to use SendKeys effectively, but not how to discover the HWND of anything other than the top-most window.
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.
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).
MSDN explains the difference: 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:
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.
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:
#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);
}
}
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.
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)
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);