After I started working on dual monitors, I have found another interesting issue:
- Create a new application with a main form and a sub-form.
- Set the property Position of the sub-form to poMainFormCenter
- Create a button "Show Sub-Form" on main form.
- Move more than 50% area of the main form out of the main screen.
- Click the button, we created.
Solution
This time you have to modify Forms.pas- Copy Forms.pas to your project folder,
- find and replace with the following code,
- and then recompile your project again.
{$IFDEF FIXUP_FORM_POPUP_POSITION}
function GetPrimaryMonitor: TMonitor;
var
I: Integer;
begin
for I := 0 to Screen.MonitorCount - 1 do
begin
Result := Screen.Monitors[I];
if Result.Primary then
Exit;
end;
Result := Screen.Monitors[0];
end;
procedure CenterFormToPrimaryMonitorCenter(var X, Y: Integer;
AForm: TCustomForm);
var
R: TRect;
begin
R := GetPrimaryMonitor.WorkareaRect;
X := R.Left + (R.Right - R.Left - AForm.Width) div 2;
Y := R.Top + (R.Bottom - R.Top - AForm.Height) div 2;
end;
procedure SnapFormToMonitorEdgeOnDemand(var X, Y: Integer;
AForm: TCustomForm);
var
DistanceLeft, DistanceRight: Integer;
CenterMon: TMonitor;
R: TRect;
begin
CenterMon := Screen.MonitorFromPoint(
Point(X + AForm.Width div 2, Screen.DesktopHeight div 2));
R := CenterMon.WorkareaRect;
// Adjust X-pos
DistanceLeft := X - R.Left;
DistanceRight := R.Right - (X + AForm.Width);
if (DistanceLeft < 0) and (DistanceRight < 0) then
begin
if DistanceLeft >= DistanceRight then
X := R.Left // Snap to left edge
else X := R.Right - AForm.Width; // Snap to right edge
end
else if (DistanceLeft < 0) or (DistanceRight < 0) then
begin
if DistanceLeft < 0 then
X := R.Left // Snap to left edge
else X := R.Right - AForm.Width; // Snap to right edge
end;
// Adjust Y-pos
if Y < R.Top then
Y := R.Top
else if Y > R.Bottom - AForm.Height then
Y := R.Bottom - AForm.Height;
end;
{$ENDIF}
procedure TCustomForm.CMShowingChanged(var Message: TMessage);
// ...
if (FPosition = poScreenCenter) or
((FPosition = poMainFormCenter) and (FormStyle = fsMDIChild)) then
begin
if FormStyle = fsMDIChild then
begin
X := (Application.MainForm.ClientWidth - Width) div 2;
Y := (Application.MainForm.ClientHeight - Height) div 2;
end else
begin
{$IFDEF FIXUP_FORM_POPUP_POSITION}
CenterFormToPrimaryMonitorCenter(X, Y, Self);
{$ELSE}
X := (Screen.Width - Width) div 2;
Y := (Screen.Height - Height) div 2;
{$ENDIF}
end;
{$IFDEF FIXUP_FORM_POPUP_POSITION}
SnapFormToMonitorEdgeOnDemand(X, Y, Self);
SetBounds(X, Y, Width, Height);
//SetWindowToMonitor() will cause unexpected popup position change!
{$ELSE}
if X < Screen.DesktopLeft then
X := Screen.DesktopLeft;
if Y < Screen.DesktopTop then
Y := Screen.DesktopTop;
SetBounds(X, Y, Width, Height);
if Visible then SetWindowToMonitor;
{$ENDIF}
end
else if FPosition in [poMainFormCenter, poOwnerFormCenter] then
begin
CenterForm := Application.MainForm;
if (FPosition = poOwnerFormCenter) and (Owner is TCustomForm) then
CenterForm := TCustomForm(Owner);
if Assigned(CenterForm) then
begin
X := ((CenterForm.Width - Width) div 2) + CenterForm.Left;
Y := ((CenterForm.Height - Height) div 2) + CenterForm.Top;
end else
begin
{$IFDEF FIXUP_FORM_POPUP_POSITION}
CenterFormToPrimaryMonitorCenter(X, Y, Self);
{$ELSE}
X := (Screen.Width - Width) div 2;
Y := (Screen.Height - Height) div 2;
{$ENDIF}
end;
{$IFDEF FIXUP_FORM_POPUP_POSITION}
SnapFormToMonitorEdgeOnDemand(X, Y, Self);
SetBounds(X, Y, Width, Height);
//SetWindowToMonitor() will cause unexpected popup position change!
{$ELSE}
if X < Screen.DesktopLeft then
X := Screen.DesktopLeft;
if Y < Screen.DesktopTop then
Y := Screen.DesktopTop;
SetBounds(X, Y, Width, Height);
if Visible then SetWindowToMonitor;
{$ENDIF}
end
else if FPosition = poDesktopCenter then
// ...
end;
No comments:
Post a Comment