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