Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Easy way to simulate keyboard press and release keys

0.00/5 (No votes)
6 Mar 2013 1  
An easy way to simulate keyboard press & release keys to another application

Introduction

This article describes an easy way to simulate keyboard press and release keys to another application. It uses the SendInput API for simulating keyboard press and release keys.

To illustrate this technique we will show how to automatically run calc.exe and simulate add x and y and get the result back.

Application Latching

We will run the application using the CreateProcess API and save the process ID to close it.

void startProcess(DWORD &processPid,char*mProcess)
{
 BOOL bWorked;
 STARTUPINFO suInfo;
 PROCESS_INFORMATION procInfo;
 memset (&suInfo, 0, sizeof(suInfo));
 suInfo.cb = sizeof(suInfo);
 bWorked = ::CreateProcess(mProcess,
      NULL,  
      NULL,
      NULL,
      FALSE,
      NORMAL_PRIORITY_CLASS,
      NULL,
      NULL,
      &suInfo,
      &procInfo);
 if (procInfo.dwThreadId = NULL)
 {
 }
 processPid = procInfo.dwProcessId;
}

Making the application in foreground

Retrieves a handle to the top-level window whose window name matches the AppName using FindWindow, then activate the application using SetForegroundWindow so the Keyboard input is directed to the window .

HWND windowHandle = FindWindow(0, AppName);
if(windowHandle == NULL)
{
    return -1;
}
SetForegroundWindow(windowHandle); 

Simulate keyboard press and release keys

Using SendChar, SendInt, SendText based on the SendInput Windows API, we will simulate keyboard press and release keys.

INPUT ip;
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wVk = CHAR_ID;
//For key press Flag=0
ip.ki.dwFlags = 0;
SendInput(1, &ip, sizeof(INPUT));
//For key relese Flag = KEYEVENTF_KEYUP
ip.ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(1, &ip, sizeof(INPUT));

Simulation sequence

First send x then + then Y and press Enter, then copy the result in Clipboard using Ctrl+C.

SendInt(x);
Sendchar(VK_ADD);
SendInt(y);
Sendchar(VK_RETURN);    

PressKey(VK_CONTROL);
Sendchar('C');
ReleseKey(VK_CONTROL);  

Retrieve the Result from Clipboard

Using GetClipboardData, retrieve the result from the Clipboard.

int GetClipboardText(char*ClipboardText)
{
    HANDLE clip;
    if (OpenClipboard(NULL))
    {
        clip = GetClipboardData(CF_TEXT);
        sprintf(ClipboardText,"%s",clip);
        return 0;
    }
    return -1;
}

Closing the application

Enumerate all windows using the EnumWindowsProc callback function, passing the PID of the process you started earlier.

void killProcess(DWORD processPid)
{
  Sleep(100);
  HANDLE ps = OpenProcess( SYNCHRONIZE|PROCESS_TERMINATE,
                    FALSE, processPid);
  EnumWindows(EnumWindowsProc, processPid);
  CloseHandle(ps) ;
}

Then in EnumWindowsProc, send the WM_CLOSE message to close it.

BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
  Sleep(1);
  DWORD wndPid;
  char Title[1024];
  // This gets the windows handle and pid of enumerated window.
  GetWindowThreadProcessId(hwnd, &wndPid);
  // This gets the windows title text
  // from the window, using the window handle
  GetWindowText(hwnd,Title,1024);
  // this makes sure that the PID matches that PID we started, and window
  // text exists, before we kill it . I don't think this is really needed,
  // I included it because some apps have more than one window.
  if ( wndPid == (DWORD)lParam && strlen(Title) != 0)
  {
    // Please kindly close this process
    ::PostMessage(hwnd, WM_CLOSE, 0, 0);
    //cout<<"Please kindly close this process"<<endl;
    return false;
  }
  else
  {
    //cout<<"Keep enumerating"<<endl;
    // Keep enumerating
    return true;
  }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here