Вы можете использовать SetWindowPos, чтобы расположить ваши окна в желаемом порядке Z. Я предлагаю вам перехватить сообщение WM_FOCUS (оно отправляется в ваше окно, когда оно получает фокус)
В вашей функции wndProc вы можете попробовать что-то вроде этого:
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..
}
Я не совсем уверен в порядке следования аргументов SetWindowPos, так как сейчас не могу проверить код, но, возможно, это поможет вам?
Если вам нужно перехватить все сообщения WM_, я бы предложил класс Window, который приложения вместо этого (как я предполагаю) вызывают (* я полагаю) для вызова CreateWindowEx
сами. Например:
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){
}
};
В этом примере ваши приложения будут наследоваться от Window, в основном предоставляя слегка измененную функцию wndProc (в ней будет отсутствовать HWND, поэтому ее нужно будет где-то хранить, если вы не заберете ее из Userdata).
Каждый раз, когда вы получаете сообщение, функция Window::wndProc(HWND, UINT, WPARAM, LPARAM)
подхватывает его. Здесь вы можете проверять любые сообщения, включая (но не ограничиваясь) WM_WINDOWPOSCHANGING
.
Другое, что нужно сделать, это:
В wndProc(UINT, WPARAM, LPARAM)
вместо звонка DefWindowProc(..)
Вы звоните Window::wndProc(UINT, WPARAM, LPARAM)
. Тогда вы могли бы вместо этого делать там свои проверки (чтобы не забивать первую wndProc
функцию) :)
Недостатком этого будет то, что если приложения написаны кем-то другим, они должны будут соответствовать вашему оконному классу. Когда вы объясняете это, пользователю не нужно взаимодействовать с вашим оконным менеджером, однако, при таком подходе единственное взаимодействие будет состоять в том, чтобы позволить вашему оконному менеджеру создать окно для пользователя.
В противном случае я думаю, что вам придется пойти с крючком, описанным в других ответах