子窗体弹出位置错误

    技术2022-05-11  71

    在设计窗体时通常会把子窗体的 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 里面定义一个环境变量,这样以后你只要给其它工程的路径里面添加这个环境变量,这些工程都可以使用你修改过的代码了。至于修改源码的一些方法和技巧,请参考 如何访问私有成员变量和函数  


    最新回复(0)