1
votes

I am trying to make a custom On screen keyboard for an existing application (that i have no control over)

The program I intend to use it with only needs certain keys (numbers + some letters) and is being used in a touch screen environment

however as screen real estate is at a premium, using the built in on screen keyboard is out of the question.

as such i am trying to make a simple GUI based one using Win32, however i can't seem to find a way to prevent the window from being activated (being the window in use) without also stopping my being able to receive input from said window.

i have tried creating the window with flags to prevent activation - WS_EX_NOACTIVATE however when i do this i dont seem to be able to receive my simulated input in another program.

i know my input code works (tested using a sleep and then clicking other window)

i have also tried using ShowWindow to remove activation from the window after the buttonpress, but to no avail.

my code simplified is: main.cpp:

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <winable.h>

#include "resource.h"

BOOL CALLBACK DialogProc(HWND H,UINT M,WPARAM W,LPARAM L)
{
    switch(M)
    {
        case WM_INITDIALOG:
        {
            return TRUE;
        }
        case WM_CLOSE:
        {
          EndDialog(H,0);
          return TRUE;
        }
        case WM_COMMAND:
        {
            ShowWindow(H, SW_SHOWNOACTIVATE);
            switch(LOWORD(W))
            {
                case A_KEY:
                    {
                        //Sleep(500);
                        INPUT ip;
                        // Set up a generic keyboard event.
                        ip.type = INPUT_KEYBOARD;
                        ip.ki.wScan = 0; // hardware scan code for key
                        ip.ki.time = 0;
                        ip.ki.dwExtraInfo = 0;
                        // Press the "A" key
                        ip.ki.wVk = 0x41; // virtual-key code for the "a" key
                        ip.ki.dwFlags = 0; // 0 for key press
                        SendInput(1, &ip, sizeof(INPUT));
                        // Release the "A" key
                        ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
                        SendInput(1, &ip, sizeof(INPUT));
                        return TRUE;
                    };
            }
        }
    }
    return FALSE;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DialogProc);
}

resource.h:

#include <windows.h>
#define DLG_MAIN 1000
#define A_KEY 2000

resource.rc:

#include "resource.h"

DLG_MAIN DIALOG 0,0,300,111
CAPTION ""
STYLE WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_EX_TOPMOST|DS_SETFOREGROUND//WS_EX_NOACTIVATE
BEGIN
    CONTROL "A", A_KEY, "Button", WS_VISIBLE, 2, 2), 20, 20
END

Any advice on where i'm going wrong/what else to try?

Thanks

James

1
Handle the WM_MOUSEACTIVATE message and return MA_NOACTIVATE.Jonathan Potter
i've tried adding an extra case under the switch(M) section, doing that and it still doesnt work, the window still takes focus and i get an error ding telling me off for type where i can't, is that the correct place to put that case?James Kent
Remember that to return a value from a dialog procedure you need to use SetWindowLongPtr(hWnd, DWLP_MSGRESULT, <value>); rather than simply returning it.Jonathan Potter
did not know that - just starting to learn C/C++, but now my whole dialog disappears when i press a single button, and no text is entered?James Kent

1 Answers

1
votes

I am not sure about other requirements you may have, but reading your post, I imagine you could use the RegisterRawInputDevices functionality, which allows you to retrieve input information from a window that is not active. In addition, you message loop may not defer “a lot” from the code you posted, as you can use the WM_INPUT message to process the input information.

Instead of placing a code snippet in this reply, I will add a link to the MSDN examples (which have a code snippet). The example may guide you to all the related functionality available in the Win32 API to retrieve raw input data.

Regarding the windows focus, you can use the WS_EX_NOACTIVATE style when creating your window, as you will still receive the WM_INPUT messages after registering for raw input.

Finally, please notice that you may have other challenges with the OS now that Windows has extra support for on-screen virtual keyboards (TabTip).