+Search dialog: wrong maximized wnd placement
Moderators: Hacker, petermad, Stefan2, white
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
I'm now using the same method as when creating: I do not restrict the window size, and resize it to the correct size after receiving WM_SIZE message. This is ugly with resizing window, but at least it works.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
What about calling MonitorFromWindow + GetMonitorInfo - this gives rcWork rectangle. After overriding the height, this could be a maximized search window size.
TApplication.MessageBox method uses MonitorFromWindow + GetMonitorInfo internally (at least in Delphi 5 and up) - however not rcWork, but rcMonitor.
TApplication.MessageBox method uses MonitorFromWindow + GetMonitorInfo internally (at least in Delphi 5 and up) - however not rcWork, but rcMonitor.
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
The problem isn't when the window is fully maximized (after starting the search). It only happens when the height is restricted just to the tabbed notebook with the search settings.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
I see - but this would also prevent users from dragging the window to other screens by dragging the title bar...
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
Can you try with beta 5 now whether you still get a wrong search dialog size?
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
-
- Power Member
- Posts: 872
- Joined: 2013-09-04, 14:07 UTC
I could not reproduce it with TC8.50b5 x64 in Windows 7 x64 Pro (Aero enabled).
My system has a non-standard dual monitor setup (one display landscape which is secondary output port of the gfx card but primary display in Windows, and one display in portrait mode, with one desktop spanning across both displays.)
Additionally to what was described in this thread, I tried moving/locking the taskbar around in different variations, tried "cheating" by manipulating the coordinates of the search window saved in TC's INI file, etc..., but i could never manage to get the maximized or maximized+docked search window outside the desktop area nor obstructed by a locked taskbar (unless i manually tore off the docked window with the mouse, of course).
My system has a non-standard dual monitor setup (one display landscape which is secondary output port of the gfx card but primary display in Windows, and one display in portrait mode, with one desktop spanning across both displays.)
Additionally to what was described in this thread, I tried moving/locking the taskbar around in different variations, tried "cheating" by manipulating the coordinates of the search window saved in TC's INI file, etc..., but i could never manage to get the maximized or maximized+docked search window outside the desktop area nor obstructed by a locked taskbar (unless i manually tore off the docked window with the mouse, of course).
I just made some tests with Windows 8.1 Preview 32-bit and TC 32-bit:
- I was able to reproduce the problem with TC 8.50 beta 1 (as described in the first post in this thread).
- I was able to reproduce the problem with TC 8.50 beta 4 (after restoring and maximizing search window again).
- I was unable to reproduce the problem with TC 8.50 beta 5.
So the problem seems to be fixed now, although I could see a fully maximized search window for a moment, even without search results.
- I was able to reproduce the problem with TC 8.50 beta 1 (as described in the first post in this thread).
- I was able to reproduce the problem with TC 8.50 beta 4 (after restoring and maximizing search window again).
- I was unable to reproduce the problem with TC 8.50 beta 5.
So the problem seems to be fixed now, although I could see a fully maximized search window for a moment, even without search results.
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
Yes, this full screen is unfortunately necessary to avoid the Windows 8 bug (failing to correctly resize to full width without full height).
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
I just made some tests with Windows 8.1 Preview. The code below seems to solve the problem completely, without that full screen hack (not tested with multimonitor system, however should work properly).
Declaration:
Implementation:
Regards
Declaration:
Code: Select all
procedure WMWindowPosChanging(var Message: TWMWindowPosChanging); message WM_WINDOWPOSCHANGING;
Code: Select all
procedure TForm1.WMWindowPosChanging(var Message: TWMWindowPosChanging);
var
Placement: TWindowPlacement;
MonInfo : TMonitorInfo;
BorderX : Integer;
BorderY : Integer;
begin
BorderX:=-1; {Make compiler happy}
BorderY:=-1; {Make compiler happy}
if Win32Platform = VER_PLATFORM_WIN32_NT then
if HandleAllocated then
with Message do
if WindowPos <> nil then
with WindowPos^ do
if flags and (SWP_NOMOVE or SWP_NOSIZE) = 0 then
repeat {until True}
Placement.length:=SizeOf(TWindowPlacement);
if not GetWindowPlacement(Handle,@Placement) then
Break;
{Check if maximizing now}
if not ((WindowState <> wsMaximized) and (Placement.showCmd = SW_MAXIMIZE)) then
Break;
{Maximized window is a bit larger than the screen size - get the difference}
if BorderStyle = bsSingle then
begin
BorderX:=GetSystemMetrics(SM_CXDLGFRAME);
BorderY:=GetSystemMetrics(SM_CYDLGFRAME);
end else
if BorderStyle = bsSizeable then
begin
BorderX:=GetSystemMetrics(SM_CXSIZEFRAME);
BorderY:=GetSystemMetrics(SM_CYSIZEFRAME);
end else
Break;
MonInfo.cbSize:=SizeOf(MonInfo);
if not GetMonitorInfo(MonitorFromWindow(Handle,MONITOR_DEFAULTTONEAREST),@MonInfo) then
Break;
{Adjust window size to work area}
with MonInfo.rcWork do
begin
if x < Left-BorderX then
begin
Dec(cx,Left-BorderX-x);
Inc(x,Left-BorderX-x);
end;
if x+cx > Right+BorderX then
Dec(cx,x+cx-Right-BorderX);
if y < Top-BorderY then
begin
Dec(cy,Top-BorderY-y);
Inc(y,Top-BorderY-y);
end;
if y+cy > Bottom+BorderY then
Dec(cy,y+cy-Bottom-BorderY);
end;
until True;
inherited;
end;
- ghisler(Author)
- Site Admin
- Posts: 50541
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
Thanks for your code - looks good, but I will have to check it on various systems including Linux first to make sure that it doesn't cause any other side effects...
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
I discovered some other problem, where Beta 6 completely fails to place the window properly, and Beta 7 is still not ideal. This problem is somewhere inside Delphi 2 VCL library. The code from my previous post works properly when compiled with Delphi 5, but not properly when compiled with Delphi 2.
Steps to reproduce with Windows 8.1 (final version):
1) place taskbar on the TOP edge of the screen,
2) press Alt+F7 and maximize search window (if it was shown as maximized, restore it and maximize it again),
3) don't close search window - move taskbar to the RIGHT edge of the screen,
4) maximize search window again.
Now we can see that:
- search window in Beta 6 overlaps with the taskbar,
- search window in Beta 7 doesn't overlap anymore, but is placed not at the top of the screen, but rather a bit lower - the difference is equal to the height of the taskbar before moving it to the right.
So the general observation is: for some unknown reason, Delphi 2 remembers work area from the moment of creating a window and passes this remembered work area to the window (during WM_GETMINMAXINFO) for all the window lifetime.
So I modified the code - now it doesn't only trim coordinates, but it totally replaces these coordinates with the actual work area and only after this it trims the height to the maximum allowed value. This code works properly even with Delphi 2.
Note: there is a bug in Delphi 2 compiler - using "repeat .. until True" statement may raise an internal compiler error or even generate invalid code - i.e. invalid jumps in places of "Break" statements (as I checked with a disassembler, one of jumps was totally outside the procedure). So I replaced "until True" with "Break" + "until False".
Regards
Steps to reproduce with Windows 8.1 (final version):
1) place taskbar on the TOP edge of the screen,
2) press Alt+F7 and maximize search window (if it was shown as maximized, restore it and maximize it again),
3) don't close search window - move taskbar to the RIGHT edge of the screen,
4) maximize search window again.
Now we can see that:
- search window in Beta 6 overlaps with the taskbar,
- search window in Beta 7 doesn't overlap anymore, but is placed not at the top of the screen, but rather a bit lower - the difference is equal to the height of the taskbar before moving it to the right.
So the general observation is: for some unknown reason, Delphi 2 remembers work area from the moment of creating a window and passes this remembered work area to the window (during WM_GETMINMAXINFO) for all the window lifetime.
So I modified the code - now it doesn't only trim coordinates, but it totally replaces these coordinates with the actual work area and only after this it trims the height to the maximum allowed value. This code works properly even with Delphi 2.
Note: there is a bug in Delphi 2 compiler - using "repeat .. until True" statement may raise an internal compiler error or even generate invalid code - i.e. invalid jumps in places of "Break" statements (as I checked with a disassembler, one of jumps was totally outside the procedure). So I replaced "until True" with "Break" + "until False".
Code: Select all
procedure TForm1.WMWindowPosChanging(var Message: TWMWindowPosChanging);
var
Placement: TWindowPlacement;
MonInfo : TMonitorInfo;
BorderX : Integer;
BorderY : Integer;
Diff : Integer;
begin
BorderX:=-1; {Make compiler happy}
BorderY:=-1; {Make compiler happy}
if Win32Platform = VER_PLATFORM_WIN32_NT then
if HandleAllocated then
with Message do
if WindowPos <> nil then
with WindowPos^ do
if flags and (SWP_NOMOVE or SWP_NOSIZE) = 0 then
repeat {until True}
Placement.length:=SizeOf(Placement);
if not GetWindowPlacement(Handle,@Placement) then
Break;
{Check if maximizing now}
if not ((WindowState <> wsMaximized) and (Placement.showCmd = SW_MAXIMIZE)) then
Break;
{Maximized window is a bit larger than the screen size - get the difference}
if BorderStyle = bsSingle then
begin
BorderX:=GetSystemMetrics(SM_CXDLGFRAME);
BorderY:=GetSystemMetrics(SM_CYDLGFRAME);
end else
if BorderStyle = bsSizeable then
begin
BorderX:=GetSystemMetrics(SM_CXSIZEFRAME);
BorderY:=GetSystemMetrics(SM_CYSIZEFRAME);
end else
Break;
MonInfo.cbSize:=SizeOf(MonInfo);
if not GetMonitorInfo(MonitorFromWindow(Handle,MONITOR_DEFAULTTONEAREST),@MonInfo) then
Break;
{Replace window size with work area}
with MonInfo.rcWork do
begin
x:=Left-BorderX;
cx:=Right-Left+2*BorderX;
y:=Top-BorderY;
cy:=Bottom-Top+2*BorderY;
end;
{Trim window width - center if trimmed}
if Constraints.MaxWidth > 0 then
begin
Diff:=cx-Constraints.MaxWidth;
if Diff > 0 then
begin
Dec(cx,Diff);
Inc(X,Diff div 2);
end;
end;
{Trim window height - move to top if trimmed}
if Constraints.MaxHeight > 0 then
begin
Diff:=cy-Constraints.MaxHeight;
if Diff > 0 then
Dec(cy,Diff);
end;
{Warning: there is some problem with Delphi 2 compiler, and using
"until True" statement may either raise an internal compiler error,
or generate invalid assembler code. So this statement was replaced
with "Break" and "until False" statements}
Break;
until False;
inherited;
end;