Нет хороших способов сделать это, но один из подходов, который может сработать для вас, - это подключить рассматриваемое приложение, используя SetWindowsHookEx (...), чтобы добавить GetMsgProc, который рисует ваше наложение в ответ на сообщения WM_PAINT. Основная идея заключается в том, что вы рисуете СВОЮ графику сразу после того, как приложение заканчивает свой собственный рисунок.
В вашем основном приложении:
....
HMODULE hDllInstance = LoadLibrary("myFavoriteDll");
HOOKPROC pOverlayHook = (HOOKPROC)GetProcAddress(hDllInstance, "OverlayHook");
SetWindowsHookEx(WH_GETMESSAGE, pOverlayHook, hDllInstance, threadId);
Выключен в DLL где-то:
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;
}
Это все win32, поэтому ваш код на C # будет p / invoke тяжелым и, соответственно, довольно уродливым. Ваша DLL также должна быть неуправляемой (если вы собираетесь внедрить ее в процесс, отличный от вашего), что делает это решение еще более неприятным.
Это решит вашу проблему с проблемами z-порядка и отсечения, когда вы будете рендерить в само окно. Однако, если приложение, на которое вы нацеливаетесь, делает любой рисунок вне WinProc, отвечающий на WM_PAINT, вещи распадаются; это не совсем редкий случай.