Search code examples
c++qtbuttontitlebar

How is Teamviewers Quickconnect button accomplished?


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

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.

Thanks.


Solution

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

    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".

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

    SetWindowsHookEx(WH_CALLWNDPROCRET, myCallWndRetProc, hModule, 0);

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

    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());
    

    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.