CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Jul 2009
    Posts
    5

    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 Marc G; August 4th, 2009 at 07:30 AM. Reason: Added code tags

  2. #2
    Join Date
    Jul 2005
    Posts
    266

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

    You need to call SetFocus right after you connect the threads in order for the SendInput to take place in the Notepad app:
    Code:
      if(AttachThreadInput( GetCurrentThreadId(), threadID,true))
    			  {
                                    SetFocus(hTargetWnd);
    				sendKey('G');
    				AttachThreadInput(GetCurrentThreadId(),threadID,   false);
    			  }

  3. #3
    Join Date
    Dec 2008
    Posts
    144

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

    Why don't you just send WM_CHAR message to the windnow? You will have the same result.
    Code:
    PostMessage(hTargetWnd, WM_CHAR, (WPARAM)'G', 0);

  4. #4
    Join Date
    Jul 2005
    Posts
    266

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

    Quote Originally Posted by Nikitozz View Post
    Why don't you just send WM_CHAR message to the windnow? You will have the same result.
    Code:
    PostMessage(hTargetWnd, WM_CHAR, (WPARAM)'G', 0);
    Because that is not the correct way to send keystrokes There can be many situations in which it won't work, also you cannot send keys like SHIFT,CTRL, etc

  5. #5
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

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

    To debug this, try setting focus on the target window and then use SendInput to send the keystrokes.

    If that works, then look at the AttachThreadInput code. If it doesn't work, revisit the SendInput code.

  6. #6
    Join Date
    Jul 2009
    Posts
    5

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

    Quote Originally Posted by kolkoo View Post
    You need to call SetFocus right after you connect the threads in order for the SendInput to take place in the Notepad app:
    Code:
      if(AttachThreadInput( GetCurrentThreadId(), threadID,true))
    			  {
                                    SetFocus(hTargetWnd);
    				sendKey('G');
    				AttachThreadInput(GetCurrentThreadId(),threadID,   false);
    			  }
    In case we change the target application to be in focuse, there is no need to use AttachThreadInput.
    I just use
    SetForegroundWindow(hTargetWnd);
    SetFocus(hTargetWnd);
    and everithing is ok.

    But I don't want to change the target application to be in focus because I'm working from my application which is in focus. It will cause to my application which the user using to be changed into background while the user using it.
    Last edited by audi02; August 5th, 2009 at 05:32 PM.

  7. #7
    Join Date
    Jul 2009
    Posts
    5

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

    Quote Originally Posted by Nikitozz View Post
    Why don't you just send WM_CHAR message to the windnow? You will have the same result.
    Code:
    PostMessage(hTargetWnd, WM_CHAR, (WPARAM)'G', 0);
    You are right. But using PostMessage arise other problems: It actually seems to be not practical for me because it seems that I must know what the target program is designed to receive while I only want to send the basic events of mouse and keys.

    Example:
    I tried for example to send WM_LBUTTONDOWN using PostMessage 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 someone can give some description on this behavior and a solution, that will be great.
    Maybe I will use the keystrokes simulation through PostMessage and the mouse with other way?

    Thanks.

  8. #8
    Join Date
    Apr 1999
    Posts
    27,449

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

    Quote Originally Posted by audi02 View Post
    Maybe I will use the keystrokes simulation through PostMessage and the mouse with other way?
    Let me ask you, why do you think there is a function called "SendInput" if sending keystrokes is as easy as posting a couple of messages?

    The answer is simple -- sending keystrokes is not simple. That's why Windows has an API to do it. Keystrokes go through a complex process of up/down presses, translations, accelerators, special keys, etc. when a key is pressed.

    If you read the API docs clearly, you will see that all of those messages you're attempting to send are not to be generated by you explicitly -- the Windows OS is the one that generates those messages (WM_LBUTTONUP, WM_KEYDOWN, etc.). Again, why would we need SendInput() if keystroke processing is so easy?

    Regards,

    Paul McKenzie

  9. #9
    Join Date
    Jul 2009
    Posts
    5

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

    Thanks for all response

    Conclusions from all response and my tests:

    1) In order to control other application which is not in focus and while *keep it non-focus* - use PostMessage.

    2) In order to control well the other application - check well the child window that is needed to have the message - my problem with the mouse events caused because I didn't send it to the correct child window.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured