Open KennyProgrammer opened 1 year ago
After few hours digging out Win API, i finally found fix for this problem. It was in adjust_maximized_client_rect, in MonitorFromWindow , where its flag was set to MONITOR_DEFAULTTONULL, witch retrieve monitor only if window is intersect that monitor, but when window was minimized by task bar it seems to not intersect with monitor and returns NULL. So to fix this need just set MONITOR_DEFAULTTOPRIMARY instead, in that case that invalid NULL handle to monitor will be retrieved always as primary monitor.
That's curious.
I did some debugging, and I see the same behavior.
I guess when WM_NCCALCSIZE
gets sent, the system is giving us the proposed window rect,
meaning it's not the actual window rect yet.
Calling GetWindowRect
from WM_NCCALCSIZE
seems to confirm that:
So it makes sense that MonitorFromWindow
can't determine which monitor this window intersects.
Using MONITOR_DEFAULTTOPRIMARY
kind of works, but only if the window was maximized on the primary monitor. Otherwise, the monitor work rect and window rect might not even overlap, and you have effectively no client area.
However, we do know the rectangle the window is about to occupy (which is the maximized rect the window is being restored to), so we can use that to determine the right monitor:
- auto monitor = ::MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
+ auto monitor = ::MonitorFromRect(&rect, MONITOR_DEFAULTTONULL);
Maybe this code can solve the problem
/* Adjust client rect to not spill over monitor edges when maximized.
* rect(in/out): in: proposed window rect, out: calculated client rect
* Does nothing if the window is not maximized.
*/
auto adjust_maximized_client_rect(HWND window, RECT& rect) -> void {
if (!maximized(window)) {
return;
}
// get the screen that the window is supposed to be on
WINDOWPLACEMENT wp{};
if (!::GetWindowPlacement(window, &wp)) {
return;
}
POINT center = {
rect.left + (rect.right - rect.left) / 2,
rect.top + (rect.bottom - rect.top) / 2
};
auto monitor = ::MonitorFromPoint(center, MONITOR_DEFAULTTONULL);
if (!monitor) {
return;
}
MONITORINFO monitor_info{};
monitor_info.cbSize = sizeof(monitor_info);
if (!::GetMonitorInfoW(monitor, &monitor_info)) {
return;
}
// when maximized, make the client area fill just the monitor (without task bar) rect,
// not the whole window rect which extends beyond the monitor.
rect = monitor_info.rcWork;
}
adjust_maximized_client_rect for me works fine when i minimize/maximize and restore window within my window, but problem appears when i hide (minimize) window using taskbar, and then again restore it with taskbar, size of the window still not fits correctly (it not fills hole monitor but a make size of my window a little larger ,and shift window down).
Not maximized window (normal)
Maximized window (by double clicking on nc area or my maximize button).
But when window maximized and minimized by taskbar and restore it fails.
And that happens on all sides of the window (i.e it little bigger that usual).
But when i resize taskbar, window again fits currently.
I try everything, send message WM_NCCALCSIZE, when message WM_SHOWWINDOW process, or manually move and change size of the window, but result still the same.
NOTE: In my window i use the same example as BordelessWindow only i change a little the HitTest, but that not causing this problem i've checked.
Edit 1: I look up to the #14 issue, it shoud fix my problem, but it didn't.