Click to See Complete Forum and Search --> : Onscreen Keyboard and fullscreen application


tqphan
February 16th, 2010, 05:52 PM
I'm making onscreen keyboard and wondering how can I get the onscreen keyboard to draw over a fullscreen application, such as a game, for example. I have managed to make the onscreen keyboard to stay on top over any fullscreen application by continuously calling SetWindowPos function. Even when my keyboard is on top and able to receive mouse messages, Windows doesn't paint my onscreen keyboard's client area. So while I cannot see my onscreen keyboard, it is still functional as expected.

So my question is how can I force Windows to paint my keyboard over a fullscreen application? To my understanding, Windows does not process WM_PAINT to any other application when a fullscreen application is active. Is this correct? If so is it possible to get around this? I tried sending myself WM_PAINT, but that did nothing. There has to be some way to get around this! Please help.

Here is the code for a simple window that will illustrate my point. What I have here is a window that doesn't receive keyboard focus but it will process mouse messages. When you right click on the client area, you will hear a beep. This window will stay on top of any application. Now, if I launch a fullscreen game, for instance, you will not be able to see this window; HOWEVER, if you right click on the area where my window supposed to be, you will still hear the beep. This means my window is there and functional but Windows refuses to paint it over the fullscreen application!




//main.cpp
#include <windows.h>

/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/* Make the class name into a global variable */
wchar_t szClassName[] = L"zk0.0.0.1";

int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
ZeroMemory(&messages, sizeof(MSG));
WNDCLASSEX wincl; /* Data structure for the windowclass */

/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); /* Use default icon and mouse-pointer */
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Use Windows's default color as the background*/

/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;

/* The class is registered */
/* WS_EX_TOPMOST - always on top | WS_EX_NOACTIVATE - Prevent mouse input from activating the window*/
/* WS_POPUPWINDOW - no title bar | WS_SIZEBOX - resizable */
hwnd = CreateWindowEx (WS_EX_TOPMOST | WS_EX_NOACTIVATE, szClassName, L"zkeys", WS_POPUPWINDOW | WS_SIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hThisInstance, NULL);

/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);

while(messages.message != WM_QUIT)
{
// IF there is a Windows message then process it.
if(PeekMessage(&messages, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
// ELSE, do other stuff.
else
{
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOACTIVATE);
UpdateWindow(hwnd);
}
}


/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}


/* This function is called by the Windows function DispatchMessage() */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) /* handle the messages */
{
case WM_LBUTTONDOWN:
SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | 0x0002, 0);
break;
case WM_DESTROY:
case WM_RBUTTONDOWN:
Beep(6666,500);
break;
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;

case WM_MOVING: /* fix for a bug in windows that prevents contents of the windows from being displayed */
case WM_SIZING:
{
RECT *prc = (RECT *)lParam;
SetWindowPos(hwnd, NULL, prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top, 0);
}
break;

default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}

return 0;
}