Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 窗口处理管理器_C++_Windows_Winapi_Window Managers_Z Order - Fatal编程技术网

C++ 窗口处理管理器

C++ 窗口处理管理器,c++,windows,winapi,window-managers,z-order,C++,Windows,Winapi,Window Managers,Z Order,我有一个运行三个应用程序的Windows box。当应用程序启动时,每个应用程序都会创建一个无边界窗口,该窗口的位置使它们以特定方式重叠 此时,当我单击底部窗口上的控件时,它会到达窗口堆栈的顶部 我需要确保每个窗口在窗口堆栈中保持其顺序,即使窗口接收到输入 我想我需要编写一些简单的窗口管理器来维护窗口的正确Z顺序 问题是,我需要知道某个特定的窗口是否改变了位置。我发现有一条WM_WindowPosChange消息,但我的理解是,该消息被发送到位置已更改的窗口 我需要以某种方式通知我的窗口管理器应

我有一个运行三个应用程序的Windows box。当应用程序启动时,每个应用程序都会创建一个无边界窗口,该窗口的位置使它们以特定方式重叠

此时,当我单击底部窗口上的控件时,它会到达窗口堆栈的顶部

我需要确保每个窗口在窗口堆栈中保持其顺序,即使窗口接收到输入

我想我需要编写一些简单的窗口管理器来维护窗口的正确Z顺序

问题是,我需要知道某个特定的窗口是否改变了位置。我发现有一条WM_WindowPosChange消息,但我的理解是,该消息被发送到位置已更改的窗口

我需要以某种方式通知我的窗口管理器应用程序Z顺序已更改


是否有某种方法可以捕获所有WM_uuu消息并确定消息是否适用于我希望控制的某个窗口?

您可以使用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_uuu消息,我建议应用程序调用一个窗口类,而不是调用
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){
    }
};
类窗口{
公众的
窗口(){
...
WNDCLASSEX wc;
零内存(&wc,sizeof(WNDCLASSEX));
wc.cbSize=sizeof(WNDCLASSEX);
wc.lpfnWndProc=wndProc;//lpCreateParams;
SetWindowLongPtr(hwnd,GWL_用户数据,(LONG_PTR)父级);
}
否则{
父项=(窗口*)GetWindowLongPtr(hwnd,GWL_用户数据);
如果(!parent)返回DefWindowProc(hwnd、msg、wParam、lParam);
}
HWND prev=父级->兆瓦;
父->mWin=hwnd;
LRESULT ret=parent->wndProc(msg、wParam、lParam);
父级->mWin=上一级;
返回ret;
}
虚拟LRESULT wndProc(UINT msg、WPARAM WPARAM、LPARAM LPARAM){
}
};
在本例中,您的应用程序将从窗口继承,基本上提供了一个稍加修改的wndProc函数(它将缺少HWND,因此需要将其存储在某个位置,除非您从Userdata获取它)

  • 每次收到消息时,
    窗口::wndProc(HWND、UINT、WPARAM、LPARAM)
    函数都会将其拾取。在这里,您可以检查任何消息,包括(但不限于)
    WM\u WINDOWPOSCHANGING

  • 另一件事是:
    wndProc(UINT、WPARAM、LPARAM)
    中,而不是调用
    DefWindowProc(..)

    您可以调用
    Window::wndProc(UINT、WPARAM、LPARAM)
    。然后您可以在那里进行检查(以避免将第一个
    wndProc
    函数包含在内):)

这样做的缺点是,如果应用程序是由其他人编写的,它们将需要符合您的windowclass。正如您所解释的,用户不需要与您的窗口管理器交互,但是,使用这种方法,唯一的交互方式是让您的窗口管理器为用户创建窗口。

否则,我认为您必须使用其他答案中解释的钩子

最简单的方法可能是将DLL注入三个应用程序中的每一个。这确保您只需要处理您真正关心的窗口消息子集

接下来,通过调用
EnumWindows()
查找所有窗口,并在每个应用程序上调用
GetWindowThreadProcessId()
确定它是否属于当前进程(即,您的DLL被注入的进程),在每个应用程序中查找主窗口(理论上可能会有更多)


现在您有了正确的HWND,您可以钩住关联的WndProc并捕获发送给它的任何WM_WindowPosChangeing。

当您创建要位于顶部的两个窗口时,将要位于底部的窗口作为
hWndParent
值指定给
CreateWindow
。当底部窗口向前移动时,窗口将始终向前移动这些窗口,以便它们始终位于其前面


所以,如果您的底部窗口是窗口1。首先创建它,然后在创建windows 2和3时,将窗口1的句柄作为hWndParent值。窗口管理器执行其余操作。

代替Msalter的方法,尝试将DLL注入到每个运行应用程序中,考虑安装WHiCBT Windows钩子。在CBTProc中,当您获得三个您关心的应用程序窗口句柄的HCBT_MOVESIZE时,返回0


请阅读和上的MSDN文档。

我想我会同意约翰·克诺勒的回答。如果希望窗口保持特定的z顺序,请确定此顺序,并使用适当的父子关系创建窗口

::SetWindowLong(hwnd_child, GWL_HWNDPARENT, hwnd_parent);
这样做时,子窗口将始终位于父窗口的顶部


如果您仍然坚持捕获消息,您可以尝试在每个窗口中捕获WM_ACTIVATE,然后将该消息转发给您的窗口管理器,该窗口管理器可以访问所有窗口的HWND,并使用SetWindowPos对其进行正确的z排序。您可以使用windows POS一次更改窗口的z顺序,而不是设置WindowPOS,并避免闪烁。

如果用户不需要与“窗口管理器”应用程序交互,我更希望使用此选项。我希望能有某种方法来检测窗口顺序何时改变,然后进行“窗口管理”