没有很好的方法可以做到这一点,但一种可能对您有用的方法是使用 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 的绘图,事情就会崩溃;这种情况并不少见。