在设计窗体时通常会把子窗体的 Position 设置成 poMainFormCenter。也就是说,子窗体弹出的位置是主窗体的正中。但是如果把主窗体拖动到屏幕左下角,而且主窗体的50%部分已经超出了屏幕范围,这个时候主窗体的正中其实已经不在屏幕范围之内了。这个时候弹出的子窗体可能部分或者完全处在屏幕之外了。
具体解决方法:修改 Forms.pas,修改 procedure TcustomForm.CMShowingChanged(var Message: Tmessage);
procedure TCustomForm.CMShowingChanged(var Message: TMessage); const ShowCommands: array[TWindowState] of Integer = (SW_SHOWNORMAL, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED); var X, Y: Integer; NewActiveWindow: HWnd; CenterForm: TCustomForm; begin if not (csDesigning in ComponentState) and (fsShowing in FFormState) then raise EInvalidOperation.Create(SVisibleChanged); Application.UpdateVisible; Include(FFormState, fsShowing); try if not (csDesigning in ComponentState) then begin if Showing then begin try DoShow; except Application.HandleException(Self); end; 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 X := (Screen.Width - Width) div 2; Y := (Screen.Height - Height) div 2; end; if X < Screen.DesktopLeft then X := Screen.DesktopLeft; if Y < Screen.DesktopTop then Y := Screen.DesktopTop; if Y > Screen.WorkAreaHeight - Height then //PATCH Y := Screen.WorkAreaHeight - Height; //PATCH SetBounds(X, Y, Width, Height); if Visible then SetWindowToMonitor; 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 X := (Screen.Width - Width) div 2; Y := (Screen.Height - Height) div 2; end; if X < Screen.DesktopLeft then X := Screen.DesktopLeft; if Y < Screen.DesktopTop then Y := Screen.DesktopTop; if Y > Screen.WorkAreaHeight - Height then //PATCH Y := Screen.WorkAreaHeight - Height; //PATCH SetBounds(X, Y, Width, Height); if Visible then SetWindowToMonitor; end else if FPosition = poDesktopCenter then begin if FormStyle = fsMDIChild then begin X := (Application.MainForm.ClientWidth - Width) div 2; Y := (Application.MainForm.ClientHeight - Height) div 2; end else begin X := (Screen.DesktopWidth - Width) div 2; Y := (Screen.DesktopHeight - Height) div 2; end; if X < Screen.DesktopLeft then //PATCH X := Screen.DesktopLeft; // if Y < Screen.DesktopTop then // Y := Screen.DesktopTop; // if Y > Screen.WorkAreaHeight - Height then // Y := Screen.WorkAreaHeight - Height; //PATCH SetBounds(X, Y, Width, Height); end;
好了!大功告成。将修改后的 Forms.pas 复制到您的工程目录下,再次编译您的程序。这个问题消失了。
此外,对于修改 Delphi 的源文件,我建议把所有修改过的源文件都放在一个新的目录 (例如 PatchedVCLs),然后在 Delphi 里面定义一个环境变量,这样以后你只要给其它工程的路径里面添加这个环境变量,这些工程都可以使用你修改过的代码了。至于修改源码的一些方法和技巧,请参考 如何访问私有成员变量和函数。