I haven't done this, so the following is what I would investigate if I were to try:
- For each application / each top-level window:
- Create a floating window and position it over the title bar wherever you want it to sit. Set up the parent / child relationship, but this window is part of your own process. (There are occasionally problems parenting a window from one process to one from another process, but try. I'd avoid injecting into other processes if possible.)
- You can investigate the window flags to see if the window has a title bar (ie if you should add a button) via
GetWindowLong
with GWL_STYLE
looking for WS_CAPTION
. The same call will also let you see the type of caption / frame, which you can combine with GetSystemMetrics
with, eg, SM_CYDLGFRAME
to figure out the right size for your button on this specific window's title bar.
- This window is now your button: paint, handle clicks etc as appropriate.
- Make it a non-focusable window so that clicks to it don't take focus away from the window is is on the title bar of. You don't want clicking it to make the title bar change colour, for example. Do this by setting the
WS_EX_NOACTIVATE
window flag, something like: SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_NOACTIVATE
)
.
- The main problem is to keep it positioned correctly when the window moves, is resized, etc. To do this, install a hook for the system move events. You can also hook minimize and restore via
EVENT_SYSTEM_MINIMIZESTART
and EVENT_SYSTEM_MINIMIZEEND
. This will allow you to keep track of all windows moving around onscreen, such that you can adjust the button-window position if necessary.
That gives you a window which you can paint as a button (and respond to clicks etc), that visually is "attached" to other windows so it stays in the same place as the user drags the title bar, minimizes or maximises the app, etc, and that is in your own process without cross-process problems.