Advertisement

problem with windows API: can't get a correctly sized client area

Started by June 15, 2018 04:56 PM
10 comments, last by matt77hias 6 years, 6 months ago

This is the code I have:


  //Create Window
    DWORD windowStyle = WS_VISIBLE;
    DWORD windowExStyle = WS_EX_OVERLAPPEDWINDOW;

    SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);

    RECT client{ 0, 0, 100, 40 };
    UINT dpi = GetDpiForSystem();

    AdjustWindowRectExForDpi(&client, windowStyle, false, windowExStyle, dpi);

    UINT adjustedWidth = client.right - client.left;
    UINT adjustedHeight = client.bottom - client.top;

    m_hwnd = CreateWindowEx(windowExStyle,
                            className.c_str(),
                            windowName.c_str(),
                            windowStyle,
                            CW_USEDEFAULT,
                            CW_USEDEFAULT,
                            adjustedWidth,
                            adjustedHeight,
                            nullptr,
                            nullptr,
                            m_hInstance,
                            m_emu
    );

The generated window has a client area of 1 pixel in height, even though I'm asking for 40. so I'm always getting 39 pixel less than what I need...can someone help me with this? x_x

Why do you use all this dpi boiler plate:


SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
RECT client{ 0, 0, 100, 40 };
UINT dpi = GetDpiForSystem();
AdjustWindowRectExForDpi(&client, windowStyle, false, windowExStyle, dpi);

instead of something like:


AdjustWindowRect(&client, windowStyle, FALSE);

 

🧙

Advertisement

because what you suggested was my first attempt, and still didn't got me the correct client size ?

I found a solution btw, it turns out even though as you can see from my code above I didn't specified the window style flag WS_CAPTION, you get one, so it wasn't being subtracted from the function math but it was being created even if I didn't asked for one... x_x

FWIIW I use something like:


static constexpr DWORD s_default_window_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;

Which imho is kind of a good default for graphical applications like games.

 

18 hours ago, MarcusAseth said:

I didn't specified the window style flag WS_CAPTION

MSDN is not really mentioning any prerequisites for WS_VISIBLE. Though, the documentation contains some flaws and ambiguous explanations.

🧙

WS_VISIBLE is so that you don't have to call ShowWindow() after you create the window, it will show by default thanks to that flag, so yeah, probably make 0 defference passing that to AdjustWindowRect or not.

Documentation says you cannot specify the WS_OVERLAPPED style when you call AdjustWindowRect, therefore you're probably getting an incorrect client size if you're passing that to it, I guess

Advertisement

I use windows with WS_OVERLAPPED set but don't use AdjustWindowRect, instead


void Surface::Size(uint32 width, uint32 height)
{
	RECT rect; Drough::memset(&rect, 0, sizeof(rect));
	GetWindowRect((HWND) handle, &rect);
	SetWindowPos((HWND) handle, 0, rect.left, rect.top, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}

does well for me

5 hours ago, Shaarigan said:

I use windows with WS_OVERLAPPED set but don't use AdjustWindowRect, instead



void Surface::Size(uint32 width, uint32 height)
{
	RECT rect; Drough::memset(&rect, 0, sizeof(rect));
	GetWindowRect((HWND) handle, &rect);
	SetWindowPos((HWND) handle, 0, rect.left, rect.top, width, height, SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
}

does well for me

Well, you're getting a wrong client area for sure, unless I'm missing something here.

Try and make a windows of height 1px and see if effectevely you get 1px or 0px.

I didn't wrote that this works, I wrote that this works with WM_OVERLAPPED set ;)

What I think you could do is calling the window without the border flags (WS_OVERLAPPEDWINDOW, WS_THICKFRAME) and then set the border flags to see how huge the difference is in height between those two window rects. This way, you know the title height because this can change between windows versions.

 

I utilized this via


void Surface::Style(Surface::SurfaceStyle style)
	{
		uint32 flags = GetWindowLongA((HWND) handle, GWL_STYLE);
		if(style == Surface::Windowed && HasFlag(flags, WS_POPUP))
		{
			flags ^= WS_POPUP;
			flags |= (WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME);
		}
		else if(style == Surface::Borderless && HasFlag(flags, WS_OVERLAPPEDWINDOW))
		{
			flags ^= WS_OVERLAPPEDWINDOW;
			flags |= WS_POPUP;
		}
		else if(style == Surface::Borderless && (HasFlag(flags, (WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME))))
		{
			flags ^= (WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME);
			flags |= WS_POPUP;
		}

		SetWindowLongA((HWND) handle, GWL_STYLE, flags);
	}

 

On 6/16/2018 at 3:31 PM, MarcusAseth said:

Documentation says you cannot specify the WS_OVERLAPPED style when you call AdjustWindowRect, therefore you're probably getting an incorrect client size if you're passing that to it, I guess

Thanks, that is interesting! Though, I need to recheck, but I have seen many DirectX samples from Microsoft themselves using this combination. I use the combination without having any problems, but I don't use a menu bar. Maybe adjusting fails with a menu bar?

Edit: Microsoft seems to violate this. Their samples use WS_OVERLAPPEDWINDOW which includes WS_OVERLAPPED.

WS_OVERLAPPEDWINDOW (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX)

🧙

This topic is closed to new replies.

Advertisement