窗体自适应屏幕分辨率

话说Delphi有个很强的窗体设计器,这一点让VC粉丝垂涎三尺而不可得。但是,Delphi里设计的窗体并没有自动适应屏幕分辨率的属性,也就是说,软件设计时调整完美的窗体控件布局,在不同屏幕分辨率的机器上运行时可能会变得面目全非。控件之间会相互移位,有的甚至移出窗体再也找不到了。

这个问题在网上搜索过多次,但大都依据控件方法ScaleBy或者ChangeScale。采用这两个方法进行自适应调整,我自己都试过,但效果并不理想。后来我自己也写了一个继承自窗体的基类,覆盖构造函数,调用自己的一个设备分辨率自适应方法,该方法遍历窗体上所有控件,并按照设计时的屏幕分辨率和当前屏幕分辨率的比值,逐一计算控件的位置和尺寸。这个想法是不错,效果也是有的,比单纯的采用ScaleBy或者ChangeScale方法要好,但也不是非常理想,没有达到自己设想的要求。原因在哪里,一直不知道。

我原来的代码曾经发布在Delphi盒子和CSDN上。

这个问题今天终于得以彻底解决了!!

原因是,我原以为将所有控件的Align属性设为alnone,Anchors属性设为空[],控件位置和尺寸就不会受其容器尺寸改变的影响。今天我在设计期对此进行试验时,发现不是这样。当窗体大小改变的时候,即使某个控件的Align:=alNone,Anchors:=[],它依然会随着窗体尺度的变化而变化。这意味着我需要一个数组事先保存所有控件的原始位置和尺寸。在窗体因为屏幕分辨率的改变而自动调整时,计算的依据依然是不变的原始窗体位置尺寸数据,这样问题就解决了。

闲话少说,上源码。

unit uMyClassHelpers;

interface

Uses

SysUtils,Windows,Classes,Graphics, Controls,Forms,Dialogs,
  uMySysUtils;

Const   //记录设计时的屏幕分辨率

OriWidth=1366;
  OriHeight=768;

Type

TfmForm=Class(TForm)   //实现窗体屏幕分辨率的自动调整
  Private
    fScrResolutionRateW: Double;
    fScrResolutionRateH: Double;
    fIsFitDeviceDone: Boolean;
    fPosition:Array of TRect;
    procedure FitDeviceResolution;
  Protected
    Property IsFitDeviceDone:Boolean Read fIsFitDeviceDone;
    Property ScrResolutionRateH:Double Read fScrResolutionRateH;
    Property ScrResolutionRateW:Double Read fScrResolutionRateW;
  Public
    Constructor Create(AOwner: TComponent); Override;
  End;

TfdForm=Class(TfmForm)   //增加对话框窗体的修改确认
  Protected
    fIsDlgChange:Boolean;
  Public
  Constructor Create(AOwner: TComponent); Override;
  Property IsDlgChange:Boolean Read fIsDlgChange default false;
 End;

implementation

Constructor TfmForm.Create(AOwner: TComponent);
begin
 Inherited Create(AOwner);
  fScrResolutionRateH:=1;
  fScrResolutionRateW:=1;
  Try
    if Not fIsFitDeviceDone then
    Begin
      FitDeviceResolution;
   fIsFitDeviceDone:=True;
    End;
  Except
  fIsFitDeviceDone:=False;
  End;
end;

procedure TfmForm.FitDeviceResolution;
Var
  i:Integer;
  LocList:TList;
  LocFontSize:Integer;
  LocFont:TFont;
  LocCmp:TComponent;
  LocFontRate:Double;
  LocRect:TRect;
  LocCtl:TControl;
begin
  LocList:=TList.Create;
  Try
    Try
      if (Screen.width<>OriWidth)OR(Screen.Height<>OriHeight) then
      begin
        Self.Scaled:=False;
        fScrResolutionRateH:=screen.height/OriHeight;
        fScrResolutionRateW:=screen.Width/OriWidth;
        Try
          if fScrResolutionRateH<fScrResolutionRateW then
            LocFontRate:=fScrResolutionRateH
          Else
            LocFontRate:=fScrResolutionRateW;
        Finally
          ReleaseDC(0, GetDc(0));
        End;

For i:=Self.ComponentCount-1 Downto 0 Do
        Begin
          LocCmp:=Self.Components[i];
          If LocCmp Is TControl Then
            LocList.Add(LocCmp);
          If PropertyExists(LocCmp,‘FONT‘) Then
          Begin
            LocFont:=TFont(GetObjectProperty(LocCmp,‘FONT‘));
            LocFontSize := Round(LocFontRate*LocFont.Size);
            LocFont.Size:=LocFontSize;
          End;
        End;

SetLength(fPosition,LocList.Count+1);
        For i:=0 to LocList.Count-1 Do
          With TControl(LocList.Items[i])Do
            fPosition[i+1]:=BoundsRect;
        fPosition[0]:=Self.BoundsRect;

With LocRect Do
        begin
           Left:=Round(fPosition[0].Left*fScrResolutionRateW);
           Right:=Round(fPosition[0].Right*fScrResolutionRateW);
           Top:=Round(fPosition[0].Top*fScrResolutionRateH);
           Bottom:=Round(fPosition[0].Bottom*fScrResolutionRateH);
           Self.SetBounds(Left,Top,Right-Left,Bottom-Top);
        end;

i:= LocList.Count-1;
        While (i>=0) Do
         Begin
          LocCtl:=TControl(LocList.Items[i]);
          If LocCtl.Align=alClient Then
          begin
            Dec(i);
            Continue;
          end;
          With LocRect Do
          begin
             Left:=Round(fPosition[i+1].Left*fScrResolutionRateW);
             Right:=Round(fPosition[i+1].Right*fScrResolutionRateW);
             Top:=Round(fPosition[i+1].Top*fScrResolutionRateH);
             Bottom:=Round(fPosition[i+1].Bottom*fScrResolutionRateH);
             LocCtl.SetBounds(Left,Top,Right-Left,Bottom-Top);
          end;
          Dec(i);
        End;
      End;

Except on E:Exception Do
      Raise Exception.Create(‘进行屏幕分辨率自适应调整时出现错误‘+E.Message);
    End;
  Finally
    LocList.Free;
  End;
end;

{ TfdForm }

constructor TfdForm.Create(AOwner: TComponent);
begin
  inherited;
  fIsDlgChange:=False;
end;

end.

上面包括两个类,一个是普通窗体类,一个是其子类对话框型窗体类。在实际应用过程中只要自己创建的窗体类继承自以上两个类中的一个,例如 TForm1 = class(TfdForm),则不需添加任何源码,设计出窗体会自动调整其上控件的尺寸,以适应不同的屏幕分辨率。

以上源码经过验证,效果非常好,解决了一个多年未决的问题!

参考:http://m.blog.csdn.net/blog/fghydx/38655291

时间: 2024-08-12 09:12:04

窗体自适应屏幕分辨率的相关文章

Delphi 窗体自适应屏幕分辨率的改进

Delphi:窗体自适应屏幕分辨率的改进 http://blog.sciencenet.cn/blog-39148-544498.html 在窗体依据屏幕分辨率自适应调整尺度方面,昨天的工作可以说是一个突破点.昨天的工作找到了长期以来我的原有方案的问题所在,这是非常关键的.但是昨天晚上的解决方案并不完美,今天的这个才是比较完美的解决版. 先补充说明一下这个问题的重要性.这本来只是一个很小的技术问题,但在现有的Windows软件开发过程中,这个问题非常常见.一些非常著名的商业化软件,也会发现这方面

Delphi:窗体自适应屏幕分辨率(根据预设值的比例改变)

delphi 程序适应屏幕分辨率,先在表单单元的Interface部分定义两个常量, 表示设计时的屏幕的宽度和高度(以像素为单位). 在表单的Create事件中先判断 当前分辨率是否与设计分辨率相同, 如果不同,调用表单的SCALE过程重新能调整表单中控件的宽度和高度. Const   Orignwidth=800;   Orignheight=600; procedure TForm1.FormCreate(Sender:TObject); begin scaled:=true; if (sc

让窗体自适应屏幕

unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,Typinfo, Vcl.StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(

Unity3D NGUI自适应屏幕分辨率(2014/4/17更新)

原地址:http://blog.csdn.net/asd237241291/article/details/8126619 原创文章如需转载请注明:转载自 脱莫柔Unity3D学习之旅 本文链接地址:Unity3D NGUI自适应屏幕分辨率 1.UIRoot:根据高度自适应屏幕分辨率. NGUI根目录的UIRoot组件自带了根据高度自适应分辨率的功能. Scaling Style属性可选择三种不同的缩放策略. PixelPerfect 完美像素:直接显示设定好的像素.当屏幕高度低于minimum

Unity NGUI根据高度自适应屏幕分辨率

Unity版本:4.5.1 NGUI版本:3.6.5 本文内容纯粹转载,转载保留参考链接和作者 参考链接:http://blog.csdn.net/asd237241291/article/details/8126619,作者:CSDN 脱莫柔 NGUI根目录的UIRoot组件自带了根据高度自适应分辨率的功能. Scaling Style属性可选择三种不同的缩放策略: PixelPerfect 完美像素:直接显示设定好的像素.当屏幕高度低于minimum Height时按比例缩小,当屏幕高度大于

rem实现页面自适应屏幕分辨率

<html> <body> <div class="test"></div> </body> </html> 默认情况下1rem=16px;   font-size: 62.5%, 1rem=10px;   以下按照屏幕分辨率设置font-size的百分率, 可以保证div的宽高比在不同分辨率下保持一致,    页面字体大小使用rem同理 /*根据屏幕分辨率自适应大小*/ @media (max-width:192

Unity GUI自适应屏幕分辨率(一)布局自适应

这里我们先谈第一个问题坐标矩阵变化实现布局自适应. 选取基准尺寸 通常你需要选择一个基准的屏幕尺寸,象现在开发的应用也需要跨平台在iOS(iPhone/iPad)/Android都可以运行,我这边选取的是iphone4的屏幕尺寸: 480 * 320. 设计师设计的GUI的素材时就是按照这个尺寸来设计.但是紧接着的问题是如何保证它在其他不同尺寸/分辨率的平台上运行时不会出现各种诡异的位置大小错乱了. 举一个实际的例子来更好描述这个问题,比如我们的游戏是水平方向的, 然后游戏进行中间的暂停界面中,

winform 自适应屏幕分辨率具体操作和注意事项

第一步:先借助一个类文件 AutoSizeFormClass.cs class AutoSizeFormClass { public struct controlRect { public int Left; public int Top; public int Width; public int Height; } //(2).声明 1个对象 //注意这里不能使用控件列表记录 List nCtrl;,因为控件的关联性,记录的始终是当前的大小. // public List oldCtrl= n

Android自适应屏幕分辨率与国际化

一.当横屏切换成竖屏时,解决的办法: 在res目录下建立layout-port和layout-land两个目录,里面分别放置竖屏和横屏两种布局文件,当手机屏幕方向变化的时android系统会自动调用相应的布局文件. 当然还有办法就是不切换.要么都是横屏或者要么都是竖屏.可以在AndroidManifest.xml文件中设置, 比如某个Activity设置为android:screenOrientation="portrait" 这样就一直保持竖屏, 如果设置为 android:scre