wayan
asked on
NickRepin or Others
This question relates to Ketuts q: Passing Keystrokes.
This is a simile of NicRepins solution:
Hi NickRepin
I have put you suggestions into action:
calc.exe is in the same DIR as Main and it startsup OK.
But we still do not seem to be able to pass keystrokes !!!!!!!!!!!!!!!!!!!!!.
Dialog consists of 3 buttons - IDOK, IDCANCEL and IDD_BUTTON1
I have compiled it with VC++ 5.0 Mulithreaded libs.
#include <windows.h>
BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK EnumProc(HWND, LPARAM);
static HWND hwndeng = 0;
static DWORD dwThreadId;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpszCmdLine, int cmdShow) {
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG 1), NULL, DlgProc);
return 0 ;
}
BOOL CALLBACK DlgProc(HWND hwnd, UINT mMsg, WPARAM wParam, LPARAM lParam) {
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartupInfo;
BOOL bCreate = FALSE;
siStartupInfo.cb = sizeof(STARTUPINFO);
siStartupInfo.lpReserved = NULL;
siStartupInfo.lpDesktop = NULL;
siStartupInfo.lpTitle = NULL;
siStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
siStartupInfo.wShowWindow = SW_SHOWNORMAL;
siStartupInfo.cbReserved2 = 0;
siStartupInfo.lpReserved2 = NULL;
switch(mMsg) {
case WM_INITDIALOG:
bCreate = CreateProcess("calc.exe", NULL, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL, NULL,
&siStartupInfo,
&piProcInfo);
if(bCreate == 0) {
MessageBox(NULL, "Calc - Process Not Found", NULL, MB_OK | MB_ICONEXCLAMATION);
return TRUE;
}
WaitForInputIdle(piProcInf o.hProcess , 3000);
dwThreadId = piProcInfo.dwThreadId;
return TRUE;
case WM_COMMAND:
switch(LOWORD (wParam)) {
case IDD_BUTTON1:
EnumThreadWindows(dwThread Id, EnumProc, 0);
if(hwndeng == NULL) {
MessageBox(NULL, "Calc - Enum Not Found", NULL, MB_OK | MB_ICONEXCLAMATION);
return TRUE;
}
EnableWindow(hwndeng, TRUE);
SendMessage(hwndeng, WM_SYSKEYDOWN, VK_F1, 0L);
return TRUE;
case IDOK:
case IDCANCEL:
CloseHandle(piProcInfo.hTh read); // not quite sure how to close process !!!!
CloseHandle(piProcInfo.hPr ocess);
ExitProcess(0);
EndDialog(hwnd, 0);
return TRUE;
}
break;
}
return FALSE;
}
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lp) {
if(GetParent(hwnd) == NULL) {
hwndeng = hwnd;
return FALSE;
}
else return TRUE;
}
This is a simile of NicRepins solution:
Hi NickRepin
I have put you suggestions into action:
calc.exe is in the same DIR as Main and it startsup OK.
But we still do not seem to be able to pass keystrokes !!!!!!!!!!!!!!!!!!!!!.
Dialog consists of 3 buttons - IDOK, IDCANCEL and IDD_BUTTON1
I have compiled it with VC++ 5.0 Mulithreaded libs.
#include <windows.h>
BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK EnumProc(HWND, LPARAM);
static HWND hwndeng = 0;
static DWORD dwThreadId;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpszCmdLine, int cmdShow) {
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG
return 0 ;
}
BOOL CALLBACK DlgProc(HWND hwnd, UINT mMsg, WPARAM wParam, LPARAM lParam) {
PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartupInfo;
BOOL bCreate = FALSE;
siStartupInfo.cb = sizeof(STARTUPINFO);
siStartupInfo.lpReserved = NULL;
siStartupInfo.lpDesktop = NULL;
siStartupInfo.lpTitle = NULL;
siStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
siStartupInfo.wShowWindow = SW_SHOWNORMAL;
siStartupInfo.cbReserved2 = 0;
siStartupInfo.lpReserved2 = NULL;
switch(mMsg) {
case WM_INITDIALOG:
bCreate = CreateProcess("calc.exe", NULL, NULL, NULL, FALSE,
NORMAL_PRIORITY_CLASS, NULL, NULL,
&siStartupInfo,
&piProcInfo);
if(bCreate == 0) {
MessageBox(NULL, "Calc - Process Not Found", NULL, MB_OK | MB_ICONEXCLAMATION);
return TRUE;
}
WaitForInputIdle(piProcInf
dwThreadId = piProcInfo.dwThreadId;
return TRUE;
case WM_COMMAND:
switch(LOWORD (wParam)) {
case IDD_BUTTON1:
EnumThreadWindows(dwThread
if(hwndeng == NULL) {
MessageBox(NULL, "Calc - Enum Not Found", NULL, MB_OK | MB_ICONEXCLAMATION);
return TRUE;
}
EnableWindow(hwndeng, TRUE);
SendMessage(hwndeng, WM_SYSKEYDOWN, VK_F1, 0L);
return TRUE;
case IDOK:
case IDCANCEL:
CloseHandle(piProcInfo.hTh
CloseHandle(piProcInfo.hPr
ExitProcess(0);
EndDialog(hwnd, 0);
return TRUE;
}
break;
}
return FALSE;
}
BOOL CALLBACK EnumProc(HWND hwnd, LPARAM lp) {
if(GetParent(hwnd) == NULL) {
hwndeng = hwnd;
return FALSE;
}
else return TRUE;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
If calc.exe is written by you, I thing it's much more easy to send WM_COMMAND rather than keybd events.
ASKER
Hi, NickRepin
Your code works fine, excellent answer.
Could you please add a comment on the following:
1) This commented out code.
//PostMessage(hwndeng, WM_KEYDOWN, VK_F1, MAKELPARAM(1,0x3b));
2) If calc.exe is written by you, I thing it's much more easy to send WM_COMMAND rather than keybd events.
I am working with ketut on this project and he was getting low on points --- Yes calc.exe (source) is in the public domain and has been extensively modified by us, and we wish to use a subset of it's functions and to completely integrate it into our GUI would take us a long time and effort.
What we want to do is invoke actions via menu accellerator strings like: Alt S, Alt Q, Alt Z etc.
As you know if you were doing this from the Keyboard, the Alt key would be depressed and the sequence would be S, Q, Z.
So that's it in a nutshell and thank you very much for your help so far.
Wayan
Your code works fine, excellent answer.
Could you please add a comment on the following:
1) This commented out code.
//PostMessage(hwndeng, WM_KEYDOWN, VK_F1, MAKELPARAM(1,0x3b));
2) If calc.exe is written by you, I thing it's much more easy to send WM_COMMAND rather than keybd events.
I am working with ketut on this project and he was getting low on points --- Yes calc.exe (source) is in the public domain and has been extensively modified by us, and we wish to use a subset of it's functions and to completely integrate it into our GUI would take us a long time and effort.
What we want to do is invoke actions via menu accellerator strings like: Alt S, Alt Q, Alt Z etc.
As you know if you were doing this from the Keyboard, the Alt key would be depressed and the sequence would be S, Q, Z.
So that's it in a nutshell and thank you very much for your help so far.
Wayan
ASKER
Just a thought on ExitProcess(0); have we got that right ?
If you need us to pose the previous comment and this one as a seperate Question, let us know.
Thanks again
wayan
If you need us to pose the previous comment and this one as a seperate Question, let us know.
Thanks again
wayan
ASKER
keybd_event(VK_MENU, 0x3B, 0, 0);
whats the significance of the OEM scan code 3B ???
whats the significance of the OEM scan code 3B ???
>1) This commented out code.
>>//PostMessage(hwndeng, WM_KEYDOWN, VK_F1, MAKELPARAM(1,0x3b));
Don't care about this.
>2) If calc.exe is written by you, I thing it's much more easy >to send WM_COMMAND rather than keybd events.
>to do is invoke actions via menu accellerator strings like: Alt >S, Alt Q, Alt Z etc.
As you see, sending keybd messages is not so easy (as I thought too). Moreover, may be some problem here. Eg, we are doing:
SetFocus(...);
// Theoretically, it's possible that other app sets focus to its window here (eg, MessageBox from Spooler) and next line will not post event to calc.exe.
keybd_event(...)
When you use the accelerator, you assing WM_COMMAND message to key combination, right?
Inside your app, there is a code like this:
case WM_COMMAND:
switch(code) {
case CMD_ALT_S:
// do something
It would better and reliable to send this command to your app, not the keybd message:
PostMessage(hwnd,WM_COMMAN D,CMD_ALT_ S,0);
This should work at 100%.
//whats the significance of the OEM scan code 3B ???
I'm not sure, but according the SDK we should supply it as the parameter. You may try do pass zero here, but it may not work.
>>//PostMessage(hwndeng, WM_KEYDOWN, VK_F1, MAKELPARAM(1,0x3b));
Don't care about this.
>2) If calc.exe is written by you, I thing it's much more easy >to send WM_COMMAND rather than keybd events.
>to do is invoke actions via menu accellerator strings like: Alt >S, Alt Q, Alt Z etc.
As you see, sending keybd messages is not so easy (as I thought too). Moreover, may be some problem here. Eg, we are doing:
SetFocus(...);
// Theoretically, it's possible that other app sets focus to its window here (eg, MessageBox from Spooler) and next line will not post event to calc.exe.
keybd_event(...)
When you use the accelerator, you assing WM_COMMAND message to key combination, right?
Inside your app, there is a code like this:
case WM_COMMAND:
switch(code) {
case CMD_ALT_S:
// do something
It would better and reliable to send this command to your app, not the keybd message:
PostMessage(hwnd,WM_COMMAN
This should work at 100%.
//whats the significance of the OEM scan code 3B ???
I'm not sure, but according the SDK we should supply it as the parameter. You may try do pass zero here, but it may not work.
I think posting WM_CLOSE message (not the ExitProcess) is the best way to close your app.
By the way, ExitProcess terminates the calling process, and you cannot terminate any other (child) process by using it.
By the way, ExitProcess terminates the calling process, and you cannot terminate any other (child) process by using it.
When using WM_COMMAND, you need no to call AttachThreadInput or SetFocus.
ASKER
thanks
ASKER