Knowledge Base Nr: 00088 SendKeysToWindow.cpp - http://www.swe-kaiser.de
Downloads:
Win32: tastendrücke an den eigenen prozess oder ein fremdes fenster schicken.
// hilfreich um aus einer c-dll oder c-programm fremdapplikationen zu triggern
// hilfreich um z.b. fremde dialoge (video for windows, printer setup, ...) fernzusteuern.
// (hier als beispiel ein programm das tastendrücke verschickt (batch-modus und
// active scripting bei IE 5.5 ein-und ausschaltet)
"tastendruecke an ein fenster schicken. z.b. einstellen von dialogen"
"als parameter wird eine ascii-datei mit folgendem inhalt angegeben:"
"zeile 2: fensterklasse (kann leer sein)"
"zeile 1: fenstername (kann leer sein)"
"zeile 3: tastencodes (getrennt mit # und endet mit #, ohne spaces)"
"zeile 4: zeit zwischen tastendruecken in millisekunden"
"gueltige codes sind:"
" A-Z, 0-9, F1-F12, TAB, SPACE, ENTER, ESC, DEL,"
" PGDN, PGUP, LEFT, RIGHT, UP, DOWN"
"modifizierer sind:"
" SHIFT+, ALT+, CTRL+"
"beispiele sind:"
" CTRL+ESC#UP#ENTER# (Shutdown dialog aufrufen)"
" CTRL+ALT+DEL# (Shutdown dialog aufrufen)"
" ie 5.5 active scripting ein:
IEFrame
ALT+T#O#CTRL+TAB#ALT+C#PGDN#PGDN#PGDN#PGDN#PGDN#PGDN#SPACE#ENTER#Y#ENTER#
50
" ie 5.5 active scripting aus:
IEFrame
ALT+T#O#CTRL+TAB#ALT+C#PGDN#PGDN#PGDN#PGDN#PGDN#PGDN#UP#SPACE#ENTER#Y#ENTER#
50
// bei verwendung von bUseThread kann asynchron weitergearbeitet werden
// - der thread wartet nTimeout_ms auf das fenster
// z.b. wartet 10s auf dialog 'drucken' und drückt 'ok'-button.
// int nErr = SendKeysToWindow("Drucken", "return#", 1, 10000);
int CProcessSupport::SendKeysToWindow(const char* lpszWindowClass, const char* lpszWindowTitle
, const char* lpszKeys, int nDelay_ms, int nTimeout_ms
, bool bUseThread)
{
//merken für SetupDialog() funktion
s_strWindowTitle = lpszWindowTitle;
s_strWindowClass = lpszWindowClass;
s_strSetupDlg = lpszKeys;
s_nDelay = nDelay_ms;
s_nTimeout = nTimeout_ms;
if (bUseThread)
{
HANDLE hnd = CreateThread(
0, // pointer to security attributes
0, // initial thread stack size
SetupDialog, // pointer to thread function
(void*)lpszWindowTitle, // argument for new thread
0, // creation flags
0 // pointer to receive thread ID
);
if (!hnd)
{
ASSERT(FALSE);
return -1;
}
}
else
{
return SetupDialog(0);
}
return 1;
}
DWORD WINAPI CProcessSupport::SetupDialog(LPVOID lpParameter)
{
HWND hwnd = NULL;
const char* pClass = 0;
const char* pTitle = 0;
HWND orgHwnd = 0;
if (!s_strWindowClass.IsEmpty())
pClass = s_strWindowClass;
if (!s_strWindowTitle.IsEmpty())
pTitle = s_strWindowTitle;
if (pClass || pTitle)
{
DWORD dwNow = ::GetTickCount();
while (!hwnd) //auf dialog warten
{
Sleep(5);
hwnd = ::FindWindow(pClass, pTitle);
if (::GetTickCount() - dwNow > s_nTimeout) //timeout handling
return -1;
}
orgHwnd = ::GetForegroundWindow();
::SetForegroundWindow(hwnd);
}
int nPressed = DoKeysPress(s_strSetupDlg, s_nDelay); //dialog einstellen
if (orgHwnd)
::SetForegroundWindow(orgHwnd);
return nPressed;
}
int CProcessSupport::DoKeysPress(const char* szKeys, int nDelay)
{
int nKeysPressed = 0;
char szError[100] = {0};
char szTmp[100] = {0};
bool bWithAlt = false;
bool bWithShift = false;
bool bWithCtrl = false;
int i = 0;
for (int n=0; szKeys[n]; n++)
{
szTmp[i++] = szKeys[n];
if (szKeys[n] == '+')
{
szTmp[i-1] = 0;
i = 0;
if (stricmp(szTmp, "ALT") == 0)
bWithAlt = true;
else if (stricmp(szTmp, "SHIFT") == 0)
bWithShift = true;
else if (stricmp(szTmp, "CTRL") == 0)
bWithCtrl = true;
else
{
sprintf(szError, "<%s> muss sein ALT, SHIFT oder CTRL", szTmp);
MessageBox(NULL, szTmp, "Fehler in DoKeysPress()", MB_OK|MB_ICONERROR);
return -1;
}
}
else if (szKeys[n] == '#')
{
szTmp[i-1] = 0;
i = 0;
int nWert = -1;
/* VK_0 thru VK_9 are the same as ASCII '0' thru '9' (0x30 - 0x39) */
/* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
if (stricmp(szTmp, "A") == 0)
nWert = 'A';
...
...
...
else if (stricmp(szTmp, "DOWN") == 0)
nWert = VK_DOWN;
else
{
sprintf(szError, "Unbekannter oder nicht implementierter VK_xxx Code <%s>", szTmp);
MessageBox(NULL, szError, "Fehler in DoKeysPress()", MB_OK|MB_ICONERROR);
return -2;
}
//event an process schicken
if (nWert > 0)
{
if (bWithAlt)
keybd_event(VK_MENU, 0, 0, 0);
if (bWithShift)
keybd_event(VK_SHIFT, 0, 0, 0);
if (bWithCtrl)
keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event(nWert ,0,0,0);
Sleep(20);
keybd_event(nWert ,0,KEYEVENTF_KEYUP,0);
if (bWithAlt)
keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0);
if (bWithShift)
keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
if (bWithCtrl)
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
}
Sleep(nDelay);
bWithAlt = false;
bWithShift = false;
bWithCtrl = false;
i = 0;
nKeysPressed++;
}
}
return nKeysPressed;
}