you can use SetWindowPos to position your windows in the Z order you want. I suggest you intercept the WM_FOCUS message (this is sent to your window when it receives focus)
In your wndProc function, maybe you can try something like this:
LRESULT wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
// other stuff..
switch (msg){
case WM_FOCUS:
{
HWND firstWindow; // get the first window here
HWND secondWindow; // this would be the second window
HWND thirdWindow; // this would be the third window
// TODO: initialize the windows correctly, based on your priority
SetWindowPos(firstWindow, secondWindow, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); // position the second window below the first window
SetWindowPos(secondWindow, thirdWindow, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE); // position the third window below the second window
}
return 0;
}
// other messages..
}
I'm not quite sure of the ordering of the SetWindowPos arguments since I can't test the code right now, but maybe this can get you going?
If you need to intercept all WM_ messages, I would suggest a Window class that the applications call instead (which I guess) of calling CreateWindowEx
themselves. For instance:
class Window {
public
Window(){
...
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = wndProc; // <- Note this one
...
}
static LRESULT WINAPI wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
// reference: http://www.gamedev.net/community/forums/topic.asp?topic_id=303854 - Evil Steve [Moderator]
Window* parent;
// Get pointer to window
if(msg == WM_CREATE){
parent = (Window*)((LPCREATESTRUCT)lParam)->lpCreateParams;
SetWindowLongPtr(hwnd,GWL_USERDATA,(LONG_PTR)parent);
}
else{
parent = (Window*)GetWindowLongPtr(hwnd,GWL_USERDATA);
if(!parent) return DefWindowProc(hwnd,msg,wParam,lParam);
}
HWND prev = parent->mWin;
parent->mWin = hwnd;
LRESULT ret = parent->wndProc(msg,wParam,lParam);
parent->mWin = prev;
return ret;
}
virtual LRESULT wndProc(UINT msg, WPARAM wParam, LPARAM lParam){
}
};
In this example your applications would inherit from Window, basically providing a slightly modified wndProc function (it would be missing the HWND so this would need to be stored somewhere, unless you pick it up from the Userdata).
Everytime you receive a message the Window::wndProc(HWND, UINT, WPARAM, LPARAM)
function would pick it up. In here you could do your checks of any messages, including (but not limited to) WM_WINDOWPOSCHANGING
.
The other thing to do would be that:
In the wndProc(UINT, WPARAM, LPARAM)
, instead of calling DefWindowProc(..)
you call Window::wndProc(UINT, WPARAM, LPARAM)
. Then you could do your checks in there instead (as to not cludge the first wndProc
function) :)
The downside of this would be that if the applications are written by someone else, they would need to comply to your windowclass. As you explain it the user shouldn't need to interact with your window manager, however, with this approach the only interaction would be to let your window manager create the window for the user.
Otherwise I think that you would have to go with the hook explained in the other answers