Teamviewers Quickconnect 按钮是如何实现的?

2021-12-18 00:00:00 qt button titlebar c++

对于那些不知道我在说什么的人:http://www.teamviewer.com/images/presse/quickconnect_en.jpg

For those of you who do not know what I am talking about: http://www.teamviewer.com/images/presse/quickconnect_en.jpg

Teamviewer 将该按钮覆盖在所有窗口上,以便您可以快速与其他人共享一个窗口.我想要任何关于实现类似东西的想法――如果你有示例代码,甚至更好(特别是按钮――而不是共享).我对 C++ 和 QT 感兴趣……但如果有其他语言/库,我会对好的解决方案感兴趣.

Teamviewer overlays that button on all windows to allow you to quickly share a window with someone else. I would like any ideas on implementing something similar -- if you have example code, even better (specifically, the button -- not the sharing). I am interested in C++ and QT... but I would be interested in good solutions in other languages/libraries if there are any.

谢谢.

推荐答案

要在外部窗口中绘制按钮或其他东西,您需要将代码注入到外部进程中.检查 SetWindowsHookEx方法:

To draw buttons or other stuff in foreign windows, you need to inject code into the foreign processes. Check the SetWindowsHookEx method for that:

您很可能想为 WH_CALLWNDPROCRET 安装一个钩子并注意 WM_NCPAINT 消息.这将是绘制按钮的正确位置.但是,我不确定是否可以在非客户区中放置窗口,因此在最坏的情况下,您必须手动"绘制按钮.

You most probably want to install a hook for WH_CALLWNDPROCRET and watch out for the WM_NCPAINT message. This would be the right place to draw your button. However, I'm not really sure, if you can place a window within a Non-Client-Area, so in the worst case, you'd have to paint the button "manually".

只需从您的主应用程序(或从 DLL 中)调用它

Just call this from your main application (or from within a DLL)

SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, hModule, 0);

请注意,myCallWndRetProc 必须驻留在 DLL 中,而 hModule 是此 DLL 的模块句柄.

Note that myCallWndRetProc must reside within a DLL and hModule is the Module-HANDLE for this DLL.

您的 myCallWndRetProc 可能如下所示:

Your myCallWndRetProc could look like:

LRESULT CALLBACK myCallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    if (nCode == HT_ACTION) {
        CWPRETSTRUCT* cwpret = (CWPRETSTRUCT*)lParam;
        if (cwpret->message == WM_NCPAINT) {
            // The non-client area has just been painted.
            // Now it's your turn to draw your buttons or whatever you like
        }
    }
    return CallNextHookEx(0, nCode, wParam, lParam);
}

在开始实施时,我建议您只创建一个简单的对话框应用程序并仅挂钩您自己的进程:

When starting with your implementation, I'd suggest, you just create a simple dialog application and hook your own process only:

SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, NULL, GetCurrentThreadId());

安装全局钩子会将 DLL 注入所有进程,这使得调试变得非常困难,并且您的 DLL 在使用时可能会被写保护.

Installing a global hook injects the DLL into all processes, which makes debugging pretty hard, and your DLL may be write-protected while it's in use.

相关文章