1

I have the following WNDPROC:

    LRESULT CALLBACK window_processing(HWND window, UINT message, WPARAM wPara, LPARAM lParam) {
#if WITH_DEBUG_UI
        if(ImGui_ImplWin32_WndProcHandler(window, message, wPara, lParam)) {
            return true;
        }
#endif
        switch(message) {
            case WM_QUIT:
                PostQuitMessage(0);
                close_window();
                exit();
                return true;
                break;
            case WM_SIZE: {
                auto new_size = get_window_size();
                if(app.resize_handler) {
                    app.resize_handler(new_size.width, new_size.height);
                    return true;
                }
                break;
            }

            case WM_SIZING: {
                RECT new_rect = *((LPRECT)(lParam));
                GetClientRect(app.wnd, &new_rect);

                auto new_size = window_size{std::size_t(new_rect.right - new_rect.left), std::size_t(new_rect.bottom - new_rect.top)};
                if(app.resize_handler) {
                    app.resize_handler(new_size.width, new_size.height);
                    return true;
                }
            } break;
        }
        return DefWindowProc(window, message, wPara, lParam);
    }

app.resize_handler is the following function:

void d3d11_loading_screen_renderer::window_size_changed(const std::size_t w, const std::size_t h) {
        std::cout << "W : " << w << " H : " << h << std::endl;
        back_buffer_rtv.Reset();
        back_buffer.Reset();
        swapchain->ResizeBuffers(0, w, h, DXGI_FORMAT_UNKNOWN, 0);
        swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), &back_buffer);
        back_buffer_rtv = create_back_buffer_rtv(device.Get(), back_buffer.Get());
        back_buffer_viewport = viewport_from_window_size(window_size{w,h});
    }

The WM_SIZE event is correctly handled; When the resizing is finished, the back buffers are correctly resized and refreshed.

But with WM_SIZING, nothing happens. the back buffer stays the same size, as seen in the following gif:

enter image description here

You can see how it resizes the buffers correctly when i finish resizing, but not during the resizing.

Anyone know what that could cause?

Edit: i dont receive any errors and the received size is correct.

Raildex
  • 3,406
  • 1
  • 18
  • 42
  • `GetClientRect(app.wnd, &new_rect);` - you're overwriting the new rectangle with the old rectangle. – Raymond Chen Jul 12 '22 at 20:46
  • @RaymondChen Am I though? the new window size is untouched, I just copy it and get the `ClientRect` of it. According to Docs you are supposed to override the size in `lParam` if you want to override the new window size. – Raildex Jul 13 '22 at 03:41
  • If I do `LPRECT rect = (LPRECT)(lParam); GetClientRect(app.wnd, (LPRECT)(lParam));` the Window shrinks to a size of 0, since Client Rect is always smaller than the window – Raildex Jul 13 '22 at 03:49
  • The `(LPRECT)(lParam)` is the rectangle the user is proposing. Use that rectangle. Don't overwrite it by calling GetClientRect. – Raymond Chen Jul 13 '22 at 04:39
  • @RaymondChen ClientRect is the Rect without Border, which is what i need/want. And it does not force a resize of the buffers aswell. – Raildex Jul 13 '22 at 04:50
  • 1
    Then use AdjustWindowRect with the rect provided in the lParam. The important thing is to use the rectangle in the lParam, since that's telling you the *future* window size; i.e., the size you are going to be resized to. Calling GetClientRect gives you the size you are being resized *from*, which is not interesting. – Raymond Chen Jul 13 '22 at 05:09
  • 1
    @RaymondChen The problem is not the Rect, but DXGISwapChain->ResizeBuffers, which does not update the framebuffers. I receive the **correct**, desired Rect into ResizeBuffers already. – Raildex Jul 13 '22 at 05:14
  • I have updated the code and the gif. – Raildex Jul 13 '22 at 05:19
  • 1
    Doesn't resizing windows run a somewhat funky modal message loop, where GDI behaves differently? Because while resizing, you also never get any flicker, even if you're doing all kinds of things wrong w.r.t flicker reduction strategies (like missing `WS_CLIPCHILDREN`, etc.). So I assume GDI fires up some advanced paint logic during that loop. So maybe you're just seeing GDI being "smart". I never got this particular thing working with DXGI either, but I didn't really try very hard since I figured that this isn't worth putting any significant effort into. All games I tested behave like this. – dialer Jul 13 '22 at 06:31
  • [It's recommended that you call ResizeBuffers when a client window is resized(that is, when an application receives a WM_SIZE message).](https://learn.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiswapchain-resizebuffers#remarks) – YangXiaoPo-MSFT Jul 13 '22 at 06:32
  • 1
    I would still be interested to see the solution though, purely out of interest of how big and convoluted it is... – dialer Jul 13 '22 at 06:32
  • 1
    Oh just to be clear: This isn't really about `WM_SIZE` vs `WM_SIZING`, since you will get `WM_SIZE` messages just fine during the resize operation. The reason your code worked before you fixed the `ClientRect` is most likely because the `WM_SIZE` messages (following each `WM_SIZING`) ended up fixing it. But when resizing begins and ends, you get an extra set of messages for that (forgot which messages exactly), which end up launching, and eventually terminating, the modal resizing message loop. – dialer Jul 13 '22 at 06:40
  • @dialer but I receive the new size **during** resizing? If there is a different loop for `WM_BEGINSIZEMOVE` and `WM_EXITSIZEMOVE` how am I able to catch and process the new sizes during the dragging? – Raildex Jul 14 '22 at 05:37
  • @Raildex During resizing (while the user is actively dragging the window border), you will get a `WM_SIZING` *followed by a `WM_SIZE`* for each incremental change in size that your window experiences (i.e. you get a message pair for every little bit the user is moving the mouse). You don't need to handle `WM_SIZING` at all. `WM_SIZING` is only rarely used in cases where you need to intervene *before* the window size has actually changed. And I don't understand the second question. The modal loop calls your WndProc normally, including `WM_SIZE`. That's the point of a modal loop. – dialer Jul 14 '22 at 06:20
  • @dialer If that's true, that would mean my code is correct and the Resizing of the Buffers is simply bugged? – Raildex Jul 14 '22 at 06:35
  • @Raildex If you completely remove the `WM_SIZING` handler, then your code is correct for some definitions of correct. But during the resize loop, windows are drawn differently. It's not just DXGI, it's raw GDI as well. Remember how resizing windows looked in Win95 and Win3.1? The contents *weren't being drawn*, you just saw a dithered outline during dragging. If they just drew themselves normally during resizing, classic Win32 applications would flicker *like crazy*, so I have to assume that MS needed to pull a few stunts (and probably dirty tricks) to make it look nice. – dialer Jul 14 '22 at 06:59
  • @dialer Alright then. Thank you for the clarification. Can you make a summary as an an answer? – Raildex Jul 14 '22 at 09:14
  • I don't intend to post an answer because I don't know the solution to your problem. There might very well *be* a good solution. If anybody knows, it would be someone like @Raymond here. I was just explaining that you were looking for the solution in the wrong place. And I honestly doubt that you are the first person in the world who tried to have their game render properly while the windows is being resized. *I still do* want to know the real answer. – dialer Jul 14 '22 at 14:06
  • From the GIF, it is evident that ResizeBuffers is working. When you resize the window, the new sizes are displayed to the debug window. When you make the window smaller, and then bigger, only the pixels from the smallest size are retained, which confirms that the buffers really did get smaller. The reason why you get blackness when you resize bigger is that you haven't rendered to the larger surfaces yet! – Raymond Chen Nov 28 '22 at 20:54
  • @RaymondChen as you can see, `WM_SIZE` and `WM_SIZING` call the resize handler of the renderer. Why are there black spots when the new size is correct? – Raildex Nov 29 '22 at 07:14
  • Because you are not rendering into the newly-resized bitmap. Add some debug output to your render function to confirm. My guess is that you render in your message loop, but resizing is a modal operation so your message loop doesn't regain control until the resize is complete. – Raymond Chen Nov 29 '22 at 16:37

0 Answers0