darek_911
darek_911

Reputation: 77

How to use the SetWindowPos function?

I'd like to create a Windows app consisting of a main parent window and several child windows. Here is an excerpt of the code I have so far:

...

   // -----> 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);

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

The problem is with the SetWindowPos() function. I can't understand how it really works. I thought that calling it like this:

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);

Would move the Child 1 window to the top of all the app windows (as the doc says for the HWND_TOP option: Places the window at the top of the Z order).

BUT, the windows are still drawned in the creation order:

image

Shouldn't SetWindowPos() move firstly Child 2 over Child 3, and next Child 1 over Child 2, making the windows laid up in the reverse order than they were created, with Child 1 on top?

Upvotes: 2

Views: 5562

Answers (1)

jwezorek
jwezorek

Reputation: 9545

Make the child windows all have the window style WS_CLIPSIBLINGS along with WS_CHILD etc.

From Microsoft's documentation:

If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible, when drawing within the client area of a child window, to draw within the client area of a neighboring child window.

Basically if the child windows do not clip each other then the order in which they are painted (which is arbitrary) determines the visual z-order.

Below for instance is your code with the message box stuff removed, using WS_VISIBLE instead of ShowWindow, adding a border for visibility, and using 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;
}

which yields overlapping children child1 is on top.

Upvotes: 3

Related Questions