Search code examples
delphion-screen-keyboard

How to position the On-Screen Keyboard window?


After launching osk.exe with ShellExecuteEx() I would like to position the keyboard window relative to the data-entry fields, so that it doesn't cover them.

How do I set the window position for the osk before calling it?

Also, how can I have the application hide the osk when I am finished?


Solution

  • You can use FindWindow using the window class "OSKMainClass" to get the window handle, and then SetWindowPos on that handle to position it to the coordinates you want. (You may need to use the control's ClientToScreen method to convert to the proper coordinates, but I'll let you figure that part out.)

    // Off the top of my head - not at a machine that has a Delphi compiler at
    // the moment.
    var
      OSKWnd: HWnd;
    begin
      OSKWnd := FindWindow(PChar('OSKMainClass'), nil);
      if OSKWnd <> 0 then
      begin
        SetWindowPos(OSKWnd, 
                     HWND_BOTTOM, 
                     NewPos.Left, 
                     NewPos.Top, 
                     NewPos.Width,
                     NewPos.Height, 
                     0);
      end;
    end;
    

    Code taken in part from a CodeProject article related to the same topic. I got the window class using AutoHotKey's Window Spy utility.

    Notes:

    1. Remy Lebeau points out in a comment that you should make sure to use CreateProcess() or ShellExecuteEx() so that you get back a process handle that can then be passed to WaitForInputIdle() before calling FindWindow(). Otherwise the call to FindWindow() may happen before OSK creates the window.

    2. mghie points out in a comment that the only way he could get this to work was by running the app as Administrator; otherwise the call to SetWindowPos() resulted in an "Access Denied (5)".