|
I am trying to create application to run as service and when user hit key like CTRL-F1 or CTRL-F2, I want the service to send keyboard message to windows so that I don't have to type my user/pass everytime I have to log in to softwares at work.
I still have to figure out how to create system wide hook to intercept the key, but your application showed me how to use keybd_event function.
I looked it up on the MSDN and it says I should use SendInput() function instead because keydb_event is superseded.
|
|
|
|
|
It's a long time since this source code is published. Has anyone now solved focus problem? If yes then please update the code. (There are now many virtual keyboard that have no focus problem)
Mahbub
|
|
|
|
|
Here's one go at it:
http://home.worldonline.dk/troels_k/code/keyboard.zip
|
|
|
|
|
The keyboard works fine as far as I can tell with everything except Internet Explorer! If you are trying to type into the Address Bar in IE (5.5) only the last key hit is shown in the edit box. And no keystrokes can get through to any web page. Unfortunatly I need to do a Kiosk type application with a web browser, and I can't figure out how to have an on-screen keyboard for the touchscreen!
Corey Cooper
CoreyC@InnovativeDesign.com
|
|
|
|
|
nklnkln
|
|
|
|
|
I've seen the same problem and also for me it's important to understand how to solve this! I think it's a focus problem... Have you seen the Windows XP virtual keyboard? It seems to works well but the keyboard doesn't seem to be focused on. The focus seems to remain always to the foreground window!
Any suggestions?
|
|
|
|
|
You have to prevent to get the focus. See thread "Focus Problem and Flashing" from 18:59 20 Jan '04.
With this patch the IE works.
|
|
|
|
|
Hi,
I do not find that the "Focus Problem and Flashing" solve the problem that the other application looses focus. It prevents our application to get the focus, but it does not prevent the other application from being deactivated.
The XP keyboard and other works fine without the target application looses focus, and that is very important in some situations.
Please update me on this one, if anyone has found the solution.
OleM
|
|
|
|
|
The following is taken from an email I put together a while ago for someone asking how I solved this problem:
I did solve this problem, but only for my particular app which was an MFCApp, using CHTMLView. I think the methodology I used would apply to other situations. Note however, that this code is very specific for my application, I have not tried to make this reusable or generic, I had a deadline that was looming, and I banged this out.
I was trying to type into a webbrowser object hosted by my own app It failed because the WebBrowser is a com object hosted by the MFC generated window that Windows reports as having the focus. How normal keyboard messages get through, I don't know.
Using Spy++ I found that the window I create (the CHtmlView derived window) has a child, which has a child, which has a child that is the actual WebBrowser object. So since I have a pointer to the window that I created, and knew that was where I wanted all my keystrokes to go, I created the following function (CConfigHtml is derived from CHtmlView):
(the operative portion here is the routine that searches for the window with the Class Name of "Internet Explorer_Server")
Note also there are some lines commented out leftover from debugging that I thought might be useful as comments.
void CConfigHtml::Search4RealBrowserhWnd()
{
try{
TRACE0("===== CConfigHtml::Search4RealBrowserhWnd!\n");
if (m_RealBrowserhWnd == NULL){
char *pbuff;
CString cstr;
m_RealBrowserhWnd = m_hWnd;
bool loop = TRUE;
while(loop) {
m_RealBrowserhWnd = ::FindWindowEx(
m_RealBrowserhWnd, //HWND hwndParent, // handle to parent window
NULL, //HWND hwndChildAfter, // handle to child window
NULL, //"Shell Embedding",//LPCTSTR lpszClass, // class name
NULL //LPCTSTR lpszWindow // window name
);
if (m_RealBrowserhWnd != NULL){
pbuff = cstr.GetBuffer(52);
int ret = ::GetClassName( m_RealBrowserhWnd, pbuff, 50);
cstr.ReleaseBuffer();
if (0 != ret){
// ErrorReportf(">>>>>>>>>>>>>GOT Browser Window Handle %#x = %s",(int)m_RealBrowserhWnd,pbuff);
if (cstr.CompareNoCase("Internet Explorer_Server")==0)
loop = FALSE; // That's it, we are done!
}
else
ErrorReportf("Window %#x has no name returned",(int)m_RealBrowserhWnd);
}
else {
SystemErrorReport("Error: getting Window Handle! ");
loop = FALSE;
}
}
}
}
catch(...){
AfxMessageBox("Exception Thrown Getting the Browser Window Handle!");
m_RealBrowserhWnd = NULL;
}
}
And then my version of ReleaseFocus() will only work with my predefined windows:
bool CConfigDlg::ReleaseFocus()
{
if ((HTMLControl != NULL) && IsWindow(HTMLControl->m_RealBrowserhWnd) ) {
HWND wnd = ::GetForegroundWindow();
if(IsWindow(wnd)) {
if(wnd == HTMLControl->m_RealBrowserhWnd) {
TRACE0("Already forground!");
return TRUE;
}
}
}
else if ((EditWithFocus != NULL) && (IsWindow(EditWithFocus->m_hWnd))){
if (NULL == ::SetFocus(EditWithFocus->m_hWnd))
AfxMessageBox("SetFocus Failed!");
}
else {
TRACE0("None of the Focus Pointers are valid!");
return FALSE;
}
return TRUE;
}
I hope I made this clear enough. Since IE is really just a big ActiveX host, the same routine should work, although I had the advantage of already having a handle to the window I knew was hosting the webbrower object. If you are trying to write to IE, you might combine the two routines so that each time ReleaseFocus() is called, it checks to see if a child window of the window it is about to set the focus to has a name of "Internet Explorer_Server". Again, the main thing is play with Spy++ and find the windows and messages, and go from there.
I hope this helped.
|
|
|
|
|
This is great man thanks ive been trying to manipulate standard input and this is the BEST!
Keep up the good work.
Ryan
|
|
|
|
|
I have learned so much from Mr. Randy More's article!
I have some other problems about the OEM scan code(I wonder if this is the right name)of the keys on the keyboard.
For example, the code '0x61' stands for the key 'a' on the keyboard,what about the code of the combination of 'Alt+a'?
I found on books that the code for 'Ctrl-Break' is 0x03, but that is all I got.
I would like to know what are the OEM scan codes that stand for two key combinations of the keyboard.
Or is this any other way to send such information from my code?
Thanks a lot!
|
|
|
|
|
The scan code will still be '0x61' but there will be a flag set for the Alt key being pressed. I'm pulling this from memory but I remember many a fun evening pulling this apart for a project. Ctrl, Shift, and detecting the difference between NumPad keys is also handled this way.
Petzold's Keyboard example from our Win31 days is a really good way to see how this works. You can also use the Proises (sp?) MFC version that has a similar Keyboard example.
|
|
|
|
|
An alternative to the implementation in this example that used the Keybd_event function may be the SendInput function:
UINT SendInput(
UINT nInputs, // count of input events
LPINPUT pInputs, // array of input events to insert
int cbSize // size of an INPUT structure
);
I like SendInput for simulating Key events since I can stuff the queue in the order I want and just get away with virtual key codes. For example, If I use SendInput to stuff the Keyboard input buffer with the following order of events:
KEY_DOWN event for 0x10 // virtual key code for shift,
KEY_DOWN event for 0x31 // Virtual key code for 0,
KEY_UP event for 0x10
KEY_UP event for 0x31
I end up with the "!" placed in the window with the current focus (and there was much rejoicing). I like this approach a bit better since it maps to the way we humans would enter it on the keyboard and I avoid any higher level thought process, bit twiddling, etc. SendInput uses the INPUT struct which contains a union to structs for keyboard events (ki), mouse events (mi) and hardware events (hi). Hopefully, the hastily typed out code fragment that I am including for my discussion isn't too badly reasoned (long day and brain like mush ...). This fragment assumes you have done the proper prerequisite work to get your environment set up not to choke on SendInput, the associated INPUT struct, and the ki struct ... and hopefully gives you an idea of implementing SendInput versus Keybd_event:
// Purpose: SendKey - Sends key events to the window with the current
// focus.
// Uses: SendInput Declared in winuser.h; Import Library: user32.lib.
// Compatibility: NT 4.0(SP3)or later;Win 98 or later;CE Unsupported
// Args:
// vk = Virtual Keycode for simulated key event,
// shift = vk code for shift or pass 0 if shift is not simulated
// control = vk code for control or pass 0 in no control
// alt = you guessed it ... vk code for alt or pass 0
void Sendkey(int vk, int shift, int control, int alt);
void SendKey(int vk, int shift, int control, int alt)
{
// special key ... the vk code holder for shift,control,or alt.
int spkey;
// A key is either shifted, control or alt. Determine which and
// build the keybuffer to accept to keys for this event.
if (shift || control || alt)
{
if (shift) spkey = shift;
else if (control) spkey = control;
else spkey = alt;
INPUT *buffer = new INPUT[4]; //allocate a buffer
buffer->type = INPUT_KEYBOARD;
buffer->ki.wVk = spkey;
buffer->ki.wScan = 0;
buffer->ki.time = 0;
buffer->ki.dwFlags = 0;
buffer->ki.dwExtraInfo =0;
(buffer+1)->type = INPUT_KEYBOARD;
(buffer+1)->ki.wVk = vk;
(buffer+1)->ki.wScan = 0;
(buffer+1)->ki.time = 0;
(buffer+1)->ki.dwFlags = 0;
(buffer+1)->ki.dwExtraInfo =0;
(buffer+2)->type = INPUT_KEYBOARD;
(buffer+2)->ki.wVk = spkey;
(buffer+2)->ki.wScan = 0;
(buffer+2)->ki.time = 0;
(buffer+2)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+2)->ki.dwExtraInfo = 0;
(buffer+3)->type = INPUT_KEYBOARD;
(buffer+3)->ki.wVk = vk;
(buffer+3)->ki.wScan = 0;
(buffer+3)->ki.time = 0;
(buffer+3)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+3)->ki.dwExtraInfo = 0;
// Here is the Sendinput function implemented
// queue is stuffed with 4 events pointed to by buffer
// with the sizeof an INPUT struct.
SendInput(4,buffer,sizeof(INPUT));
delete (buffer); // We always clean up our messes.
}
// Check for combinations of 2 special keys, i.e. shift-alt,
// ctrl-alt,shift-ctrl by intersecting logical conditions of
// the 3 possible keys that can be pressed at once and building
// the buffer to accept 3 key events.
else if ((shift || control) && (control || alt))
{
INPUT *buffer = new INPUT[6]; //Buffer 3 key events
// Key Presses .. the first 3 events what are the 2 keys modifying
// the third?
// Determine first condition for which key had a value ...
// either shift or control and input the key into the buffer.
if (shift) spkey = shift;
else spkey = control;
buffer->type = INPUT_KEYBOARD;
buffer->ki.wVk = spkey;
buffer->ki.wScan = 0;
buffer->ki.time = 0;
buffer->ki.dwFlags = 0;
buffer->ki.dwExtraInfo =0;
// Determine what the second key is that made the test true
// and put the key into the buffer.
if (alt) spkey = alt;
else spkey = control;
(buffer+1)->type = INPUT_KEYBOARD;
(buffer+1)->ki.wVk = spkey;
(buffer+1)->ki.wScan = 0;
(buffer+1)->ki.time = 0;
(buffer+1)->ki.dwFlags = 0;
(buffer+1)->ki.dwExtraInfo =0;
(buffer+2)->type = INPUT_KEYBOARD;
(buffer+2)->ki.wVk = vk;
(buffer+2)->ki.wScan = 0;
(buffer+2)->ki.time = 0;
(buffer+2)->ki.dwFlags = 0;
(buffer+2)->ki.dwExtraInfo = 0;
(buffer+3)->type = INPUT_KEYBOARD;
(buffer+3)->ki.wVk = buffer->ki.wVk;
(buffer+3)->ki.wScan = 0;
(buffer+3)->ki.time = 0;
(buffer+3)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+3)->ki.dwExtraInfo = 0;
(buffer+4)->type = INPUT_KEYBOARD;
(buffer+4)->ki.wVk = (buffer+1)->ki.wVk;
(buffer+4)->ki.wScan = 0;
(buffer+4)->ki.time = 0;
(buffer+4)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+4)->ki.dwExtraInfo = 0;
(buffer+5)->type = INPUT_KEYBOARD;
(buffer+5)->ki.wVk = vk;
(buffer+5)->ki.wScan = 0;
(buffer+5)->ki.time = 0;
(buffer+5)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+5)->ki.dwExtraInfo = 0;
SendInput(6,buffer,sizeof(INPUT));
delete(buffer);
}
// the dreaded Shift, Control, Alt + Key combination
else if (shift && control && alt)
{
INPUT *buffer = new INPUT[8];
buffer->type = INPUT_KEYBOARD;
buffer->ki.wVk = shift;
buffer->ki.wScan = 0;
buffer->ki.time = 0;
buffer->ki.dwFlags = 0;
buffer->ki.dwExtraInfo =0;
(buffer+1)->type = INPUT_KEYBOARD;
(buffer+1)->ki.wVk = control;
(buffer+1)->ki.wScan = 0;
(buffer+1)->ki.time = 0;
(buffer+1)->ki.dwFlags = 0;
(buffer+1)->ki.dwExtraInfo =0;
(buffer+2)->type = INPUT_KEYBOARD;
(buffer+2)->ki.wVk = alt;
(buffer+2)->ki.wScan = 0;
(buffer+2)->ki.time = 0;
(buffer+2)->ki.dwFlags = 0;
(buffer+2)->ki.dwExtraInfo = 0;
(buffer+3)->type = INPUT_KEYBOARD;
(buffer+3)->ki.wVk = vk;
(buffer+3)->ki.wScan = 0;
(buffer+3)->ki.time = 0;
(buffer+3)->ki.dwFlags = 0;
(buffer+3)->ki.dwExtraInfo = 0;
(buffer+4)->type = INPUT_KEYBOARD;
(buffer+4)->ki.wVk = shift;
(buffer+4)->ki.wScan = 0;
(buffer+4)->ki.time = 0;
(buffer+4)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+4)->ki.dwExtraInfo = 0;
(buffer+5)->type = INPUT_KEYBOARD;
(buffer+5)->ki.wVk = control;
(buffer+5)->ki.wScan = 0;
(buffer+5)->ki.time = 0;
(buffer+5)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+5)->ki.dwExtraInfo = 0;
(buffer+6)->type = INPUT_KEYBOARD;
(buffer+6)->ki.wVk = alt;
(buffer+6)->ki.wScan = 0;
(buffer+6)->ki.time = 0;
(buffer+6)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+6)->ki.dwExtraInfo = 0;
(buffer+7)->type = INPUT_KEYBOARD;
(buffer+7)->ki.wVk = vk;
(buffer+7)->ki.wScan = 0;
(buffer+7)->ki.time = 0;
(buffer+7)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+7)->ki.dwExtraInfo = 0;
SendInput(8,buffer,sizeof(INPUT));
delete(buffer);
}
// simple unmodified normal key event
else
{
INPUT *buffer = new INPUT[2];
buffer->type = INPUT_KEYBOARD;
buffer->ki.wVk = vk;
buffer->ki.wScan = 0;
buffer->ki.time = 0;
buffer->ki.dwFlags = 0;
buffer->ki.dwExtraInfo =0;
(buffer+1)->type = INPUT_KEYBOARD;
(buffer+1)->ki.wVk = vk;
(buffer+1)->ki.wScan = 0;
(buffer+1)->ki.time = 0;
(buffer+1)->ki.dwFlags = KEYEVENTF_KEYUP;
(buffer+1)->ki.dwExtraInfo =0;
SendInput(2,buffer,sizeof(INPUT));
delete(buffer);
}
}
Assuming I don't have typos ... (Big assumption) ... this fragment should hopefully illustrate the use of SendInput. And remember if you are one of our CE friends ... ignore this and stick with the Keybd_event function.
Rich L.
|
|
|
|
|
Have you seen the onscreen keyboard at http://www.virtual-keyboard.com/?
These keyboards run under Windows 95/98/NT, and have no "flashing" problem.
|
|
|
|
|
So do the ones from http://www.imgpresents.com. We're the ones that supply all the pen and touch systems manufacturers and the Assistive Technology (disabled) Community. We also have over 40+ International Keyboards, can Ctrl/Alt/Del, and our keyboards come up for Network logon even under NT, 2000, and Terminal Services.
Yes, we're a little expensive (although not compared to a pen tablet or touchscreen; or a decent keyboard for that matter), but some people like real phone support, and products that stay current with all the Windows versions and other O/S that they use.
|
|
|
|
|
HI...nice work..
I made the same app like this...a virtual keyboard...
I struggled the focus problem for weeks..
But there is no vision to slove this problem in this year..-_-;
Would plz think once more about this?
Or any idea for that?
I can't make it alone...
Regards
bajy
|
|
|
|
|
I like your virtual keyboard - well done. Just a suggestion: you might want to force a release for the Shift, Ctrl, Alt keys when the window is minimized to the system tray
|
|
|
|
|