There are no good ways to do this, but one approach that may work for you is to link the application in question using SetWindowsHookEx (...) to add GetMsgProc, which draws your overlay in response to WM_PAINT messages. The main idea is that you draw your graphics right after the application finishes its own drawing.
In the main application:
.... HMODULE hDllInstance = LoadLibrary("myFavoriteDll"); HOOKPROC pOverlayHook = (HOOKPROC)GetProcAddress(hDllInstance, "OverlayHook"); SetWindowsHookEx(WH_GETMESSAGE, pOverlayHook, hDllInstance, threadId);
Turn off the dll somewhere:
LRESULT CALLBACK OverlayHook(int code, WPARAM wParam, LPARAM lParam) { //Try and be the LAST responder to WM_PAINT messages; //Of course, if some other application tries this all bets are off LRESULT retCode = CallNextHookEx(NULL, code, wParam, lParam); //Per GetMsgProc documentation, don't do anything fancy if(code < 0) return retCode; //Assumes that target application only draws when WM_PAINT message is //removed from input queue. if(wParam == PM_NOREMOVE) return retCode; MSG* message = (MSG*)lParam; //Ignore everything that isn't a paint request if(message->message != WM_PAINT) return retCode; PAINTSTRUCT psPaint; BeginPaint(message->hwnd, &psPaint); //Draw your overlay here ... EndPaint(message->hwnd, &psPaint); return retCode; }
This is all win32, so your C # code will be p / invoke heavy and therefore pretty ugly. Your DLL should also be unmanaged (if you intend to implement a process other than your own), which makes this an even more unpleasant decision.
This will solve your problem with the problems of z-order and clipping, since you are rendering in the window itself. However, if the application you are targeting does any drawing outside WinProc that responds to WM_PAINT, it falls apart; This is not an unusual occurrence.
Kevin montrose
source share