2013-03-07 136 views
1

我有一个组合框有两个选项,两个选项都触发窗体大小调整。我的想法是隐藏并显示基于选择的其他控件。更改窗体大小后的窗体

当我更改窗体宽度时,大小会根据需要进行更改,但窗体现在不再位于屏幕的中心。我可以在改变窗体宽度的同时来回移动窗体的XY位置吗?

procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject); 
begin 
    if(SpecialFilesComboBox.ItemIndex = 0) then begin 
    //No special files 
    Width := 412; 
    Height := 423; 
    ... 
    end 
    else begin 
    //Yes special files 
    Width := 893; 
    Height := 423; 
    ... 
    end; 
end; 
+0

PS我可以'if'语句后没有简单的调用了这一点,我会得到一个访问冲突:'BugReportFrm.Position := poMainFormCenter;' – ikathegreat 2013-03-07 06:31:22

+1

是BugReportFrm分配的?您的代码显示TReportFrm。只是不要使用实例:Position:= poMainFormCenter; – bummi 2013-03-07 06:38:54

+0

只需根据需要设置“顶部”和“左侧”即可。从Monitor.WorkAreaRect – 2013-03-07 06:41:06

回答

5

一个非常简单的ReCenter功能可能是这样的:

procedure TReportFrm.ReCenter; 
var 
    LRect: TRect; 
    X, Y: Integer; 
begin 
    LRect := Screen.WorkAreaRect; 
    X := LRect.Left + (LRect.Right - LRect.Left - Width) div 2; 
    Y := LRect.Top + (LRect.Bottom - LRect.Top - Height) div 2; 
    SetBounds(X, Y, Width, Height); 
end; 

procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject); 
begin 
    if(SpecialFilesComboBox.ItemIndex = 0) then begin 
    //No special files 
    Width := 412; 
    Height := 423; 
    ... 
    end 
    else begin 
    //Yes special files 
    Width := 893; 
    Height := 423; 
    ... 
    end; 
    ReCenter; 
end; 

IT中心的窗口到屏幕的工作区,你可能希望将其中心到其他的参考,在这种情况下,它是由给你确定有意义的矩形。

+0

完美计算。最好/最直接的delphi解决方案我已经在一段时间了,谢谢。 – ikathegreat 2013-03-07 07:04:09

+4

这个数学在这里是错误的。只有在工作区域顶部和左侧均为零的情况下才能工作。工作区域的中心是(左+右)div 2.你的减号是错误的。该代码也否认了多监视器系统的存在。 – 2013-03-07 07:34:26

+0

@大卫哦,我的...我不确定屏幕是否可以有不同的左/顶比0,0,但我更新了我的答案。如上所述,它将表格置于屏幕Workarea中,并且很大程度上展示了如何在答案中获取表单监视器的WorkArea。我不同意你提出的(左+右)div 2解决方案,你确定吗?我手头没有其他显示器可供测试。 – jachguate 2013-03-07 08:16:46

5

多显示器系统现在很常见。放置在屏幕的中心可能会将表格分散到多个显示器上。这是不可取的。

所以我中心形式的监视器上:

R := Form.Monitor.WorkAreaRect; 
Form.Left := (R.Left+R.Right-Form.Width) div 2; 
Form.Top := (R.Top+R.Bottom-Form.Height) div 2; 

由于@bummi指出的那样,你可以这样写:

Form.Position := poScreenCenter; 

这几乎可以作为你的愿望。我将把这个表格放在屏幕上。但是,它总是选择默认监视器。因此,使用该代码可能会导致您的表单被移到不同的显示器上,我认为这绝对不可取。

而是迫使形式中心,你可以决定,而不是在所有侧面扩大或缩小它:

procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject); 
var 
    NewLeft, NewTop, NewWidth, NewHeight: Integer; 
begin 
    if(SpecialFilesComboBox.ItemIndex = 0) then begin 
    //No special files 
    NewWidth := 412; 
    NewHeight := 423; 
    ... 
    end 
    else begin 
    //Yes special files 
    NewWidth := 893; 
    NewHeight := 423; 
    ... 
    end; 

    NewLeft := Left + (Width-NewWidth) div 2; 
    NewTop := Top + (Top-NewHeight) div 2; 
    NewBoundsRect := Rect(NewLeft, NewTop, NewLeft+NewWidth, NewTop+NewHeight); 
    BoundsRect := NewBoundsRect; 
end; 

如果你想获得真正可爱的你会调整边界RECT从而使新大小和定位的形式没有离开显示器的边缘。

procedure MakeAppearOnScreen(var Rect: TRect); 
const 
    Padding = 24; 
var 
    Monitor: HMonitor; 
    MonInfo: TMonitorInfo; 
    Excess, Width, Height: Integer; 
begin 
    Monitor := MonitorFromPoint(Point((Rect.Left+Rect.Right) div 2, (Rect.Top+Rect.Bottom) div 2), MONITOR_DEFAULTTONEAREST); 
    if Monitor=0 then begin 
    exit; 
    end; 
    MonInfo.cbSize := SizeOf(MonInfo); 
    if not GetMonitorInfo(Monitor, @MonInfo) then begin 
    exit; 
    end; 
    Width := Rect.Right-Rect.Left; 
    Height := Rect.Bottom-Rect.Top; 

    Excess := Rect.Right+Padding-MonInfo.rcWork.Right; 
    if Excess>0 then begin 
    dec(Rect.Left, Excess); 
    end; 
    Excess := Rect.Bottom+Padding-MonInfo.rcWork.Bottom; 
    if Excess>0 then begin 
    dec(Rect.Top, Excess); 
    end; 
    Excess := MonInfo.rcWork.Left+Padding-Rect.Left; 
    if Excess>0 then begin 
    inc(Rect.Left, Excess); 
    end; 
    Excess := MonInfo.rcWork.Top+Padding-Rect.Top; 
    if Excess>0 then begin 
    inc(Rect.Top, Excess); 
    end; 
    Rect.Right := Rect.Left+Width; 
    Rect.Bottom := Rect.Top+Height; 
end; 

接着前面的代码示例将改变这样的:

NewBoundsRect := Rect(NewLeft, NewTop, NewLeft+NewWidth, NewTop+NewHeight); 
MakeAppearOnScreen(NewBoundsRect); 
BoundsRect := NewBoundsRect; 
+0

至于位置将按照不同的设置所需的工作,我没有看到重新补充的需要。 – bummi 2013-03-07 07:49:46

+1

@bummi位置仅适用于我认为的表单的初始显示。 – 2013-03-07 08:00:57

+0

我无法谈论D7之前的版本,但是这会起作用:procedure TForm1.Button1Click(Sender:TObject); 开始 位置:= poScreenCenter; 结束; – bummi 2013-03-07 09:17:38

相关问题