Well, I took a shot at it and failed. However, I'll post the code I got. What seems to be happening is that Windows isn't allowing me to subclass the desktop window. When I call GetLastError() after the call to SetWindowLong() that would set the subclass proc - here MyDesktopHook(), I'm getting the error #5 which is "ACCESS DENIED".
So my subclass isn't working. Perhaps I've a dumb error; was coding pretty fast. Anyway here's the code and I've a tutorial on subclassing here...
http://www.jose.it-berater.org/smfforum/index.php?topic=3392.0
Check Out ProgEx40f
//Form1.h
typedef struct WindowsEventArguments
{
HWND hWnd;
WPARAM wParam;
LPARAM lParam;
HINSTANCE hIns;
}WndEventArgs, *lpWndEventArgs;
struct EVENTHANDLER
{
unsigned int Code;
long (*fnPtr)(lpWndEventArgs);
};
//Main.cpp
#include <windows.h>
#include <stdio.h>
#include "Form1.h"
EVENTHANDLER EventHandler[3];
WNDPROC fnDesktopProc=0;
FILE* fp;
long __stdcall fnMyDesktopHook(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
if(msg==WM_PAINT)
fprintf(fp,"Got WM_PAINT Message For Desktop Window!\n");
else
fprintf(fp,"Got Something Else!\n");
return CallWindowProc(fnDesktopProc,hwnd,msg,wParam,lParam);
}
long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
HWND hDesktop;
fp=fopen("Output.txt","w");
fprintf(fp,"Entering fnWndProc_OnCreate()\n");
fprintf(fp," Output.txt Opened In fnWndProc_OnCreate()\n");
hDesktop=GetDesktopWindow();
fprintf(fp," hDesktop = %u\n",hDesktop);
if(hDesktop)
{
fnDesktopProc=(WNDPROC)SetWindowLong(hDesktop,GWL_WNDPROC,(long)fnMyDesktopHook);
fprintf(fp," GetLastError() = %u\n",GetLastError());
fprintf(fp," fnDesktopProc = %u\n",(unsigned)fnDesktopProc);
}
fprintf(fp,"Leaving fnWndProc_OnCreate()\n\n");
return 0;
}
long fnWndProc_OnLButtonDown(lpWndEventArgs Wea)
{
RedrawWindow(NULL,NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
return 0;
}
long fnWndProc_OnClose(lpWndEventArgs Wea)
{
HWND hDesktop;
fprintf(fp,"Entering fnWndProc_OnClose()\n");
hDesktop=GetDesktopWindow();
if(fnDesktopProc)
SetWindowLong(hDesktop,GWL_WNDPROC,(long)fnDesktopProc);
DestroyWindow(Wea->hWnd);
PostQuitMessage(0);
fprintf(fp," Output.txt Closed In fnWndProc_OnClose()\n");
fprintf(fp,"Leaving fnWndProc_OnClose()\n\n");
fclose(fp);
return 0;
}
void AttachEventHandlers(void) //This procedure maps windows messages to the
{ //procedure which handles them.
EventHandler[0].Code=WM_CREATE, EventHandler[0].fnPtr=fnWndProc_OnCreate;
EventHandler[1].Code=WM_LBUTTONDOWN, EventHandler[1].fnPtr=fnWndProc_OnLButtonDown;
EventHandler[2].Code=WM_CLOSE, EventHandler[2].fnPtr=fnWndProc_OnClose;
}
long __stdcall fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
WndEventArgs Wea; //This procedure loops through the EVENTHANDER array
//of structs to try to make a match with the msg parameter
for(unsigned int i=0; i<3; i++) //of the WndProc. If a match is made the event handling
{ //procedure is called through a function pointer -
if(EventHandler[i].Code==msg) //(EventHandler[i].fnPtr). If no match is found the
{ //msg is passed onto DefWindowProc().
Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
return (*EventHandler[i].fnPtr)(&Wea);
}
}
return (DefWindowProc(hwnd, msg, wParam, lParam));
}
int __stdcall WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
char szClassName[]="Form1";
WNDCLASSEX wc;
MSG messages;
HWND hWnd;
AttachEventHandlers();
wc.lpszClassName=szClassName; wc.lpfnWndProc=fnWndProc;
wc.cbSize=sizeof (WNDCLASSEX); wc.style=CS_VREDRAW|CS_HREDRAW;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION); wc.hInstance=hIns;
wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION); wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); wc.cbWndExtra=0;
wc.lpszMenuName=NULL; wc.cbClsExtra=0;
RegisterClassEx(&wc);
hWnd=CreateWindowEx(0,szClassName,szClassName,WS_OVERLAPPEDWINDOW,100,100,350,300,HWND_DESKTOP,0,hIns,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
I added a WM_LBUTTONDOWN handler that causes the desktop to redraw and that is working because you can see the screen flicker. However, I'm not picking anything up in the subclass proc because the call to set it is failing (Windows won't let me do it).
Unless I've got some dumb error I missed that is causing my subclass of the desktop to fail, my guess is that Windows won't allow it. However, if you are just using the desktop as an example and really have some other user created (as opposed to Windows system window) window in mind, the technique might work. However, the best you could hope for I guess would be the update region.