Hi,
I am trying to create a transparent window using Win32 API which can be dragged across the screen and the window's background will keep on being transparent and showing the windows behind it.
I'm doing so by performing the following:
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL;
wcex.hCursor = NULL;
wcex.hbrBackground = NULL;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
The:
wcex.hbrBackground = NULL;
line is responsible of making the window transparent upon initialization.
Creating the window is done in:
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance;
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
And the way the window keeps on being transparent upon dragging is:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_MOVING:
InvalidateRect(hWnd, NULL, TRUE);
break;
default:
return = DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Where the:
InvalidateRect(hWnd, NULL, TRUE);
line causes the window to be redrawn upon moving event.
The problem is that the background of the window is not re-rendered in the regions which are not "new".
For example,
say I open an application (word, chrome etc. - lets call it WindowB) and than I run my application which opens WindowA that covers WindowB but I can see the content of WindowB in the background (since WindowA is a transparent window). If I drag WindowA across the screen I still see WindowB in the background and that's great.
If I minimize WindowB I still see portion of WindowB which intersects WindowA region (No problem here since I didn't redraw WindowA).
If I start to drag WindowA, I assumed that WindowB portion showed in WindowA will disappear and I'll see what's currently is the top most window in the desktop as WindowA's background, since I call
InvalidateRect(hWnd, NULL, TRUE); upon the moving event.
What actually happens is that I still see WindowB in all the regions which are not "new regions" - by new regions I mean regions in the screen where WindowA was moved to and was not part of WindowA region before the move.
It seems that the call for
InvalidateRect(hWnd, NULL, TRUE); is not enough since it renders only "new regions".
I would very much appreciate any assistance on this issue.
The main function of my application is the default function created by Visual Studio 2010 for a Win32 Application project:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MSG msg;
HACCEL hAccelTable;
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TEST2, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TEST2));
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
Thanks,
Gidi