windows 如何在另一个应用程序之上绘制图形/文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/815667/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:23:34  来源:igfitidea点击:

How to draw graphics/text on top of another application

c#windowswinapigraphics

提问by s5804

I want to enhance an application, but there is no 3:e party API available. So basically the idea is to draw graphics/text on top of the applications windows.

我想增强应用程序,但没有可用的 3:e 方 API。所以基本上这个想法是在应用程序窗口的顶部绘制图形/文本。

There are problems with z order, clipping, and directing mouse clicks either to my application or the other application.

z 顺序、剪辑和将鼠标单击定向到我的应用程序或其他应用程序时存在问题。

What is an elegant way of doing this?

这样做的优雅方式是什么?

Example image here. It is a trading application where my application wants to add extra information into the trading application's windows. [URL=http://img104.imageshack.us/my.php?image=windowontop.png][/URL]

示例图像在这里。这是一个交易应用程序,我的应用程序希望在其中向交易应用程序的窗口添加额外信息。[URL= http://img104.imageshack.us/my.php?image=windowontop.png][/URL]

采纳答案by Kevin Montrose

There are no nice ways to do this, but one approach that may work for you is to hook the application in question using SetWindowsHookEx(...) to add a GetMsgProc, which draws your overlay in response to WM_PAINT messages. The basic idea is that you're drawing YOUR graphics right after the application finishes its own drawing.

没有好的方法可以做到这一点,但一种可能对您有用的方法是使用 SetWindowsHookEx(...) 挂钩有问题的应用程序,以添加 GetMsgProc,它会根据 WM_PAINT 消息绘制叠加层。基本思想是在应用程序完成自己的绘图后立即绘制图形。

In your main app:

在您的主应用程序中:

....
HMODULE hDllInstance = LoadLibrary("myFavoriteDll");
HOOKPROC pOverlayHook = (HOOKPROC)GetProcAddress(hDllInstance, "OverlayHook");
SetWindowsHookEx(WH_GETMESSAGE, pOverlayHook, hDllInstance, threadId);

Off in a DLL somewhere:

在某个 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;
}

This is all win32 so your C# code will be p/invoke heavy and correspondingly quite ugly. Your DLL must be unmanaged as well (if you intend to inject into a process other than your own), making this an even nastier solution.

这都是 win32,所以你的 C# 代码将是 p/invoke 重,相应地相当丑陋。您的 DLL 也必须是非托管的(如果您打算注入到您自己的进程之外的进程中),这将是一个更糟糕的解决方案。

This would solve your issue with z-order and clipping issues, as you're rendering into the window itself. However, if the application you're targeting does any drawing outside of the WinProc responding to WM_PAINT things fall apart; this is not an entirely uncommon occurence.

当您渲染到窗口本身时,这将解决您的 z 顺序和裁剪问题。但是,如果您的目标应用程序在响应 WM_PAINT 的 WinProc 之外进行任何绘图,事情就会分崩离析;这并非完全不常见的情况。

回答by tenfour

There are problems with z order, clipping, and directing mouse clicks either to my application or the other application.

z 顺序、剪辑和将鼠标单击定向到我的应用程序或其他应用程序时存在问题。

These are all tasks that the window manager was designed to deal with. You should create a layered window on top of the apps' windows.

这些都是窗口管理器设计用来处理的任务。您应该在应用程序窗口的顶部创建一个分层窗口。

See also: Prevent repainting of window in C++

另请参阅:防止在 C++ 中重新绘制窗口