Thread: Sending keystrokes to other *non-focus* application

  1. #1
    Registered User
    Join Date
    Aug 2009
    Posts
    3

    Sending keystrokes to other *non-focus* application

    In order to send keystorkes or mouse clicks to other application that is not in focus, I found
    in the internet the concept of using SendInput while attaching my application thread to the application I want to control. Here is the short console program code for writing the letter 'g' on the notepad program.
    But still problem - it doesn't put the letter on the notepad... why?

    Code:
    #include "stdafx.h"
    #include "conio.h"
    #include "windows.h"
    
    void sendKey(WORD wVk)
    {
    	INPUT input[2];
    
    	input[0].ki.wVk = wVk;
    	input[0].ki.wScan = 0;
    	input[0].ki.dwFlags = 0; //press down;
    	input[0].ki.time = 0;
    	input[0].ki.dwExtraInfo = 0;
    	input[0].type = INPUT_KEYBOARD;
    
    	input[1].ki.wVk = wVk;
    	input[1].ki.wScan = 0;
    	input[1].ki.dwFlags = KEYEVENTF_KEYUP;
    	input[1].ki.time = 0;
    	input[1].ki.dwExtraInfo = 0;
    	input[1].type = INPUT_KEYBOARD;
    
    	SendInput(2, input, sizeof(INPUT));
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	TCHAR	sText[1024];
    	HWND	hTargetWnd;
    	DWORD   processID;
    	DWORD	threadID;
    	
    	
    	HWND hNotepadWnd = FindWindow(NULL,  L"Untitled - Notepad");
        hTargetWnd=FindWindowEx(hNotepadWnd,NULL,L"Edit",NULL);
    	threadID = GetWindowThreadProcessId(hTargetWnd , &processID);	
    	if(hTargetWnd)
    	{
    		wsprintf(sText, L"Target window found\nWindow = %p\nprocessID = %x\nThreadID = %x\n",hTargetWnd,processID,threadID);
    		wprintf(L"%s",sText);
    		
    			  if(AttachThreadInput( GetCurrentThreadId(), threadID,true))
    			  {
    				sendKey('G');
    				AttachThreadInput(GetCurrentThreadId(),threadID,   false);
    			  }
    	}
    	else
    	{
    		wprintf(L"Window Notepad wasn't found\n");
    	}
    
    	// if there was SendInput, it also should be seen here
    	while(_kbhit())
    	{
    		wprintf(L"%c",getch());
    	}
    
    	// wait for keystroke to exit
    	while(!_kbhit());
    
    	return 0;
    }
    Last edited by Salem; 08-05-2009 at 11:58 PM. Reason: Removed colour from code - it adds nothing, if you apply it to the whole block

  2. #2
    Registered User
    Join Date
    Mar 2003
    Location
    UK
    Posts
    170
    If you have the handle to the NotePad application then try posting a WM_CHAR message, for example:

    Code:
          PostMessage( hTargetWnd, WM_CHAR,  'g', 0 );

  3. #3
    Registered User
    Join Date
    Aug 2009
    Posts
    3
    Thanks, that may work.

    I tried to work with PostMessage and the messages are indeed, received by the notepad.
    But I found that in this case, I must know what the target program is designed to receive.
    I tried for example to send WM_LBUTTONDOWN in order to simulate left mouse button click, but the target program didn't react to this even it received it.
    When I checked, using Spy++ the messages it accepts when the mouse is really on it, I found the messages are much more complicated than just WM_LBUTTONDOWN and includes WM_NCHITTEST, WM_SETCURSOR and more. Why it is not just WM_LBUTTONDOWN ? I don't know. it's first time for me in this subject.

    If you can give some description on this behavior and a solution, that will be great.
    Thanks

  4. #4
    Registered User Joelito's Avatar
    Join Date
    Mar 2005
    Location
    Tijuana, BC, México
    Posts
    310
    Quote Originally Posted by Scarlet7 View Post
    If you have the handle to the NotePad application then try posting a WM_CHAR message, for example:

    Code:
          PostMessage( hTargetWnd, WM_CHAR,  'g', 0 );
    If I want to send "Alt+B", for example?
    * PC: Intel Core 2 DUO E6550 @ 2.33 GHz with 2 GB RAM: Archlinux-i686 with xfce4.
    * Laptop: Intel Core 2 DUO T6600 @ 2.20 GHz with 4 GB RAM: Archlinux-x86-64 with xfce4.

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by audi02 View Post
    Thanks, that may work.

    I tried to work with PostMessage and the messages are indeed, received by the notepad.
    But I found that in this case, I must know what the target program is designed to receive.
    I tried for example to send WM_LBUTTONDOWN in order to simulate left mouse button click, but the target program didn't react to this even it received it.
    When I checked, using Spy++ the messages it accepts when the mouse is really on it, I found the messages are much more complicated than just WM_LBUTTONDOWN and includes WM_NCHITTEST, WM_SETCURSOR and more. Why it is not just WM_LBUTTONDOWN ? I don't know. it's first time for me in this subject.

    If you can give some description on this behavior and a solution, that will be great.
    Thanks
    I think that WM_SETCURSOR and similar are always given to your program, even if you don't catch them. I would expect Notepad to listen for that so that it knows where you're clicking (to move the cursor to that spot, on a button, etc.)

  6. #6
    Registered User
    Join Date
    Mar 2003
    Location
    UK
    Posts
    170
    I tried for example to send WM_LBUTTONDOWN in order to simulate left mouse button click, but the target program didn't react to this even it received it.
    What reaction were you expecting, or hoping for on a left mouse button?

    If to bring the NotePad to the top window the use the following:
    Code:
        SetForegroundWindow( hTargetWnd );
    If to set the cursor position then WM_LBUTTONDOWN will work, but only the x y coordinates within the text region, the following will set the cursor coords to x=0 y=0 (top left of window):
    Code:
        PostMessage(hTargetWnd, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(0,0));
        PostMessage(hTargetWnd, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(0,0));
    The following code example will bring the NotePad to the front and write 3 lines the insert some text into line 1:
    Code:
    void SendString(HWND h, char *text)
    {
        int len = strlen(text);
        for(int i = 0; i < len; i++)
            PostMessage(h, WM_CHAR, text[i], 0);
    }
    
    void SetCursor(HWND h, short x, short y )
    {
        PostMessage(h, WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x,y));
        PostMessage(h, WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x,y));
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        ...
    
        SetForegroundWindow(hTargetWnd);
    
        SetCursor(hTargetWnd, 0,0);
    		
        SendString(hTargetWnd, "Hello World line 1\n");
        SendString(hTargetWnd, "Hello World line 2\n");
        SendString(hTargetWnd, "Hello World line 3\n");
    
        SetCursor(hTargetWnd, 20,0);
    
        SendString(hTargetWnd, "(Inserted)");
    
        ...
    }
    Last edited by Scarlet7; 08-06-2009 at 04:44 AM.

  7. #7
    Registered User
    Join Date
    Aug 2009
    Posts
    3
    Thanks Scarlet7.

    1) It works.
    2) I don't want to make the target program (NotePad in this example) focused , so we can use the PostMessage without SetForegroundWindow(hTargetWnd) and SetCursor(hTargetWnd, 0,0)
    3) I found that the reasone I didn't have the corrrect response to WM_LBUTTONDOWN etc' was because I didn't use the correct child window - my mistake!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sending keystrokes to another view
    By azeemanwer in forum C++ Programming
    Replies: 2
    Last Post: 08-28-2007, 10:41 AM
  2. sending a string as keyboard keystrokes wrongly
    By hanhao in forum C++ Programming
    Replies: 1
    Last Post: 06-29-2007, 07:49 AM
  3. Pass Fake Keystrokes to 3'rd Party Application
    By Jattie in forum Windows Programming
    Replies: 11
    Last Post: 10-31-2002, 06:53 PM
  4. Replies: 1
    Last Post: 06-06-2002, 04:17 PM
  5. Sending Keystrokes
    By evilmonkey in forum C++ Programming
    Replies: 1
    Last Post: 01-31-2002, 01:18 PM