【问题标题】:How to use the SetWindowPos function?如何使用 SetWindowPos 函数?
【发布时间】:2021-11-22 11:06:23
【问题描述】:

我想创建一个包含一个主父窗口和几个子窗口的 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 窗口移动到所有应用程序窗口的顶部(正如docHWND_TOP 选项所说:Places the window at the top of the Z order)。

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

难道SetWindowPos() 不应该先移动Child 2Child 3,然后再移动Child 1Child 2,从而使窗口以与创建时相反的顺序排列,Child 1 在顶部?

【问题讨论】:

  • 如果一切都是HWND_TOP,那么实际上谁有优先权? ??????
  • 这能回答你的问题吗? Moving a child control to top
  • 还有stackoverflow.com/questions/17722398/child-window-z-order/…(本质上是z顺序和剪辑兄弟之间的区别)
  • 您可能还需要让这些子窗口自己重绘。
  • @PeteKirkham,是的,这是一个类似的问题,但正如 David Heffernan 所建议的那样,最奇怪的叫 SetWindowPos(b1, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); 对我不起作用,而是在 b2 上调用 SetWindowPos工作!。是不是很奇怪!?

标签: c++ windows winapi


【解决方案1】:

使子窗口都具有窗口样式 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 在顶部。

【讨论】:

  • 好的,我知道,但是当我通过调用 SetWindowPos(hWnd_child1, HWND_TOP, 0, 0, 100, 80, NULL); 明确地将 Child 1 移动到 z 有序堆栈的顶部时,为什么它不起作用!?
  • 它确实有效。我会用一张图片更新我的答案。您需要清楚您期望它在工作时的样子,例如孩子周围没有边框等。
  • 好吧,WS_CLIPSIBLINGS 确实有效,但我问过这个案例,没有使用WS_CLIPSIBLINGS
  • 如果没有剪辑兄弟姐妹 child1 可以在 z 顺序的顶部,但如果子节点 2 是在子节点 1 之后绘制的,则子节点 2 会被绘制在它的顶部。即使子节点 2 被绘制,使用剪辑兄弟节点也是如此最后当它绘制将被绘制的区域时被剪裁,这样子 1 就不会被过度绘制。
  • @darek_911 如果你不使用SWP_NOREDRAW 标志,每次调用SetWindowPos 都会导致该窗口被重绘。但它不会导致兄弟窗口被重绘。因此,无论您最后调用 SetWindowPos 的哪个窗口看起来都在顶部。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-29
相关资源
最近更新 更多