Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Sending keystrokes to other *non-focus* application

Sending keystrokes to other *non-focus* application

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestion
8 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    audi02
    wrote on last edited by
    #1

    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?

    #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;
    

    }

    A D A L 4 Replies Last reply
    0
    • A audi02

      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?

      #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;
      

      }

      A Offline
      A Offline
      Adam Roderick J
      wrote on last edited by
      #2

      keybd_event API is better to use :) refer msdn for more help

      Величие не Бога может быть недооценена.

      1 Reply Last reply
      0
      • A audi02

        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?

        #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;
        

        }

        D Offline
        D Offline
        David Crow
        wrote on last edited by
        #3

        audi02 wrote:

        But still problem - it doesn't put the letter on the notepad... why?

        Functions return values for a reason. Did you bother to check the return value from SendInput()?

        "Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown

        "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

        A 1 Reply Last reply
        0
        • A audi02

          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?

          #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;
          

          }

          A Offline
          A Offline
          amatecki
          wrote on last edited by
          #4

          SendInput and keybd_event functions insert keyboard events into the keyboard input stream and these events are received by active/focused window. If You would like to send keystroke to non-focused window You probably should send message directly to that window.

          1 Reply Last reply
          0
          • A audi02

            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?

            #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;
            

            }

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #5

            audi02 wrote:

            But still problem - it doesn't put the letter on the notepad... why?

            This is by Microsoft design. SendInput[^] and keybd_event[^] inserts keyboard input directly into the kernel input stream. The Windows subsystem Win32k.sys handles user input for usermode windows. Windows that do not have focus do not recieve the WM_KEYDOWN Notification[^], WM_CHAR Notification[^] nor the WM_KEYUP Notification[^]. If you want to send simulated keystrokes to windows that do not have focus you will need to either: 1.) Use the BringWindowToTop Function to bring the window to top before simulating keystrokes. 2.) Use the PostMessage Function[^] to do the dirty work of Win32k.sys This should do the trick:PostMessage(hTargetWnd,WM_CHAR,'g',0);
            Note that using PostMessage to simulate keyboard input is not recommended for a variety of reasons. Some of which include... hooks will not be called... GetKeyState and GetAsyncKeyState will not return correct results... GetQueueStatus with QS_INPUT will not be correct. In a nutshell... by using PostMessage you will be bypassing alot of the Win32k subsystems which could result in undesired behavior. Best Wishes, -David Delaune

            A 1 Reply Last reply
            0
            • D David Crow

              audi02 wrote:

              But still problem - it doesn't put the letter on the notepad... why?

              Functions return values for a reason. Did you bother to check the return value from SendInput()?

              "Old age is like a bank account. You withdraw later in life what you have deposited along the way." - Unknown

              "Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons

              A Offline
              A Offline
              audi02
              wrote on last edited by
              #6

              I checked by int res = SendInput(2, input, sizeof(INPUT)); the results is as expected res= 2.

              1 Reply Last reply
              0
              • L Lost User

                audi02 wrote:

                But still problem - it doesn't put the letter on the notepad... why?

                This is by Microsoft design. SendInput[^] and keybd_event[^] inserts keyboard input directly into the kernel input stream. The Windows subsystem Win32k.sys handles user input for usermode windows. Windows that do not have focus do not recieve the WM_KEYDOWN Notification[^], WM_CHAR Notification[^] nor the WM_KEYUP Notification[^]. If you want to send simulated keystrokes to windows that do not have focus you will need to either: 1.) Use the BringWindowToTop Function to bring the window to top before simulating keystrokes. 2.) Use the PostMessage Function[^] to do the dirty work of Win32k.sys This should do the trick:PostMessage(hTargetWnd,WM_CHAR,'g',0);
                Note that using PostMessage to simulate keyboard input is not recommended for a variety of reasons. Some of which include... hooks will not be called... GetKeyState and GetAsyncKeyState will not return correct results... GetQueueStatus with QS_INPUT will not be correct. In a nutshell... by using PostMessage you will be bypassing alot of the Win32k subsystems which could result in undesired behavior. Best Wishes, -David Delaune

                A Offline
                A Offline
                audi02
                wrote on last edited by
                #7

                Thanks for the detailed explanation. You are right about the PostMessage as I had tried it. 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 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. Maybe I will use the keystrokes simulation through PostMessage and the mouse with other way? Thanks.

                L 1 Reply Last reply
                0
                • A audi02

                  Thanks for the detailed explanation. You are right about the PostMessage as I had tried it. 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 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. Maybe I will use the keystrokes simulation through PostMessage and the mouse with other way? Thanks.

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  audi02 wrote:

                  It actually seems to be not practical

                  Correct. I would say that its not a good idea to use PostMessage for reliably simulating input.

                  audi02 wrote:

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

                  There are so many things happening in the windows subsystem (Win32k.sys) that it will be difficult to overcome undesired side-effects. For example when the window lost focus Win32k.sys internally keeps track of the window state, the subsystem knows not to put input messages into the window message que. When injecting rogue messages into the que you cannot always predict the outcome. I dont really have any positive advice to give you regarding injecting user input into a window. How do you know the author of notepad or ApplicationX did not check his window state when notepad recieves mouse input? You will also battle these types of issues as well. What type of application are you developing? Why can't you just bring the window to the top? Best Wishes, -David Delaune

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups