首页 > 解决方案 > 如何使用 SetWindowPos 函数?

问题描述

我想创建一个由主父窗口和几个子窗口组成的 Windows 应用程序。这是我到目前为止的代码摘录:

...

   // -----> CHILD WINDOWS <-----

   HWND hWnd_child1 = CreateWindowW(L"STATIC", L"Child 1", WS_CHILD,
     0, 0, 100, 80, hParentWnd, nullptr, hInstance, nullptr);

   if (!hWnd_child1) {
     MessageBox(NULL, L"CreateWindowW Child 1", L"Error!", MB_ICONEXCLAMATION | MB_OK);
     return FALSE;
   }

   HWND hWnd_child2 = CreateWindowW(L"STATIC", L"Child 2", WS_CHILD,
     10, 10, 160, 120, hParentWnd, nullptr, hInstance, nullptr);

   if (!hWnd_child2) {
     MessageBox(NULL, L"CreateWindowW Child 2", L"Error!", MB_ICONEXCLAMATION | MB_OK);
     return FALSE;
   }

   HWND hWnd_child3 = CreateWindowW(L"STATIC", L"Child 3", WS_CHILD,
     20, 20, 160, 120, hParentWnd, nullptr, hInstance, nullptr);

   if (!hWnd_child3) {
     MessageBox(NULL, L"CreateWindowW Child 3", L"Error!", MB_ICONEXCLAMATION | MB_OK);
     return FALSE;
   }

   ShowWindow(hWnd_child3, nCmdShow);
   SetWindowPos(hWnd_child2, HWND_TOP, 10, 10, 100, 80, NULL);
   ShowWindow(hWnd_child2, nCmdShow);
   SetWindowPos(hWnd_child1, HWND_TOP, 0, 0, 100, 80, NULL);
   ShowWindow(hWnd_child1, nCmdShow);

   ShowWindow(hParentWnd, nCmdShow);
   UpdateWindow(hParentWnd);

   // -------------------
...

问题出在SetWindowPos()功能上。我无法理解它是如何工作的。我以为这样称呼它:

ShowWindow(hWnd_child3, nCmdShow);
SetWindowPos(hWnd_child2, HWND_TOP, 10, 10, 100, 80, NULL);
ShowWindow(hWnd_child2, nCmdShow);
SetWindowPos(hWnd_child1, HWND_TOP, 0, 0, 100, 80, NULL);
ShowWindow(hWnd_child1, nCmdShow);

将窗口移动Child 1到所有应用程序窗口的顶部(正如文档所说的 HWND_TOP选项:) Places the window at the top of the Z order

但是,窗口仍然按创建顺序绘制:

图片

不应该SetWindowPos()先移动Child 2Child 3然后Child 1移动Child 2,使窗户以与创建时相反的顺序放置,Child 1在顶部?

标签: c++windowswinapi

解决方案


使子窗口都具有窗口样式 WS_CLIPSIBLINGS 以及 WS_CHILD 等。

来自微软的文档:

如果未指定 WS_CLIPSIBLINGS 并且子窗口重叠,则在子窗口的客户区域内绘制时,可以在相邻子窗口的客户区域内绘制。

基本上,如果子窗口不相互剪辑,那么它们被绘制的顺序(这是任意的)决定了视觉 z 顺序。

例如,下面是您的代码,其中删除了消息框内容,使用 WS_VISIBLE 而不是 ShowWindow,添加可见性边框,并使用 WS_CLIPSIBLINGS。

BOOL CreateChildren(HWND hParentWnd) {
    HWND hWnd_child1 = CreateWindowEx(WS_EX_CLIENTEDGE, L"STATIC", L"Child 1", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
        0, 0, 100, 80, hParentWnd, nullptr, g_hInstance, nullptr);

    HWND hWnd_child2 = CreateWindowEx(WS_EX_CLIENTEDGE, L"STATIC", L"Child 2", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
        10, 10, 160, 120, hParentWnd, nullptr, g_hInstance, nullptr);

    HWND hWnd_child3 = CreateWindowEx(WS_EX_CLIENTEDGE, L"STATIC", L"Child 3", WS_VISIBLE | WS_CHILD | WS_CLIPSIBLINGS,
        20, 20, 160, 120, hParentWnd, nullptr, g_hInstance, nullptr);

    SetWindowPos(hWnd_child2, HWND_TOP, 10, 10, 100, 80, NULL);
    SetWindowPos(hWnd_child1, HWND_TOP, 0, 0, 100, 80, NULL);

    UpdateWindow(hParentWnd);
    return TRUE;
}

产生 重叠的孩子 child1 在顶部。


推荐阅读