利用OnResize事件改变控件位置及大小
C++ Builder/Delphi中的Form控件有一个OnResize事件,Form的所有与大小变化有关的动作可以触发这个事件,包括Form的创建、最大化/最小化/还原、用鼠标拖动改变大小等。因此,在此事件中动态地改变各个控件的位置可以确保其在Form中的相对位置正确。因为CBuilder与Delphi的程序有很多共同之处,所以这里只列出CBuilder的代码。
下面的代码将确保控件在任何情况下都居中。
程序一:
void __fastcall TForm1::FofmResize(TObject*Sender)
{int midLoc=Width/2; //取Form的中点
//设置Label1的位置为Form居中
Label1->Left=midLoc-Label1->Width/2;
//设置Button1的位置为Form居中
Button1->Left=midLoc-Button1->Width/2;}
稍微修改这段代码,可以使控件保持在任何想要的位置。同样,也可以利用OnResize事件改变控件的大小。当Form中控件很多时,分别对每一个控件单独调整位置是件非常麻烦的事,在TFrom类中有一个Controls数组维护所有From中的控件,利用它可方便地对所有控件进行操作。下面是其源代码:
程序二:
void __fastcall TForm1::FormResize(TObject*Sender)
{int midLoc=Width/2;
TControl * ChildControl;
fof(int i=0; i < ControlCount; i++)
{//遍历Controls数组,ControlCount是数组元素个数
ChildControl = Controls[i];
ChildCotrol->Left = midLoc-ChildControl->Width/2;}
}
利用“容器”控制成组控件位置
上面的代码对维持所有控制到统一 梅浅7奖悖焕诙猿勺榭丶胁僮鳌 在C++Builder中提供了一些能安放其它控件的“容器”控件,如TPanel、TGroupBox等,可以将控件放在“容器”控件中:然后对“容器”控件进行操作,从而达到成组控制控件的目的。利用“容器”控件控制控件位置的结果,所有控件都自动居中,但是在GroupBox1控件中的子控件却没有居中,这是因为Controls数组只维护Form的直接子控件,对Form中控件的子控件则无能为力。因此,GroupBox1控件中的子控件仍然在初始位置,必须编写相应代码动态控制其位置及大小。这种技术非常重要,特别是在动态改变“容器”控件大小时。其实,“容器”控件与From一样有Controls数组,只要对其进行与程序2类似的操作即可。代码见程序3
程序三
void __fastcall TForm1::FormResize(TObject*Sender)
{int midLoc=Width/2;
TControl * ChildControl;
for(int i=0;i < 0;ControlConnt; i++)
{//遍历Controls数组,ControlCount是数组元素个数
ChildControl = Controls[i];
ChildControl->Left = midLoc-ChildControl->Width/2;
if (ChildControl ==GroupBox1)
{//若控件是GroupBox,对其子控件进行操作
int SubMidLoc=GroupBox1-$#@62;Width/2;
for(int j=0;j < 0;GroupBox1->ControlCount;j++)
{//遍历GroupBox1的Controls数组。ControlCount是数组元素个数
ChildControl=GroupBox1->Controls[j];
ChildContro1->Left=SubMidLoc-ChildControl->Width/2;}
}
}
}
在不同分辨率下维护窗体位置及大小
商业程序一般要在各种分辨率下运行,正确判断当前分辨率就显得很重要。Windows函数GetDeviceCaps可以返回任意设备描述表中设备大小。 GetDeviceCaps有两个参数,第一个是要查询的设备描述表句柄,第二个是要查询参数的类型,其中HORZRES,VERTRES分别代表屏幕水平和垂直分辨率。程序4是获得当前屏幕分辨率的代码。一般可将这段代码放在“工程文件”(如Project1.cpp)中,并将i、j定义为全局变量,然后可以利用前面介绍的技术控制各种屏幕元素的大小及位置。
程序四:
//获得屏幕设备描述表句柄
HDC hdc=GetDC(NULL);
//查询屏幕水平分辨率,并返回在变量i中
int i=GetDeviceCaps(hdc,HORZRES);
//查询屏幕水平分辨率,并返回在变量j中
int j=GetDeviceCaps(hdc,VERTRES);
//释放屏幕设备描述表
ReleaseDC(NULL,hdc);
//获取当前屏幕分辨率
int PelsWidth = GetSystemMetrics(SM_CXSCREEN);
int PelsHeight = GetSystemMetrics(SM_CYSCREEN);
AnsiString text="当前屏幕分辨率为"+IntToStr(PelsWidth)+"*"+IntToStr(PelsHeight);
ShowMessage(text);
//----------设置当前屏幕分辨率-----------------------------------------------------------------
void __fastcall TForm1::DynamicResolution(int x,int y)
{
TDeviceMode lpDevMode;
bool Result;
// 本段代码 转自 C++Builder 研究 - http://www.ccrun.com/Result = EnumDisplaySettings(NULL,0,&lpDevMode);
if (Result)
{
lpDevMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
lpDevMode.dmPelsWidth = x;
lpDevMode.dmPelsHeight = y;
Result = ChangeDisplaySettings(&lpDevMode,0);
// = DISP_CHANGE_SUCCESSFUL;
}
}
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
DynamicResolution(800,600);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BitBtn2Click(TObject *Sender)
{
DynamicResolution(1024,768);
}
用同样的方法,可以对不同大小纸张的打印进行控制……,有兴趣的朋友可查看GetDevice Caps帮助及打印帮助。
动态缩放窗体及控件时的考虑
如果应用程序的窗体和可视控件可动态缩放,需调整缩放进程各个方面以在所有可能的屏幕分辨率下保证应用程序具有最佳外观。下面是动态缩放应用程序的可视单元应考虑的一些因素:
· 根据开发计算机与要把应用程序安装到其上的计算机的屏幕分辨率,计算窗体和可视控件缩放的比例。使用常数代表开发计算机上屏幕分辨率的大小:可以是以像素计算的高度或宽度。在运行时使用TScreen::Height或TScreen::Width属性获取用户计算机的对应数值。用开发计算机的值除以用户计算机的值导出在两台计算机之间的屏幕分辨率差别比例。
· 通过减少或增加单元的大小和改变其在窗体上的位置缩放应用程序的可视单元(窗体和控件)。缩放按开发和用户计算机的屏幕分辨率之间的差别比例进行。缩放和重定位窗体上的可视控件可通过将窗体的TCustomForm::Scaled属性设为true并调用其TWincontrol::ScaleBy方法自动进行。ScaleBy方法不会改变窗体的高度和宽度。需自行用屏幕的Height和Width属性当前值乘上分辨率差
别比例。
· 可以不使用TWincontrol::ScaleBy方法自动缩放,而通过在循环引用每个可视控件中并设置其尺寸和位置自行缩放窗体上的控件。用可视控件的Height和Width属性值乘上屏幕分辨率差别比例。用可视控件的Top和Left属性值乘上屏幕分辨率差别比例重定位可视控件。
· 如果设计应用程序的计算机设置了比用户计算机低的屏幕分辨率,字体大小将在按比例缩放可视控件的进程中被减小。如果在设计时字体大小已经太小,在运行时字体可能会被缩小到不可读。
例如,窗体的缺省字体大小是8。如果开发计算机的屏幕分辨率为640×480而用户的计算机为1024×768,可视控件尺寸将按0.625的比例减小(640/1024=0.625)。原来的字体大小8被减小为5(8×0.625=5)。当Windows以减小的字体大小显示应用程序的文本时会挤在一起并且不可读。
· 有一些可视控件,如TLabel和TEdit,当控件的字体大小变化时会动态地缩放。当窗体和控件动态缩放时,这会影响发布应用程序。控件除根据屏幕分辨率差别比例缩放外,还会因字体大小变化而缩放。这种效果可以通过将这些控件的AutoSize属性设为false来禁用。
· 避免使用显式的像素坐标,例如当直接在画布中绘制时。应按开发和用户计算机之间的屏幕分辨率差别比例相应修改坐标。例如,如果应用程序在画布中绘制一个高10个、宽20像素矩形,应分别把10和20乘上屏幕分辨率差别比例。这可确保矩形在不同的屏幕分辨率下看起来显得大小一样。