Click here to Skip to main content
15,888,351 members
Articles / Desktop Programming / MFC
Article

Onscreen Keyboard

Rate me:
Please Sign up or sign in to vote.
4.71/5 (34 votes)
21 Mar 2000 666.6K   16.9K   102   92
An onscreen keyboard for pen computing and touchscreens
  • Download source files - 143 Kb

    Sample Image - OnscreenKeyboard.gif

    I needed a simple onscreen keyboard to interface with a touch / pen based computer that I bought through an online auction. Although Microsoft supplies one with its Pen Extensions 2.0 it only works win Win95 and I wanted to use NT.

    All of the available onscreen keyboards I found were either too expensive, or they were only designed to operate with 3.1 and 9x so (of course) I decided to see if I could make one. Along the way I learned a little about how the keyboard is handled, and the thread keyboard maps.

    Included with this article is a working, but simple, onscreen keyboard. I submitted it mostly as an example of the methods:

    • AttachThreadInput
    • keybd_event
    • VkKeyScan
    • GetKeyState

    This program has one nasty limitation, and that is that it "flashes" since it does not prevent the changing of focus to itself when clicked, and then back to the target window when the keystroke is generated. If someone wants to tackle that one please feel free ;-)

  • 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


    Written By
    United States United States
    This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

    Comments and Discussions

     
    QuestionHas anyone solved focus problem? Pin
    Mahbub7312-Apr-02 10:58
    Mahbub7312-Apr-02 10:58 
    AnswerEdit control focus Pin
    23-May-02 0:19
    suss23-May-02 0:19 
    GeneralDoesn't work with IE Pin
    8-Oct-01 11:13
    suss8-Oct-01 11:13 
    GeneralRe: Doesn't work with IE Pin
    Anonymous31-Jul-02 0:43
    Anonymous31-Jul-02 0:43 
    GeneralRe: Doesn't work with IE Pin
    Thomas Righetti28-Jun-04 21:43
    Thomas Righetti28-Jun-04 21:43 
    GeneralRe: Doesn't work with IE Pin
    Dirk Moshage17-Aug-04 1:36
    Dirk Moshage17-Aug-04 1:36 
    GeneralRe: Doesn't work with IE Pin
    Ole Martin Brynildsen2-Sep-04 4:16
    Ole Martin Brynildsen2-Sep-04 4:16 
    GeneralRe: Doesn't work with IE Pin
    CoreyCooper29-Jun-04 6:14
    CoreyCooper29-Jun-04 6:14 
    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.


    GeneralGreat!!! Pin
    17-Sep-01 18:57
    suss17-Sep-01 18:57 
    GeneralA Problem about the keyboard Pin
    Ray31-Oct-00 6:28
    Ray31-Oct-00 6:28 
    GeneralRe: A Problem about the keyboard Pin
    17-Mar-01 5:33
    suss17-Mar-01 5:33 
    GeneralRe: A Problem about the keyboard Pin
    25-Oct-01 4:56
    suss25-Oct-01 4:56 
    GeneralOnscreen Keyboard Pin
    amy9-Oct-00 23:48
    amy9-Oct-00 23:48 
    GeneralRe: Onscreen Keyboard Pin
    28-Mar-01 11:47
    suss28-Mar-01 11:47 
    GeneralFocus Problem Pin
    Ryan Park5-May-00 18:28
    Ryan Park5-May-00 18:28 
    GeneralNice work! Pin
    Felix23-Mar-00 8:36
    Felix23-Mar-00 8:36 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.