delphi的精美界面
Delphi界面设计专辑
,前言:,界面的美观和用户亲和性是应用软件成功的首要条件,因此界面往往是程序员最费心的地方。在这个专辑中,将向读者全面介绍Delphi中界面设计的原则和技巧
窗体设计
制作固定大小的Form
固定的Form像一个对话框,何不试试下面的语句
巧用Delphi制作溅射屏幕
精心编写的WINDOWS程序显示启动注意事项,称之为溅射屏幕(splash screen)。利用一点儿小小的内容,即可给程序的显示添加不少色彩
LED数码管仿真显示程序
在电子设备上广泛地使用LED数码管显示数据,在许多应用软件中也经常模拟LED数码管显示数据,使程序画面看起来很有特色
菜单设计
DELPHI中自适应表单的实现
我们知道,屏幕分辨率的设置影响着表单布局,假设你的机器上屏幕分辨率是800*600,而最终要分发应用的机器分辨率为640*480,或1024*768,这样你原先设计的表单在新机器上势必会走样
作非常规程序菜单掌握delphi高级秘籍
大家可能见过诸如金山毒霸,瑞星杀毒,以及五笔输入法等等在系统托盘(即右下角有时间和输入法图标的地方)在的控制菜单,而在正常的任务栏(即屏幕最下方的“开始”按钮的右边的各式各样)中却不出现按钮的程序,即我们常说的在后台运行的程序
用Delphi制作动态菜单
所谓动态菜单是指菜单项随着程序的操作变化而变化。现在,我们用Delphi来实现这一功能,具体步骤如下
工具栏和状态条
为Windows窗口标
栏添加新按钮
对于我们熟悉的
windows窗口来讲,标题栏上一般包含有3个按钮,即最大化按钮,最小化按钮和关闭按钮。你想不想在Windows的窗口标题栏上添加一个新的自定义按钮
用Delphi4实现风Word97格的工具栏
用过Word97的人对它的工具栏印象很深刻,因为它的风格很“酷”,同样IE4.0的工具栏也有类似的风格,Win98的出现,使这种风格的工具栏得到了推广
如何隐藏和显示Windows的任务条
如果隐藏和显示Windows的任务条?仅仅调用以下的函数就可以.
其他技巧
Delphi利用Windows GDI实现文字倾斜
在Delphi开发环境中,文字的输出效果一般都是头上脚下的"正统"字符,如何输出带有一定倾斜角度的文字以达到特殊的显示效果呢
Delphi之三十六计之界面篇
设置状态栏面板对象的Style为OwnerDraw,并在状态栏对象的DrawPanel事件中书写以下代码
利用COM技术实现外壳扩展的属性页
当用户在资源管理器中调用右键菜单时,会显示一个"属性"菜单项,点击属性菜单项会显
示一个属性页,用户可以获得甚至修改文件信息
制作固定大小的Form
固定的Form像一个对话框,何不试试下面的语句,
C++ Builder
请参照Delphi的例子
Delphi
您可以覆写 CreateParams() 这个 TWinControl 的虚拟程序, 改变 form的 wc.Stylee, 将 WS_SYSMENU 这个旗标解除, 这样, 就不会有左上角的
SystemMenuBox 了.
至於不能移动.缩小/放大, 可以自已拦下 WM_NCHITTEST, 然後一概回应滑鼠点在视窗 Client 区域, 相信这个视窗就呆呆的不会动了.
详情可以查一下 Win32API Help 的 CreateWindow() 与 WM_NCHITTEST 的说明. unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject); private
{ Private declarations }
procedure WMNCHitTest(var Msg: TMessage); message WM_NCHITTEST;
protected
procedure CreateParams(var Params: TCreateParams); override;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
巧用Delphi制作溅射屏幕
精心编写的WINDOWS程序显示启动注意事项,称之为溅射屏幕(splash screen)。利用一点儿小小的内容,即可给程序的显示添加不少色彩。
由于
本身创建程序的主窗口,且启动溅射屏幕必须在创建主窗口之前出现,所以工程文件必须创建自己的启动屏幕。这意味着用户必须修改源代码来创建工程文件,而这通常在DELPHI编程中是不需要的。下面的过程介绍了溅射屏幕的建立过程。
1、开始一个新的工程。将窗体命名为MainForm,同时将其Caption属性设置为SplashinDemo。把这个工程保存在一个目录中,如C:ProjectsSplashin。把MainForm的单元命名为Main,把工程文件命名为Splashin。
2、在MainForm中插入一个Button组件。将Button的Name属性改为ExitButton,而将其Caption属性改为Exit。为ExitButton的OnClick事件创建一个处理器,在过程的begin和end关键词之间插入Close;语句。
3、选取File|New Form命令,或者单击New Form速度按钮。添加一个新的窗体。
4、将这个窗体的Name属性改变为SplashForm,删除其Caption属性。此外,将其BorderStyle属性改变为bsnone,同时将BorderIcons下的三个子值设置为False。
5、保存这个工程。当Delphi提示读者提供单元文件名时,要确信当前目录为正确的目录。为SplashForm的单元文件名输入Splash。
6、将SplashForm的Enabled属性设置为False。这里不想让用户能够给窗口提供键盘和鼠标命令,这是极少见的情况之一。在这个例子中,我们想让程序对SplashForm的显示拥有完全的控制权。
7、由于窗口没有轮廓,所以从Additional组件类中插入一个Bevel组件对象。这有助于定义窗口的边缘。将Bevel1的Align属性设置为alClient。同时,将对象的Shape属性改变为bsFrame,将其Style属性改变为bsRaised。这些值由使用者来确定。
8、在SplashForm中插入想使用的组件,在这里不要插入任何按钮或者其他相互作用的控件。应用程序本身显示和去除启动溅射对话框。
9、选择Project菜单。高亮显示Splash工程个弹出式菜单。选择Options命令。在所产生的Project Options对话框中,选取Forms页标签。注意,MainForm和SplashForm位于自动创建的窗体列表中。高亮显示每个窗体并单击鼠标右按钮来将其移动到Available窗体。所有的Delphi窗体在运行时都是在内存中自动创建的,这要消耗内存和系统资源。在这样的一个案例中,程序是在运行时创建窗体的,读者应该从自动创建的列表中删除窗体。关闭ProjectOptions窗口。
10、接下来,修改工程的源代码,以便在显示主窗口之前显示溅射对话框。这里需要在工程文件中插入语句,以便与Splash.dpr工程文件相匹配。工程源代码如下:
program Project3;
uses
Forms,
main in „main.pas„ {MainForm},
splash in „splash.pas„ {SplashForm};
{$R *.RES}
begin
SplashForm:=TSplashForm.Create(Application);
SplashForm.Show;
SplashForm.Update;
Application.CreateForm(TMainForm,MainForm);
SplashForm.Close;
Application.Run;
end.
11、如果这时编译和运行程序,它就非常快速地显示和去除启动溅射对话框,以至用户可能没机会见到它。为了强迫对话框保持几秒钟的可见时间,请选取程序的MainForm。为窗体的OnCreate命令创建一个处理器。在关键词的前面添加一个名为stopTime的长整型变量。在begin和end之间插入两个语句:一个为对Windows GetTickCount函数的调用。来将stopTime设置为Windows已在运行的秒数;另一个语句为while语句,这个语句另外延迟2秒钟。程序清单如下:
unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TMainForm = class(TForm)
Exitbutton: TButton;
procedure ExitbuttonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
procedure TMainForm.ExitbuttonClick(Sender: TObject);
begin
close;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
stopTime:LongInt;
begin
stopTime:=GetTickCount div 1000;
while ((GetTickCount div 1000),(stopTime+2)) do
Sleep(1);
end;
end.
12、按F9编译、运行程序。
LED数码管仿真显示程序
在电子设备上广泛地使用LED数码管显示数据,在许多应用软件中也经常模拟LED数码管显示数据,使程序画面看起来很有特色。使用Delphi 程序实现LED数码管的仿真显示非常容易,具体步骤如下:
1(启动Delphi 4.0。在“Tools”工具菜单上选择Delphi的图象编辑器“Image Editor”,建立一个新的位图,并设定位图的尺寸,宽为:48,高为:64。设定位图的底色为紫红色,前景色为红色。在位图上选择适当宽度的线条画出一个正方的8字,并将方型8字的各个拐角处用斜线断开,这样可使图象模拟的更加真实。完成后按文件名bitmap_0.bmp存储。然后用此文件复
制9个文件,文件名分别为bitmap_1-9。用图象编辑器将这些方形的8字位图按文件名序号的顺序分别修改成0,9的数字位图,存储后备用。
2(建立一个新的工程,在窗体Form1上添加“面板”元件Panel1,设定“面板”元件的属性:bevelouter=bmRaised; bvevelInner=bvLowered; BorderWidth=4,设置后在Panel1元件上形成一个凸起的边框。在Panel1上添加一个“画板”元件PaintBox1,将PaintBox1的属性Hight 和Width设定为64和318,并适当调整Panel1面板的尺寸,使其正好包围画板元件。
3(在窗体中添加一个“图象列表”元件ImageList1,在元件上双击鼠标,调出添加图象对话框,将先前制作好的位图bitmap_0至bitmap_9按顺序添加进图象列表元件中去,使图象列表中位图的序号与位图本身代表的数字相同,并注意将位图设定为不透明。
4(转到单元编辑窗口,在Tform1的类说明部分添加一个显示LED的过程说明语句:
procedure display_LED(number:integer); 。
在implementation语句下面添加一个全局变量和对应上面过程说明的过程体。内容如下: implementation
{$R *.DFM}
var
dis_number:integer;
procedure Tform1.display_LED(number:integer); var
I:integer;
digital:array[0..5]of integer; begin
{限制显示位数小于6位}
if number>999999 then number:=0;
for I:=0 to 5 do digital[I]:=0;
{分离数字位}
I:=0;
while (number)>0 do
begin
digital[I]:=number mod 10;
number:=number div 10;
I:=I+1;
end;
{显示数字}
for I:=5 downto 0 do
imagelist1.draw(paintbox1.canvas, (5-I)*54,0,digital[I]);
end;
5(在Form1窗体的OnCreated 事件中输入语句:dis_number:=0; ,使显示的初始值为0。在画板元件的On Paint 事件中输入语句:display_LED(dis_number); ,此语句非常重要,它可以在初始启动时显示初值0,在窗口本身被覆盖后又恢复到前台时仍可显示正常的数值。至此已完成了显示函数的程序编制。在需要显示数字的程序中调用display_LED 函数就能将数字显示在LED 的仿真显示板上?揪倮绦蛑幌允?位以下的数字。
6(为了测试显示效果,我们在窗体上增加一个编辑框元件Edit1,和一个按钮元件button1。用鼠标双击按钮元件跳转到Click事件编辑窗口,输入如下语句:
dis_number:=strTOint(Edit1.text);
display_LED(dis_number);
完成后按F9键编译并运行程序。在运行窗口的编辑框中输入6位以下的整数数字,点击按钮,编辑框中的数字就显示在LED仿真显示板上。
DELPHI中自适应表单的实现
我们知道,屏幕分辨率的设置影响着表单布局,假设你的机器上屏幕分辨率是800*600,而最终要分发应用的机器分辨率为640*480,或1024*768,这样你原先设计的表单在新机器上势必会走样。这时你一定希望表单能自己适应不同的分辨率,下面就有两种
可供你参考。
一、根据新的分辨率自动重画表单及控件
先在表单单元的Interface部分定义两个常量,表示设计时的屏幕的宽度和高度(以像素为单位)。在表单的Create事件中先判断当前分辨率是否与设计分辨率相同,如果不同,调用表单的SCALE过程重新能调整表单中控件的宽度和高度。
Const
Orignwidth=800;
Orignheight=600;
procedureTForm1.FormCreate(Sender:TObject); begin
scaled:=true;
if(screen.width<>orignwidth)then begin
height:=longint(height)*longint (screen.height)divorignheight;
width:=longint(width)*longint
(screen.width)divorignwidth;
scaleby(screen.width,orignwidth); end;
end;
SCALE过程在调整控件宽度和高度的同时,也自动调整控件字体的大小,以适应新的分辨率, 但美中不足的是它并不改变控件的顶点坐标位置,也就是说,该过程不改变控件之间的相对位置关系。要想调整控件之间的选队相对位置,还需要自己编程实现,有兴趣的读者可试一试。
二、将机器分辨率更改为设计时的分辨率
这种方法不改变表单本身,而是将屏幕分辨率更改为与表单设计时用到的分辨率相同。它需要用到WINDOWSAPI函数EnumDisplaySettings和ChangeDisplaySettings,前者取当前显示模式信息,后者则更改显示设置,具体参数的含义请参见DELPHI帮助。设计时宽度常量和高度常量的定义如方法一。
procedureTForm1.FormCreate(Sender:TObject); var
devmode:tDevicemode;
begin
ifscreen.width<>orignwidththen
begin
ifEnumDisplaySettings(nil,0,devmode)then begin
devmode.dmfields:=dm_pelswidthORdm_pelsheight; devmode.dmpelswidth:=orignwidth;{宽度}
devmode.dmpelsheight:=orignheight;{高度}
ChangeDisplaySettings(devmode,0);{更改设置}
end;
end;
end;
以上两种方法在WINDOWS95+DELPHI3.0环境下均已通过,二者相比,前者是主动适应,后者则是被动适应。
作非常规程序菜单掌握delphi高级秘籍
大家可能见过诸如金山毒霸,瑞星杀毒,以及五笔输入法等等在系统托盘(即右下角有时间和输入法图标的地方)在的控制菜单,而在正常的任务栏(即屏幕最下方的“开始”按钮的右边的各式各样)中却不出现按钮的程序,即我们常说的在后台运行的程序。如果自己的程序中也能有这样的话,那种与众不同的感觉真棒.
预备知识:
1:向系统托盘中加入图标控制菜单:
向系统托盘中加入图标控制菜单须用到函数Shell_NotifyIconA,而这个函数又有两个参数:'TnotifyIconDataA'结构的参数和一个消息参数
即:Shell_NotifyIconA(dwMessage:DWORD;lpData:PNotifyIconDataA),第一个参数dwMessage可以是以下值:NIM_ADD:增加一个图标 ;NIM_MODIFY:修改一个已有的图标 ;NIM_DELETE:删除一个已有的图标 ;
第二个参数的TnotifyIconDataA结构如下:
TnotifyIconDataA=record
cbSize:DWORD; {表示该结构的长度}
Wnd:HWND; {是调用Shell_NotifyIconA函数的窗口的句柄即Handle} iID:UINT; {是在下面的uCallbackMessage参数指定的消息中使用的一个自定义数值} uFlags:UINT; {决定该结构中的有效部分,如有NIF_MESSAGE则 uCallbackMessage参数有效 ;若有NIF_ICON 则hIcon有效;有 NIF_TIP则 szTip参数有效,当然你可以让这三个参数都有效只须要在这个参数中写成NIF_MESSAGE+NIF_ICON+NIF_TIP即可} uCallbackMessage:UNIT; {当添加的图标上有鼠标事件如右击等等时系统向Wnd参数所指定的窗口发送消息,这个消息的Msg参数是uCallbackMessage,这个消息的wParam参数是 uID,这个消息的lParam参数是鼠标事件的 Msg值}
Icon:HICON; {是出现在系统托盘中的图标的句柄即handle}
szTip:array[0..63] of AnsiChar; {即delphi是常用的hint即当鼠标停留在托盘图标上时的提示,例如你可用„这是我的第一个托盘图标菜单?,
end;
,:在状态栏上隐藏程序;
在一般情况下我们在打开一个窗口或是一个程序时都会在任务条上出现按钮如在IE中每打开一个新的窗口在任务条上就有一个新的按钮,在这里我们的程序是用在系统托盘中图标控制菜单,程序在后台运行,即希望我们的程序不在任务条上出现按钮;这个可用函数SetWindowLong来实现,在我们这个程序中的代码如下:
procedure TForm1.FormCreate(Sender: TObject); begin
form1.Width:=1;
form1.Height:=1; {让窗口在运行时表现为一个像素长宽的点,
form1.Left:=screen.Width-1; ,让窗口在运行时在屏幕的右上角而不影响我们的桌面的操作,
form1.top:=1;
form1.Brush.Style:=bsclear; ,让窗口在运行时在表现为透明,
setwindowlong(application.handle,gwl_exstyle,ws_ex_toolwindow); ,让窗口在运行时不在任务栏上出现按钮,
end;
,:在程序中控制光驱的打开和关闭;
当我们不再用手动的打开关闭光驱门时,我们的光驱寿命也就会相应延长,我们在程序中可用函数
function mciSendString(lpstrCommand,lpstrReturnString:
PChar;uReturnLength :UINT;hWndCallback:HWND):MCIERROR;stdcall;
其中lpstrComman参数表示一个MCI命令行,如:?set cdaudio door open wait„,„set cdaudio
door closed wait?等等你可以delphi中的mmSystem.pas中查看详细说明;而参数'lpstrReturnString'表示接收返回信息的缓冲区指针,如果不需要返回值这里可写为'nil',参数'uReturnLength'表示接收返回信息的缓冲区的长度,若上面为'nil'这里为'0','hWndCallback'参数表示回调窗口的句柄,在这里可写为'handle';
在我们的程序中原代码如下:
打开光驱门:
procedure TForm1.N1Click(Sender: TObject); begin
mcisendstring('set cdaudio door open wait',nil,0,handle);
end;
关闭关驱门:
procedure TForm1.N2Click(Sender: TObject); begin
mcisendstring('set cdaudio door closed wait',nil,0,handle);
end;
,:在程序中控制重启电脑和关闭计算机;退出WINDOWS可用的函数有ExitWindows()和ExitWindowsEx()在本程序中的代码如下:
重启:
procedure TForm1.N8Click(Sender: TObject); begin
showmessage('请先关闭并保存正在运行的程序');
exitwindowsex(ewx_force or ewx_reboot,0); end;
关闭计算机:
procedure TForm1.N9Click(Sender: TObject); begin
showmessage('请先关闭并保存正在运行的程序');
exitwindowsex(ewx_shutdown or ewx_poweroff,0);
end;
,:实现光驱的自动播放和更改光驱图标都需要更改注册表;要实现注册表的读写我们用以下代码:
例如有
var reg:tregistry;
reg:=tregistry.Create;
reg.RootKey:=hkey_local_machine; {这里是注册表的主键,
reg.OpenKey('software\microsoft\windows\currentversion\explorer\shell icons',true); ,这里是注册表的子键,
reg.WriteString('11',mn); ,这里对注册表进行写操作,
,关于注册表的相关知识大家可参考„电脑爱好者?出版的,,注册表完全精通,,一书,
还有一点应特别注意的是在更改光驱图标时不仅要在注册表中更改,还要把'c:\windows\shelliconcache'文件删除,这相关的关于文件操作的知识以及后面一些有关程序中加入声音等等大家一定都会,这里也就不再多说.
用Delphi制作动态菜单
所谓动态菜单是指菜单项随着程序的操作变化而变化。现在,我们用Delphi来实现这一功能,具体步骤如下:
1(首先,确定动态菜单的数据来源,即要确定动态菜单标题是来自Windows的系统注册表,还是来自一个数据库,或者是来自一个子目录,主要由程序的功能而定。这里假设主窗口名为MainForm,上面已有主菜单,其动态菜单的数据源是一个String(字符串)类型的变量,名称为SubMenuItemSource。
2(确定生成的动态菜单的功能,即定义动态菜单的OnClick()事件,例如,动态菜单标题来自一个磁盘文件名时,那么程序在响应OnClick()事件时,可能的操作是要打开选中的文件。因此,对菜单所在的主窗口模块的单元程序的数,据我们需要定义Type后添加一个自定义的事件MyClick()。
然后,需要编写如下MyClick()事件的具体内容:
procedure TMainForm.MyClick(Sender: TObject);//动态菜单OnClick事件响应
begin
Show.Message(TMenuItem(Sender).Caption);//显示选中的动态菜单标题,
end;
这里调用的ShowMessage标准例程(在Dialogs.pas中)显示TMenuItem(Sender).Caption,
它就是选择的菜单项的Caption,类似用TMenuItem(Sender).Name则是选择菜单项的Name。
3.编写程序将动态菜单标题添加到指定的菜单顶下,并将其与OnClick()事件联系起来。将以下程序段添加到MainForm的OnCreate事件过程中,可在程序启动时完成动态菜单的动
态生成:
procedure TMainForm.FormCreate(Sender: TObject);
var
addSubItem:TMenuItem;
i:Integer;
begin
for i:=0 to N do //N等于要添加的动态菜单数目,需事先定义为数值型变量,并赋值
begin
addSubItem:= TMenuItem.Create(Self);
addSubItem.Name := ′A′+IntToStr(i);
addSubItem.Caption := SubMenuItemSource; // 步骤1的SubMenuItemSource应先赋值
FileOpenItem.Add(addSubItem); //在名称为FileOpenItem的菜单项下添加子菜单
addSubItem.OnClick:=MyClick; // 步骤2的MyClick(),自定义菜单要响应的事件
end
end;
为Windows窗口标题栏添加新按钮
对于我们熟悉的标准windows窗口来讲,标题栏上一般包含有3个按钮,即最大化按钮,最小化按钮和关闭按钮。你想不想在Windows的窗口标题栏上添加一个新的自定义按钮,满足你的个性化需求,从而也使自己的窗口更具特色呢,~
下面我们就讨论一下在delphi中如何给窗口的标题栏上添加新的按钮。
一、实现起来要定义以下过程:
1、定义DrawCaptButton过程,这个过程的功能是在指定的位置画出按钮。
在过程中要使用win32函数GetSystemMetrics得到窗口的大小和标题按钮的大小;使用delphi函数Bounds定义一个矩形,这个矩形就是新按钮的位置;再定义一个小的矩形,这个矩形是为了填写文本;最后就调用delphi中比较有用的函数drawbuttonface把按钮画出来。
2、每次我们对窗口进行操作,例如,最大化操作或最小化操作,新按钮就会消失,为了解决这个问题,我们对所有的消息要进行处理,给每个消息编写一个过程对按钮进行重画。
A、定义WMNCPaint(var Msg:TWMNCPaint)过程,处理消息WM_NCPaint。
B、定义WMNCActivate(var Msg :TWMNCActivate)过程,处理消息WM_NCACTIVATE。
C、定义WMSetText(var Msg:TWMSetText)过程,处理消息WM_SETTEXT。
D、定义WMNCHitTest(var Msg :TWMNCHitTest)过程,处理消息WM_NCHITTEST。
E、定义WMNCLButtonDown(var Msg : TWMNCLButtonDown)过程,处理消息WM_NCLBUTTONDOWN。
二、具体的源程序如下:
我们结合源程序来讲述过程的实现,从中可以看出程序对win32函数的调用,以及drawbuttonface函数的使用方法。
unit Main;
interface
uses
Windows, Buttons, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
procedure FormResize(Sender: TObject);
private
CaptionBtn : TRect;
procedure DrawCaptButton;
procedure WMNCPaint(var Msg : TWMNCPaint); message WM_NCPaint;
procedure WMNCActivate(var Msg : TWMNCActivate); message WM_NCACTIVATE;
procedure WMSetText(var Msg : TWMSetText); message WM_SETTEXT;
procedure WMNCHitTest(var Msg : TWMNCHitTest); message WM_NCHITTEST;
procedure WMNCLButtonDown(var Msg : TWMNCLButtonDown); message
WM_NCLBUTTONDOWN;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
const
htCaptionBtn = htSizeLast + 1;
{$R *.DFM}
procedure TForm1.DrawCaptButton;
file://drawcapbuttton过程的具体实现
var
xFrame,
yFrame,
xSize,
ySize : Integer;
R : TRect;
begin
xFrame := GetSystemMetrics(SM_CXFRAME);
yFrame := GetSystemMetrics(SM_CYFRAME);
file://把窗口的宽度置于变量xFrame,把窗口的高度置于变量yFrame
xSize:= GetSystemMetrics(SM_CXSIZE);
ySize:= GetSystemMetrics(SM_CYSIZE);
// 把标题栏按钮的宽度置于变量xSize,把标题栏按钮的高度置于变量ySize
CaptionBtn := Bounds(Width - xFrame - 4*xSize + 2,
yFrame + 2, xSize - 2, ySize - 4);
file://定义出新的标题按钮的位置,值放在变量CaptionBtn中
Canvas.Handle := GetWindowDC(Self.Handle);
file://得到窗口的句柄
Canvas.Font.Name := 'Symbol';
Canvas.Font.Color := clBlue;
Canvas.Font.Style := [fsBold];
Canvas.Pen.Color := clYellow;
Canvas.Brush.Color := clBtnFace;
file://定义画布的字体、画笔、刷子等属性
try
DrawButtonFace(Canvas, CaptionBtn, 1, bsAutoDetect, False, False, False);
file://在画布上画出定义的按钮
R := Bounds(Width - xFrame - 4 * xSize + 2,
yFrame + 3, xSize - 6, ySize - 7);
file://在新按钮上画出一个小矩形
with CaptionBtn do
Canvas.TextRect(R, R.Left + 2, R.Top - 1, 'W');
file://在上面画出的小矩形上填写一个字符'w'字符
finally
ReleaseDC(Self.Handle, Canvas.Handle);
Canvas.Handle := 0;
file://容错处理,如果出现异常,把句柄释放掉
end;
end;
procedure TForm1.WMNCPaint(var Msg : TWMNCPaint);
//WMNCPaint过程的具体实现,该过程在绘制窗口时被调用
begin
inherited;//继承默认的消息处理程序
DrawCaptButton;//对按钮进行重画
end;
procedure TForm1. (var Msg : TWMNCActivate);
// WMNCActivate过程与WMNCPaint过程实现方法相同,该过程在窗口的非客户区要更改为激活状态或非激活状态时被调用
begin
inherited;
DrawCaptButton;
end;
procedure TForm1.WMSetText(var Msg : TWMSetText);
// WMSetText过程与WMNCPaint过程实现方法相同,该过程在设置窗口的文本时被调用
begin
inherited;
DrawCaptButton;
end;
procedure TForm1.WMNCHitTest(var Msg : TWMNCHitTest);
file:// WMNCHitTest过程与WMNCPaint过程实现方法相同,该过程在光标移动或鼠标按钮被按下或鼠标按钮被释放时调用
begin
inherited;
with Msg do
if PtInRect(CaptionBtn, Point(XPos - Left, YPos - Top)) then
Result := htCaptionBtn;//判断鼠标所在位置是否在新按钮的矩形范围内,如果在返回新按钮的标识值
end;
procedure TForm1.WMNCLButtonDown(var Msg : TWMNCLButtonDown);
// WMNCLButtonDown过程与WMNCPaint过程实现方法相同,当光标处于窗口非客户区范围内鼠标左键被按下时调用该过程
begin
inherited;
if (Msg.HitTest = htCaptionBtn) then
ShowMessage('你点击的是标题栏上的新按钮');
file://判断被点击的是否是新按钮,如果是显示上面的信息,在这里你可以按你的需要编写程序代码
end;
procedure TForm1.FormResize(Sender: TObject);
begin
Perform(WM_NCACTIVATE, Word(Active), 0);
file://如果窗口大小改变则重画标题栏
end;
end.
三、程序执行结果
如图1-1所示标题栏上出现一个新按钮
图1-1
通过以上的示例过程,相信你能根据自己的具体要求,利用Delphi设计出别具特色的Windows窗口来~
用Delphi4实现风Word97格的工具栏
用过Word97的人对它的工具栏印象很深刻,因为它的风格很“酷”,同样IE4.0的工具栏也有类似的风格,Win98的出现,使这种风格的工具栏得到了推广。其实,用Delphi4很容易实现具有Word97风格的工具栏。
在Delphi4的元件选项板Additional页中,新增了Controlbar元件,此元件和Win32页中的Toolbar、Coolbar配合使用,再辅以Imagelist、Mainmenu等元件,完全可以实现具有Word97风格的工具栏。下面以一个FORM中的工具栏为例,详细介绍设计步骤:
1?从Additional页中选择Controlbar,将其放入FORM1中,设置其属性如下:Allign:=altopAutosize:=trueBevelkind:=bknone
2?从Win32页中选择Toolbar,将其放于Controlbar上,调整Toolbar的位置,使其置于最左,再调整其宽度,设置属性Edgeborders:=[],Flat:=TRUE。用鼠标右击Toolbar,在浮动菜单上选择Newbutton,重复若干次,设计好所需的按钮。
3?从Win32页中选择Imagelist元件,为FORM1设计主菜单,主菜单的设计方法同Delphi2、Delphi3。设计好主菜单后,将其属性Automerge置为TRUE。
4?最后为每一个按钮分配Tmenuitem的Name值,将每个按钮的Menuitem属性值设为所需菜单的Name值。
按F9运行程序,便可发现,设计出的工具栏已经具有Word97的风格,用鼠标在各个按钮上移动,按钮自动上浮,单击鼠标,弹出相应的菜单。需要说明的是,Mainmenu的属性Automerge置为TRUE,是为了不让主菜单出现在FORM1的最上端。工具栏的设计必须将Controlbar与Toolbar结合使用,不然得不到与Word97外观一样的工具栏。
如何隐藏和显示Windows的任务条
如果隐藏和显示Windows的任务条?仅仅调用以下的函数就可以.
procedure hideTaskbar; //隐藏
var
wndHandle : THandle;
wndClass : array[0..50] of Char; begin
StrPCopy(@wndClass[0], Shell_TrayWnd); wndHandle := FindWindow(@wndClass[0], nil); ShowWindow(wndHandle, SW_HIDE); End;
procedure showTaskbar;
var
wndHandle : THandle;
wndClass : array[0..50] of Char; begin
StrPCopy(@wndClass[0], Shell_TrayWnd); wndHandle := FindWindow(@wndClass[0], nil); ShowWindow(wndHandle, SW_RESTORE); end;
Delphi利用Windows GDI实现文字倾斜
一、引言
在Delphi开发环境中,文字的输出效果一般都是头上脚下的"正统"字符,如何输出带有一定倾斜角度的文字以达到特殊的显示效果呢,笔者在制作公章辅助设计软件过程中,通过Windows图形设备接口函数实现了文字呈辐射状分布的功能。
Windows图形设备接口(Graphics Device Interface)是Windows系统中的图形核心模块,以GDI.EXE形式提供给开发者使用。Windows中的图形基本上是由GDI.EXE中的函数来处理的,它的主要特点是在输出设备上支持与设备无关的图形。在GDI函数中,文本亦被视为一种图形对象,但并非简单的几何方式绘制,因为文本的输出涉及到字体。
根据Windows中字体所用的技术可以分为3类字体:光栅字体,矢量字体和TrueType字体。其中,True Type字体的主要优点之一是可被任意放大或旋转,在任何尺寸上,都可以达到较为满意的显示效果,尤其,其允许在显示器和打印机上使用相同的字体。Windows为应用程序之所以能够提供设备无关性是通过采用让应用程序创建逻辑对象从而使用物理对象的方法实现的,同样,对于字体的使用也是一样的:应用程序在使用字体时,首先创建逻辑字体,以便Windows从设备中选择一种与之匹配的物理字体,从而达到较为准确的输出效果。
使用Windows GDI函数实现文字的倾斜效果的基本步骤如下:
1.取得设备描述表或图形设备的句柄:
HDC GetDc(Thandle AWinHandle);
2.创建逻辑字体并设置文字的倾斜度:
HFont CreateFontIndirect(LogFont Far *Iplf),
其中,Iplf为tagLogFont结构体,通过设置其lfEscapement可设置文字的倾斜度(为实际度数的10倍),例如:0度-正常字体,450度-左上45度倾斜,900度-正向左,等。
3.将逻辑字体选入设备列表,从而,Windows选择与之匹配的物理字体,并且新的字体取代
旧的字体:
HGDIOBJ SelectObject(HDC hdc,HGDIOBJ hgdiobj);
注:在此之前现
4.使用当前设备的字体进行文字输出:
BOOL TextOut(HDC hdc, int PosX, int PosY, LPCTSTR OutStr, int StrLength);
5.释放不再使用的图形对象(这里为逻辑字体):
BOOL DeleteObject(HGDIOBJ hObject);
6.释放设备描述表或图形设备的句柄,函数声明如下:
ReleaseDc(THandle AWinHandle,HDC Dc);
注:上述过程要求在窗口的Paint事件中编写重新绘画或绘制文字的代码。
二、程序实现
在Delphi5.0中新建一个工程,在主窗体的Paint事件中编写如下代码:
procedure TForm1.FormPaint(Sender: TObject);
var
FLogFont : tagLogFontA; file://逻辑字体--结构体类型
hTempFont, hPrevFont: HFONT; file://字体句柄
hTempDC: HDC; file://设备描述表或图形设备句柄
TempString: string; file://输出的文字
begin
FLogFont.lfHeight := 10; file://字高
FLogFont.lfWidth := 10; file://字宽
FLogFont.lfWeight := 1; file://字体笔划粗细程度
FLogFont.lfUnderline := 0; file://没有下划线
FLogFont.lfStrikeOut := 0; file://没有删除线
FLogFont.lfItalic := 0; file://斜体效果否
FLogFont.lfCharSet := GB2312_CHARSET; file://字符集
FLogfont.lfEscapement := 450; file://倾斜度
FLogFont.lfOrientation := 450; file://方向与倾斜度取值同
FLogFont.lfFaceName := '宋体'; file://字体名称
file://创建逻辑字体
hTempFont := CreateFontIndirect(FLogFont);
TempString := '测试';
file://取得窗口的设备句柄
hTempDC := GetDC(Handle);
file://取出窗口设备的当前字体,并替换为新字体
hPrevFont := SelectObject(hTempDC, hTempFont);
file://设置设备窗口的文字色彩
SetTextColor(hTempDc, clRed);
file://输出文字
TextOut(hTempDc, 200 , 200, PChar(TempString), Length(TempString));
file://恢复原有的字体
SelectObject(hTempDc, hPrevFont);
file://删除逻辑字体
DeleteObject(hTempFont);
file://释放设备接口
ReleaseDC(Handle, hTempDC);
end;
以上代码若不写在窗体的Paint事件,则当窗体接收到重绘消息时,默认的窗口绘制过程将重新绘制窗口而使倾斜文字消失。
三、结束语
以上,只是Windows GDI接口函数使用的一个具体例子,希望能对广大读者起到抛砖引玉的作用,利用Windows GDI接口函数编写出更为丰富多彩的的文字效果。 Delphi之三十六计之界面篇
1(为MDI窗体客户区填充位图
//在主窗体中添加Image1控件
//申明
private
FClientInstance : TFarProc;
FPrevClientPro 0 to ClientWidth div Image1.Picture.Width do
BitBlt(Dc,
Col * Image1.Picture.Width,
Row * Image1.Picture.Height,
Image1.Picture.Width,
Image1.Picture.Height,
Image1.Picture.Bitmap.Canvas.Handle,
0,
0,
SRCCOPY);
Result := 1;
end;
else
Result := CallWindowProc(FPrevClientProc,
ClientHandle,
Msg,
wParam,
lParam);
end;
end;
//FormOnCreate
procedure TMainFrm.FormCreate(Sender: Tobject);
begin
FClientInstance := MakeObjectInstance(ClientWndProc);
FPrevClientProc := Pointer(GetWindowLong(ClientHandle,GWL_WNDPROC));
SetWindowLong(ClientHandle,GWL_WNDPROC, LongInt(FClientInstance));
end;
2(给窗体添加皮肤
//在窗体中放一名为Image1的TImage控件,并设置位图
//在窗体的private节中声明过程
procedure WMEraseBkgnd(var m: TWMEraseBkgnd); message WM_ERASEBKGND;
…………..
在实现部分书写代码如下:
procedure Tform1.WMEraseBkgnd(var m : TWMEraseBkgnd);
begin
m.Result := LRESULT(False);
end; procedure TForm1.FormPaint(Sender: TObject);
var
x, y: Integer;
iBMWid, iBMHeight : Integer;
begin
iBMWid := Image1.Width;
iBMHeight := Image1.Height;
y := 0;
while y $#@60; Height do
begin
x := 0;
while x $#@60; Width do
begin
Canvas.Draw(x, y, Image1.Picture.Bitmap);
x := x + iBMWid;
end;
y := y + iBMHeight;
end;
end;
3(创建异形窗体
//例:画圆角矩形窗口
procedure TForm1.DrawRndRectRegion;
var
rgn: HRgn;
Rect: TRect;
begin
Rect := Self.Canvas.ClipRect;
rgn := CreateRoundRectRgn(rect.left, rect.top, rect.right, rect.bottom, 30, 30);
SetWindowRgn(Self.Handle, rgn, TRUE);
end;
其它:CreateEllipticRgn(椭圆),CreatePolygonRgn(多边形)略。
4(用渐变色填充窗体
procedure TForm1.FormPaint(Sender: TObject);
var
Row, Ht: Word ;
begin
Ht := (ClientHeight + 255) div 256 ;
for Row := 0 to 255 do
with Canvas do begin
Brush.Color := RGB(Row, 0, 0) ;
FillRect(Rect(0, Row * Ht, ClientWidth, (Row + 1) * Ht)) ;
end ;
end;
5(实现Winamp形式窗口拖动的方法
//在窗体的Private节中作如下声明
procedure WmNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
//在实现部分写如下代码:Ht: Word ;
begin
Ht := (ClientHeight + 255) div 256 ;
for Row := 0 to 255 do
with Canvas do begin
Brush.Color := RGB(Row, 0, 0) ;
FillRect(Rect(0, Row * Ht, ClientWidth, (Row + 1) * Ht)) ;
end ;
end;
5(实现Winamp形式窗口拖动的方法
//在窗体的Private节中作如下声明
procedure WmNCHitTest(var Msg: TWMNCHitTest); message WM_NCHITTEST;
//在实现部分写如下代码:
procedure TForm1.WmNCHitTest(var Msg: TWMNCHitTest);
begin
DefaultHandler(Msg);
if Msg.Result = HTCLIENT then
Msg.Result := HTCAPTION;
enbr> Y := 480;
end;
with ptMaxTrackSize do
begin
X := 800;
Y := 600;
end;
end;
end;
7(自汇状态栏
//设置状态栏面板对象的Style为OwnerDraw,并在状态栏对象的DrawPanel事件中书写以下代码:
procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar;
Panel: TStatusPanel; const Rect: Trect);
begin
with statusbar1.Canvas do begin
Brush.Color := clRed;
FillRect(Rect);
TextOut(Rect.Left, Rect.Top, "Panel "+IntToStr(Panel.Index));
end;
end;
8(一个具有超连接性质的Label(示范如何使控件具有鼠标进入与退出事件)
//新建单元,创建以下类
uses Windows, Messages, Graphics, Controls, StdCtrls;
………..
TMyLabel = class(Tlabel)
Private
FMouseInPos : Boolean;
procedure CMMouseEnter(var Amsg: Tmessage); message CM_MOUSEENTER;
procedure CMMouseLeave(var Amsg: Tmessage); message CM_MOUSELEAVE;
protected
procedure Paint; override;
End;
//各事件代码
procedure TMyLabel.CMMouseEnter(var Amsg: Tmessage);
begin
FMouseInPos := True;
Refresh;
end;
procedure TMyLabel.CMMouseLeave(var Amsg: Tmessage);
begin
FMouseInPos := False;
Refresh;
end;
procedure TMyLabel.Paint;
begin
if FMouseInPos then
begin
Font.Color := clRed;
Font.Style := Font.Style + [fsUnderline];
end
else
begin
Font.Color := clBlue;
Font.Style := Font.Style - [fsUnderline]; end;
Inherited Paint;
end;
利用COM技术实现外壳扩展的属性页
当用户在资源管理器中调用右键菜单时,会显示一个"属性"菜单项,点击属性菜单项会显
示一个属性页,用户可以获得甚至修改文件信息。我们可以定制属性页通过实现属性页扩展。如下图所示,本文实现了一个显示wave(波形)文件的信息如声道数等信息的属性页扩展。
属性页扩展通常是同某类文件相关联的来实现同之相关的操作和信息显示,另外可以同驱动器相关联,我们还可以用属性页扩展来替换控制面板程序的属性页。象其他外壳扩展程序一样,属性页扩展也是以动态连接库形式实现的进程内COM对象。它除了IUnknown接口外还要实现IShellExtInit和IShellPropSheetExt接口。
建立同文件关联的属性页扩展
首先,我们用命令File|New...,创建一个ActiveX Library,然后新建一个COM Object,实现的接口为IShellExtInit和IShellPropSheetExt。
同文件建立关联需要注册属性页,要在注册表中同相应文件对应的表项下添加Shellex/PropertySheetHandlers子键,每增加一个页面就需要注册一个表项,最大可以添加的页面数是24,我们可以用一个扩展实现多个页面。这里我们通过从TComObjectFactory继承类实现的UpdateRegistry实现了注册。
type
TCXPropSheetFactory=class(TComObjectFactory)
public
procedure UpdateRegistry(Register: Boolean); override;
end;
procedure TCXPropSheetFactory.UpdateRegistry(Register: Boolean);var
ClassID: string;
Str,KeyName : string;begin
inherited UpdateRegistry(Register);
if Register then
begin
ClassID:=GUIDToString(Class_CXPropSheet);
with TRegistry.Create do
try
RootKey:=HKEY_CLASSES_ROOT;
OpenKey(?\.wav?,TRUE);
KeyName := ReadString(??);
if Keyname = ?? then
begin
WriteString(??,?WaveFile?);
OpenKey(?\.wav?,TRUE);
KeyName := ReadString(??);
end;
OpenKey(?\?+KeyName+?\shellex\Propert eetHandlers\Wav?,TRUE);
WriteString(??,Classid);
finally
Free;
end;
if(Win32Platform=VER_PLATFORM_WIN32_NT)then
begin
with TRegistry.Create do
try
RootKey:=HKEY_LOCAL_MACHINE;
OpenKey(?SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions?, True);
OpenKey(?Approved?, True);
WriteString(ClassID, ?Wave File Property Sheet?);
finally
Free;
end;
end;
end
else
删除注册表项....................... end;初始化扩展是通过IShellExtInit实现的,当外壳调用IShellExtInit.Initialize时,它传递一个数据对象包含来文件对应的目录的PIDL标识符。Initialize方法需要从数据对象中提取文件名,并把文件名和PIDL标识符保存起来为了以后使用。
function TCXPropSheet.SEIInitialize(pidlFolder: PItemIDList;
lpdobj: IDataObject; hKeyProgID: HKEY): HResult;
var
StgMedium: TStgMedium;
FormatEtc: TFormatEtc;
szFile: array[0..MAX_PATH+1]of Char;
filecount: integer;begin
Result:=E_FAIL;
if(lpdobj=nil)then
begin
Result:=E_INVALIDARG;
messagebox(0, ?1?, ?错误?, mb_ok);
Exit;
end;
with FormatEtc do
begin
cfFormat:=CF_HDROP;
ptd:=nil;
dwAspect:=DVASPECT_CONTENT;
lindex:=-1;
tymed:=TYMED_HGLOBAL;
end;
Result:=lpdobj.GetData(FormatEtc, StgMedium);
if Failed(Result)then
Exit;
//如果只有一个文件被选中,获得文件名并保存。
filecount:=DragQueryFile(stgmedium.hGlobal, $FFFFFFFF, nil, 0);
if filecount=1 then
begin
Result:=NOERROR;
DragQueryFile(stgmedium.hGlobal, 0, szFile, SizeOf(szFile));
FFilename:=strpas(szFile);
end;
ReleaseStgMedium(StgMedium);end;添加页面的操作是通过IShellPropSheetExt接口来实现的。如果属性页是和文件相关联,外壳会调用IShellPropSheetExt.AddPages给属性页添加一个页面。如果属性页同控制面板程序相关联,外壳调用IShellPropSheetExt.ReplacePage来替换页面。
IShellPropSheetExt.AddPages方法有两个参数,lpfnAddPage是一个指向AddPropSheetPageProc回调函数的指针,回调函数用来提供要添加的页面信息给外壳。lParam是一个用户自定义的值,这里我们用它来返回给回调函数对象。
一般的IShellPropSheetExt.AddPages方法实现步骤是:
给PROPSHEETPAGE结构设定正确的值,特别是:
把扩展的对象引用记数变量付值给pcRefParent成员,这可以防止页面还在显示时,扩展对象被卸载。
实现PropSheetPageProc回调函数来处理页面创建和销毁的情况。
调用CreatePropertySheetPage函数来创建页面。
调用lpfnAddPage指向的函数来来添加创建好的页面。
function TCXPropSheet.AddPages(lpfnAddPage: TFNADDPROPSHEETPAGE;
lParam: LPARAM): HResult;var
PSP: TPropSheetPage;
HPSP: HPropSheetPage;begin
result:=E_FAIL;
try
psp.dwSize:=SizeOf(psp);
psp.dwFlags:=PSP_USEREFPARENT or PSP_USETITLE or PSP_USECALLBACK;
psp.hInstance:=hInstance;
//这里我们使用了事先储存在wave.res中的对话框模板,模板是用delphi5自带的
//resource workshop编辑的,使用delphi5\bin\brcc32.exe编译的。
psp.pszTemplate:=MakeIntResource(100);
//标题名
psp.pszTitle:=?波文件信息?;
//设定回调函数
psp.pfnDlgProc:=@DialogProc;
psp.pfnCallBack:=@PropCallback;
//设定对象引用记数变量
psp.pcRefParent:=@comserver.objectcount;
//用lParam向回调函数传递对象
psp.lParam:=integer(self);
HPSP:=CreatePropertySheetPage(psp);
if HPSP$#@60;$#@62;nil then begin
if not lpfnAddPage(HPSP, lParam)then begin
DestroyPropertySheetPage(HPSP);
end else begin
_addref;//增加引用记数,否则一脱离这个方法的作用域,delphi自动释放对象。
result:=S_OK;
end
end
except
on e: exception do begin
e.message:=?添加页面?+e.message;
messagebox(0, pchar(e.message), ?错误?, mb_ok);
end;
end;end;
function TCXPropSheet.ReplacePage(uPageID: UINT;
lpfnReplaceWith: TFNADDPROPSHEETPAGE; lParam: LPARAM): HResult;begin
Result:=E_NOTIMPL;//同文件关联时,外壳不调用ReplacePage,所以不用实现end;回调函
数处理属性页的消息,主要要响应WM_INITDIALOG消息来初始化页面显示信息,响应
WM_COMMAND消息来处理用户交互,响应WM_NOTIFY消息来处理页面切换或关闭后处
理操作结果。
function DialogProc(hwndDlg: HWnd; Msg: UINT; wParam: wParam;
lParam: LPARAM): Bool; stdcall;
var
PageObj: TCXPropSheet;
filename: string;
displayName : string;
SheetHWnd: HWnd;
begin
result:=false;
try
if Msg=WM_INITDIALOG then begin//初始化界面
//获得lparam传递过来的对象
pageObj:=TCXPropSheet(PPropSheetPage(lParam)^.lParam);
//保存对象信息
SetWindowLong(hwndDlg, DWL_USER, integer(pageObj));
//设置界面显示波文件信息
SetDlgItemText(hwndDlg, 100, PChar(ExtractFileName(PageObj.FFileName)));
OpenMedia(PageObj.FFileName);
SetDlgItemText(hwndDlg, 101, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_AVGBYTESPERSEC))));
SetDlgItemText(hwndDlg, 102, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_BITSPERSAMPLE))));
SetDlgItemText(hwndDlg, 103, PChar(IntToStr(GetWavStatus(MCI_WAVE_STATUS_CHANNELS))));
CloseMedia;
SetWindowLong(hwndDlg, DWL_MSGRESULT, 0);
Result:=TRUE;
end
else if(Msg=WM_COMMAND)then begin
if Lo(wParam)=110 then//用户点击了关于按钮(id=110)
MessageBox(0,?作者:hubdog?+#13#10+?email:hubdog@263.net?,?关于...?,MB_OK);
end else if(msg=WM_NOTIFY)then begin
sheetHwnd:=getparent(hwndDlg);//获得属性页的窗口句柄
case PNMHdr(lparam)^.code of
//页面失去焦点
PSN_KILLACTIVE:
begin
SetWindowLong(hwndDlg, DWL_MSGRESULT, 0);
Result:=TRUE;
end;
end;
end;
except
on e: exception do begin
e.message:=?回调处理?+e.message;
messagebox(0, pchar(e.message), ?错误?, mb_ok);
end;
end;
end;
建立同驱动器相关联的属性页扩展用
同上面讲的有两点不同:
IShellExtInit.Initialize方法传递过来的数据对象包含的驱动器路径可能是CFSTR_MOUNTEDVOLUME格式而不是CF_HDROP格式的?曜记魇荂F_HDROP格式的,而在NTFS文件系统中映射的远程设备则是CFSTR_MOUNTEDVOLUME格式的。
注册表项是HKEY_CLASSES_ROOT\Drive\Shellex\PropertySheetHandlers子键。
建立控制面板属性页扩展
同上面讲的有两点不同:
控制面板程序调用IShellPropSheetExt.ReplacePage方法来替换页面,它不调用IShellPropSheetExt。AddPages方法。
注册方式:子键可以在不同位置创建,这依赖于扩展是针对用户还是针对机器的。对用户方式子键是HKEY_CURRENT_USER\REGSTR_PATH_CONTROLPANEL,否则子键是HKEY_LOCAL_MACHINE\REGSTR_PATH_CONTROLSFOLDER。
Delphi界面我来改
类 别:Delphi & IDE
WinAmp换肤,IE换肤,GF换肤,当换肤已成CFANS的必修课时,你有没有想过给Delphi也换一回肤呢,
Delphi换肤当然不能象WinAmp那样Down一些皮肤文件就OK了,也不象IE那样修改注册表就可以了(看完本文后,你会发现就是这么简单)。
我们为Delphi换肤主要要做两件事(如果有其他要求,可参照之),一是将元件选项板多行显示,二是为集成开发环境工具栏和菜单加上图片,怎样做呢,Delphi是用来编程的,当然是通过编程来实现了。
第一件事是元件选项板的多行显示,Delphi的标准元件在元件选项板上有二三十页,还有数十页的第三方控件,但Delphi的标准界面的元件选项板是单行显示的,有时用起来很不方便,如果能多行显示该多好,请跟我来:
用New菜单创建一个新Package,在Package窗口按Add按钮,选New Component页,在Ancestor Type下拉框中输入TObject,在Class Name项中输入TMyIDE,然后OK,在代码编辑器中删除Register过程的定义程实现部份,在Uses中引用comctrls。
在private段添下面两个方法:
procedure SetMultiLineComponentPalette(MuitLine:Boolean);
procedure ResizeMultiLineComponentPalette(Sender:TObject);
在Public部份添加构造函数和析构函数,如下:
constructor Create;// TObject的构造函数是静态方法,不能重载。
destructor Destroy;override;
定义一个全局变量:MyIDE1;
Var MyIDE1:TMyIDE;
以上四个函数及过程的实现部份如下:
constructor TMyIDE.Create;
begin
SetMultiLineComponentPalette(True); End;
destructor TMyIDE.Destroy;
begin
SetMultiLineComponentPalette(False); end;
procedure TMyIDE.SetMultiLineComponentPalette(MuitLine:Boolean);
Var m:Integer;
App:TForm;
TabControl:TTabControl;
begin
if Screen.FormCount>0 then
begin
For m:=0 to Screen.FormCount-1 do//遍历IDE的所有窗体;
begin
App :=Screen.Forms[m];
if UpperCase(App.Name)='APPBUILDER' then//如果是Delphi的主窗体;
begin
TabControl:=TTabControl(App.FindComponent('TabControl'));//元件选项板;
if TabControl<>nil then
begin
TabControl.MultiLine:=MuitLine;//多行显示;
if MuitLine then
TabControl.OnResize:=MyIDE1.ResizeMultiLineComponentPalette
//OnResize事件,以便元件选项板能显示元件页;如果不处理该事件,元件选项板将不能显示出元件页。
else
TabControl.OnResize:=nil;
end;
end;
end;
end;
end;
procedure TMyIDE.ResizeMultiLineComponentPalette(Sender:TObject);
var AHeight: Integer;
begin
if Sender is TTabControl then
begin
with Sender as TTabControl do
begin
AHeight := Height-(DisplayRect.Bottom-DisplayRect.Top)+29;
Constraints.MinHeight:=AHeight;
Constraints.MaxHeight:=AHeight;//改变约束高度;
(Sender as TTabControl).Parent.Constraints.MaxHeight:=AHeight;
(Sender as TTabControl).Parent.Constraints.MinHeight:=AHeight;//改变父控件的约束高度;
end;
end;
end;
代码应该不难看懂,但是定义好的方法如何使用呢,这就要单元的单元的初始化initialization部分Create MyIDE;又要在finalization部份释放MyIDE。代码如下: initialization
MyIDE1:=TMyIDE.Create;
finalization
MyIDE1.Free;
end.
下面对以上的代码略加解释:
在TMyIDE类的Create构造函数中使用SetMultiLineComponentPalette(True)过程改变IDE的元件选项板,在析构函数中调用SetMultiLineComponentPalette(False)将IDE改成标准IDE界面。
在SetMultiLineComponentPalette方法中,首先遍历系统所有的Form对象,找到Delphi IDE
的主界面,然后用Tform的FindComponent函数找到名为TabControl的元件对象,改变其MultiLine属性,如果MultiLine为True就将其OnResize事件赋与自定义的过程,否则清除OnResize事件。
在OnResize(ResizeMultiLineComponentPalette方法)事件中,计算元件选项板的所需高度,然后改自已和父控件的约束度高度。
以上代码完成后,在Package窗口中按Install按钮,怎么样,还行吧~ 第二件事是给IDE添加图片,这部份就复杂多了,限于篇幅,这里只作简单介绍,笔者主页上有免费详细代码供下载,。
给IDE添加图片的原理是在MyIDE的Create函数中遍历所有的Delphi的主窗体的元件,如果是主菜单或弹出菜单就将其OwnerDraw属性设成True;然后用递归的方法设置其各子菜单的OnDrawItem事件,并在该事件中自已绘制菜单项,这样你就可以随心所欲地自已作出自已的IDE界面,如果你愿意,你也许能作出一个象WinAmp一样的Delphi IDE来。
Delphi实现容器分隔
随着Windows95的流行,分隔器控件已成为操作系统的常用部件,它将容器(通常为窗体或面板)的客户区域分为可调整大小的若干部分,称为窗格。我们最常见到的例子就是Windows95的资源管理器,它使用了一个分隔器控件(也就是在资源管理器中可以用鼠标左右拖动的竖条)将目录树视图和文件表视图分隔开,可以由用户任意调整。Delphi提供了一个分隔器控件TSplitter来实现这种功能,下面以制作一个简单的资源管理器为例来介绍设计步骤:
1.从Standard 标记页中选择容器Panel控件,将其放入Form1中,命名为Panel1,并将其Align属性设置为alClient。
2.从Win3.1标记页中选择DirectoryListBox控件,将其放入容器Panel1中,命名为DirectoryListBox1,置Align属性为alLeft,并调整其初始宽度。
3.从Additional标记页中选择Splitter控件,放入容器Panel1中,置Align属性为alLeft,Width属性为5。
4.再从Win3.1标记页中选取FileListBox控件放入Panel1中,命名为FileListBox1,置Align属性为alClient。
5.最后,将DirectoryListBox1的FileList属性置为FileListBox1。
现在,按F9运行程序,便会出现一个简单的资源管理器,设计出的窗体具有随意调整窗格大小的能力。在Delphi中实现容器分隔非常简单,甚至一句程序代码也不用写。要注意的是,封装了分隔器控件的TSplitter只有在Delphi 3 以上才有,Delphi 2 以下必须编写一段程序代码才能实现此功能。
(江苏 韩世伟)
Delphi之快速设计(界面篇)
?众所周知,Delphi已经是RAD之中的RAD了,但本人的目的是更加充分地挖掘出Delphi的优秀品质,哎,人的胃口呀......
本人打算从两个方面来谈论这个话题:界面设计及程序设计.
本文介绍界面的快速设计:
如果你的手在键盘上,我想你不太会愿意再去伸手拿鼠标来移动组件吧,再说鼠标也不太精确(下面提到的均针对键盘操作,能用鼠标操作完成的不在此列),那好,以下快捷键及一些技巧请各位看官"收好".
?一、以下快捷键指的是对窗体表格上组件的操作:
?快捷键1:
【Ctrl+UP】,向上移动当前组件(精确);
【Ctrl+Left】,向左移动当前组件(精确);
【Ctrl+Down】,向下移动当前组件(精确);
【Ctrl+Right】,向右移动当前组件(精确);
注:
以上快接键中再加Shift进行组合(比如【Ctrl+Shift+Right】)即可实现粗略调整;
?快捷键2:
【Shift+UP】,减小当前组件的高度;
【Shift+Left】,减小当前组件的宽度;
【Shift+Down】,增加当前组件的高度;
【Shift+Right】,增加当前组件的宽度;
注:
以上Up,Left等指的是方向键;
?二、以下快捷键指的是在对象观察器上的操作:
?快捷键3:
【F11】,切换到对象观察器(注:如果连续按F11则将实现在对象观察器、窗体表格、代码编辑器之间切换);
【Ctrl+Down】,下拉当前窗体的组件列表;
【Ctrl+Enter】,编辑带...的属性值(如组件的字体TFont);
【Alt+Down】,下拉组件当前属性选单队列(如Align->alNone,alLeft,alRight等);
【Ctrl+Tab】,在属性列表及事件列表中切换;
?三、菜单快捷键:
?快捷键4:
【F12】,【Shift+F12】,【Ctrl+F12】等在Delphi的菜单中已有定义的在此不必罗嗦.
技巧:
如何选择被组件覆盖了的窗体(比如某组件的Align属性为alClient)?
方法一、按ESC键,一层一层的往后选,直到窗体被选为当前组件为止;
方法二、按Shift的同时单击鼠标左键,一步即可选定(推荐);
方法三、按F11选定对象观察器,然后切换到属性列表,再用上面快捷键3中的【Ctrl+Down】.
CoDelphi.com版权所有,未经允许,不得进行任何形式转载
WinAmp换肤,IE换肤,GF换肤,当换肤已成CFANS的必修课时,你有没有想过给Delphi也换一回肤呢,
Delphi换肤当然不能象WinAmp那样Down一些皮肤文件就OK了,也不象IE那样修改注册表就可以了(看完本文后,你会发现就是这么简单)。
我们为Delphi换肤主要要做两件事(如果有其他要求,可参照之),一是将元件选项板多行显示,二是为集成开发环境工具栏和菜单加上图片,怎样做呢,Delphi是用来编程的,当然是通过编程来实现了。
第一件事是元件选项板的多行显示,Delphi的标准元件在元件选项板上有二三十页,还有数十页的第三方控件,但Delphi的标准界面的元件选项板是单行显示的,有时用起来很不方便,如果能多行显示该多好,请跟我来:
用New菜单创建一个新Package,在Package窗口按Add按钮,选New Component页,在Ancestor Type下拉框中输入TObject,在Class Name项中输入TMyIDE,然后OK,在代码编辑器中删除Register过程的定义程实现部份,在Uses中引用comctrls。
在private段添下面两个方法:
procedure SetMultiLineComponentPalette(MuitLine:Boolean);
procedure ResizeMultiLineComponentPalette(Sender:TObject);
在Public部份添加构造函数和析构函数,如下:
constructor Create;// TObject的构造函数是静态方法,不能重载。
destructor Destroy;override;
定义一个全局变量:MyIDE1;
Var MyIDE1:TMyIDE;
以上四个函数及过程的实现部份如下:
constructor TMyIDE.Create;
begin
SetMultiLineComponentPalette(True); End;
destructor TMyIDE.Destroy;
begin
SetMultiLineComponentPalette(False); end;
procedure TMyIDE.SetMultiLineComponentPalette(MuitLine:Boolean);
Var m:Integer;
App:TForm;
TabControl:TTabControl;
begin
if Screen.FormCount>0 then
begin
For m:=0 to Screen.FormCount-1 do//遍历IDE的所有窗体;
begin
App :=Screen.Forms[m];
if UpperCase(App.Name)='APPBUILDER' then//如果是Delphi的主窗体;
begin
TabControl:=TTabControl(App.FindComponent('TabControl'));//元件选项板;
if TabControl<>nil then
begin
TabControl.MultiLine:=MuitLine;//多行显示;
if MuitLine then
TabControl.OnResize:=MyIDE1.ResizeMultiLineComponentPalette
//OnResize事件,以便元件选项板能显示元件页;如果不处理该事件,元件选项板将不能显示出元件页。
else
TabControl.OnResize:=nil;
end;
end;
end;
end;
end;
procedure TMyIDE.ResizeMultiLineComponentPalette(Sender:TObject);
var AHeight: Integer;
begin
if Sender is TTabControl then
begin
with Sender as TTabControl do
begin
AHeight := Height-(DisplayRect.Bottom-DisplayRect.Top)+29;
Constraints.MinHeight:=AHeight;
Constraints.MaxHeight:=AHeight;//改变约束高度;
(Sender as TTabControl).Parent.Constraints.MaxHeight:=AHeight;
(Sender as TTabControl).Parent.Constraints.MinHeight:=AHeight;//改变父控件的约束高度;
end;
end;
end;
代码应该不难看懂,但是定义好的方法如何使用呢,这就要单元的单元的初始化initialization部分Create MyIDE;又要在finalization部份释放MyIDE。代码如下:
initialization
MyIDE1:=TMyIDE.Create;
finalization
MyIDE1.Free;
end.
下面对以上的代码略加解释:
在TMyIDE类的Create构造函数中使用SetMultiLineComponentPalette(True)过程改变IDE的元件选项板,在析构函数中调用SetMultiLineComponentPalette(False)将IDE改成标准IDE界面。
在SetMultiLineComponentPalette方法中,首先遍历系统所有的Form对象,找到Delphi IDE
的主界面,然后用Tform的FindComponent函数找到名为TabControl的元件对象,改变其MultiLine属性,如果MultiLine为True就将其OnResize事件赋与自定义的过程,否则清除OnResize事件。
在OnResize(ResizeMultiLineComponentPalette方法)事件中,计算元件选项板的所需高度,然后改自已和父控件的约束度高度。
以上代码完成后,在Package窗口中按Install按钮,怎么样,还行吧~
第二件事是给IDE添加图片,这部份就复杂多了,限于篇幅,这里只作简单介绍,笔者主页上有免费详细代码供下载,。
给IDE添加图片的原理是在MyIDE的Create函数中遍历所有的Delphi的主窗体的元件,如果是主菜单或弹出菜单就将其OwnerDraw属性设成True;然后用递归的方法设置其各子菜单的OnDrawItem事件,并在该事件中自已绘制菜单项,这样你就可以随心所欲地自已作出自已的IDE界面,如果你愿意,你也许能作出一个象WinAmp一样的Delphi IDE来。
下面是的修改后的IDE图片~
投稿人:大鱼儿 投稿日期:2001-5-25 9:30:00
// Author: 没脾气 notemper@hoolee.com
// 这是我按照自己的习惯改的 DelphiIDE 皮肤。
// 其中修改了“Delphi界面我来改”一文中的一个 bug
// 其中的 SetMultiLineComponentPalette 函数也许应改名。现在只是自己用,不作太多修改了。
unit jnc_IDE;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls,
ComCtrls, Grids;
type
TJnIDE = class(TObject)
private
procedure SetMultiLineComponentPalette( IsMultiLine: Boolean );
procedure ResizeMultiLineComponentPalette( Sender: TObject );
public
constructor Create;
destructor Destroy; override;
end;
var
GJnIDE: TJnIDE;
implementation
constructor TJnIDE.Create; begin
SetMultiLineComponentPalette( True );
end;
destructor TJnIDE.Destroy; begin
SetMultiLinecomponentPalette( False );
end;
procedure TJnIDE.SetMultiLineComponentPalette( IsMultiLine: Boolean );
var
m: Integer;
aForm: TForm;
frmAppBuilder: TForm;
TabControl: TTabControl;
aControlBar: TControlBar;
aSubForm: TCustomForm; begin
try
if Screen.FormCount > 0 then
begin
for m:=0 to Screen.FormCount - 1 do
begin
aForm := Screen.Forms[m];
if CompareText( aForm.Name, ''AppBuilder'' ) = 0 then
begin
frmAppBuilder := aForm;
aControlBar := TControlBar( frmAppBuilder.FindComponent( ''ControlBar1'' ) );
if aControlBar <> nil then
begin
aControlBar.BevelEdges := [ beBottom, beLeft, beRight, beTop ];
end;
TabControl := TTabControl( frmAppBuilder.FindComponent( ''TabControl'' ) );
if TabControl <> nil then
begin
TabControl.Font.Name := ''Small Fonts'' ;
TabControl.Font.Size := 7;
TabControl.MultiLine := IsMultiLine;
if IsMultiLine then
begin
TabControl.OnResize := Self.ResizeMultiLineComponentPalette;
end else
begin
TabControl.OnResize := nil; // Fixed orginal bug.
end;
end;
aSubForm := TCustomForm( frmAppBuilder.FindComponent( ''PropertyInspector'' ) );
if aSubForm <> nil then
begin
aSubForm.Font.Name := ''Tahoma'';
aSubForm.Font.Size := 9;
end;
end;
end;
end;
except
end;
end;
procedure TJnIDE.ResizeMultiLineComponentPalette( Sender: TObject );
var
AHeight: Integer;
begin
if Sender is TTabControl then
begin
with Sender as TTabControl do
begin
AHeight := Height - (DisplayRect.Bottom - DisplayRect.Top ) + 29;
Constraints.MinHeight := AHeight;
Constraints.MaxHeight := AHeight;
Parent.Constraints.MaxHeight := AHeight;
Parent.Constraints.MinHeight := AHeight;
end;
end;
end;
initialization
GJnIDE := TJnIDE.Create;
finalization
GJnIDE.Free;
end.
定制Speedbar
在Delphi的可视化设计界面中,使用最频繁的地方要数位于屏幕左上角的加速按钮栏(Speedbar)了。在实践过程中,笔者无意中发现了Speedbar的定制方法,这在我用过的四本Delphi参考书中均未提及到。步骤如下:
右键点击Speedbar,在弹出菜单中选Properties,这时会出现一个名为Speedbar Editor的对话框。假设想要增设一项“语法检查”的功能,可在左边Categories列表框中选Project,再把右侧的Syntax Check图标拖放到Speedbar的合适的位置上,这项功能就已经加上了。如果speedbar上没有多余的空间来容纳新的按钮,可将鼠标停在speedbar右框处,变为双向箭头的形状时,向右拖动一段距离,就可腾出空间。如想删除speedbar上的某个按钮,可简单地把它拖出speedbar的范围,就能删除。操作十分方便。建议把Syntax Check、Project Options(工程选项)、WindowsApi Help加到Speedbar中,可以提高开发效率。
多国语言之step
且说Energy受命之后,在Delphi5前苦苦讨教,这才发觉delphi5的技术比他 想象的还厉害,不禁冷汗直流:如果有什么闪失哪里逃得过这里大狭们的眼 睛啊。不由之间身形已经端了5尺。
Energy颤颤危危的New了一个Application,保存慌忙之间居然没起名字, 凭经验应该叫project1;然后放了一个菜单,一个按钮一个label,不禁暗自 思量到。在多国这够说明问题了吧。
想到CJ不觉在菜单的第一项中填下了caption=CJ,name=mnuChinese;呵呵, 既然有CJ也该有Energy,于是另一项中填下了 caption=Energy,name=mnuEnglish;
然后怎么办,,,
心中无限惶恐的Energy 调出了delphi的例子Demos\Richedit又看了看,立马又 气粗起来。呵呵,有一样好东西,可是让我可以省事不少,不禁又是一阵得意。 (Energy悄悄地把Demos\Richedit\reinit.pas往自己project目录一拷,在
project中又把它加了进来,自言自语道:50% over)
按他的意思先设置一下需要的语言页常数。
implementation
uses reinit;
const
ENGLISH = (SUBLANG_ENGLISH_UK shl 10) or LANG_ENGLISH;
CHINESE = (SUBLANG_CHINESE_SIMPLIFIED shl 10) or LANG_CHINESE;
{$R *.DFM}
做个初始化
procedure TForm1.FormCreate(Sender: TObject); begin
mnuEnglish.Tag:=ENGLISH;
mnuChinese.Tag:=CHINESE;
end;
然后嘛(不就是菜单切换嘛)
于是把两了菜单都指到了一个地方
procedure TForm1.mnuLangClick(Sender: TObject);
begin
if LoadNewResourceModule(TComponent(Sender).Tag) <> 0 then
ReinitializeForms;
end;
呵呵;(90% over)
不会吧,让你step,你到现在都没说,就这么尽抄袭代码。Energy委屈的说,谁让 他是课代表的。想起当年是班里总课代表,我不做功课居然就没人做的年月,不禁 又是一阵感慨。
兄弟们还差10%,加油啊~
菜单[Project]-[Languages]-[Add...] [Next>],选择中文(chs),英语(eng);(我只用了这两种语言);
[Next>],[Next>],[Next>],[Finsih],[Yes] 让你保存dpg时小心目录可能是chs,应该用上一级目录才好。
看到了吗,这是你可以修改所有的东西。别乱改。
其中有一些出错信息之类这里都后,放心改好了,改完后可以作为一个模板文件保留。 下次就不用改了。
请关闭吧~
现在可以看到你的project Manager中有3个项目,project1.exe,porject1.eng,project1.chs
后面两了是资源文件,你可以
1,双击project1.eng -- form1,然后修改一些东西。比如button1的caption="eng";改变一下它
的大小和字体。
2,双击project1.chs -- form1,然后修改一些东西。比如button1的caption="chs";改一下字体。 不过最好不要随意改动form的大小和位置~
选中project1.exe,设定为Activate;
然后(兄弟们99%了)
右键project1.chs--build;
右键project1.eng--build;
右键project1.exe--build;
run
噫,你会发现exe中的界面不起作用了。呵呵,系统自己自动选择了一个语言页嘛。 什么你不要自动,$#$%^%^&,[project]-[Languages]-[set Active];
对了如果要在调出那个grid方式修改的工具可以[view]-[Translation Manager];
好了好了,顺便付上我写了说明的reinit.pas文件其实好好看一下就知道还有更强大
的功能等着你利用呢~
语言页的常数在windows.pas里开始于行218;且
+-----------------------+-------------------------+ | Sublanguage ID | Primary Language ID | +-----------------------+-------------------------+ 15 10 9 0 bit
unit ReInit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms;
procedure ReinitializeForms; //重新设置form
function LoadNewResourceModule(Locale: LCID): Longint; // 调取新的语言资源
implementation
type
TAsInheritedReader = class(TReader)
public
procedure ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer); override;
end;
procedure TAsInheritedReader.ReadPrefix(var Flags: TFilerFlags; var AChildPos: Integer);
begin
inherited ReadPrefix(Flags, AChildPos);
Include(Flags, ffInherited);
end;
// 刷新语言页
function SetResourceHInstance(NewInstance: Longint): Longint; var
CurModule: PLibModule;
begin
CurModule := LibModuleList; // 系统全局变量;模块列表。
Result := 0;
while CurModule <> nil do
begin
if CurModule.Instance = HInstance then
begin
if CurModule.ResInstance <> CurModule.Instance then
FreeLibrary(CurModule.ResInstance); // 释放旧语言页所占资源
CurModule.ResInstance := NewInstance; // 设置新语言页
Result := NewInstance;
Exit;
end;
CurModule := CurModule.Next;
end;
end;
// 调取新的语言资源 LCID为语言页;
function LoadNewResourceModule(Locale: LCID): Longint;
var
FileName: array [0..260] of char;
P: PChar;
LocaleName: array[0..4] of Char;
NewInst: Longint;
begin
GetModuleFileName(HInstance, FileName, SizeOf(FileName)); // 别紧张,只是取一下当前
// 的模块名,之所以如此是
// 由于可能本身是个dll。
GetLocaleInfo(Locale, LOCALE_SABBREVLANGNAME, LocaleName,
SizeOf(LocaleName)); //取当前使的语言页
P := PChar(@FileName) + lstrlen(FileName); //指针运算而已 //可能是exe :-)
while (P^ <> '.') and (P <> @FileName) do Dec(P); //找到语言页资源文件的后缀
NewInst := 0;
Result := 0;
if P <> @FileName then // 如果找到
begin
Inc(P);
if LocaleName[0] <> #0 then
begin
// Then look for a potential language/country translation
lstrcpy(P, LocaleName); // 解出资源文件名文件
NewInst := LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE); // 加载资源文件
if NewInst = 0 then
begin
// Finally look for a language only translation // 加载失败,使用原文件
LocaleName[2] := #0;
lstrcpy(P, LocaleName);
NewInst := LoadLibraryEx(FileName, 0, LOAD_LIBRARY_AS_DATAFILE);
end;
end;
end;
if NewInst <> 0 then
Result := SetResourceHInstance(NewInst) // 用资源文件刷语言。
end;
function InternalReloadComponentRes(const ResName: string; HInst: THandle; var Instance:
TComponent): Boolean;
var
HRsrc: THandle;
ResStream: TResourceStream;
AsInheritedReader: TAsInheritedReader;
begin { avoid possible EResNotFound exception }
if HInst = 0 then HInst := HInstance;
HRsrc := FindResource(HInst, PChar(ResName), RT_RCDATA);
Result := HRsrc <> 0;
if not Result then Exit;
ResStream := TResourceStream.Create(HInst, ResName, RT_RCDATA);
try
AsInheritedReader := TAsInheritedReader.Create(ResStream, 4096);
try
Instance := AsInheritedReader.ReadRootComponent(Instance);
finally
AsInheritedReader.Free;
end;
finally
ResStream.Free;
end;
Result := True;
end;
function ReloadInheritedComponent(Instance: TComponent; RootAncestor: TClass): Boolean;
function InitComponent(ClassType: TClass): Boolean;
begin
Result := False;
if (ClassType = TComponent) or (ClassType = RootAncestor) then Exit;
Result := InitComponent(ClassType.ClassParent);
Result := InternalReloadComponentRes(ClassType.ClassName, FindResourceHInstance(
FindClassHInstance(ClassType)), Instance) or Result;
end;
begin
Result := InitComponent(Instance.ClassType);
end;
//重新设置在显示中的所有from,;
procedure ReinitializeForms; var
Count: Integer;
I: Integer;
Form: TForm;
begin
Count := Screen.FormCount;
for I := 0 to Count - 1 do
begin
Form := Screen.Forms[I];
ReloadInheritedComponent(Form, TForm); //重新刷新所有元件几其父对象
end;
end;
end.
////////////////////////////////
用Delphi 5的Integrated Translation Environment (ITE)可以轻易得完成这个工作。
我们创建一个示意性的工程MultiLanguage,在Form上放一个Label和一个Button,分别把Caption赋值为“English Label”和“English Button”。
选择菜单Project|anguages|Add ..., Delphi显示Add Languages对话框,选择Next。
从语言列表中选中“英语(美国)”和“中文(中国)”,选择Next。
ITE会根据所选的语言创建子目录,目录名称是语言的缩写,选择Next。
第一次增加语言时, Update Mode固ㄎ狢reate new,选择Next。
选择Finish。
Delphi会自动创建支持不同语言的资源动态库。
Delphi还会自动创建一个工程组,其中包括原有的MultiLanguages.EXE,还包括新建的两个资源动态库 (MultiLanguages.enu, MultiLanguages.chs)。保存工程组。
Delphi启动Translation Manager,左边是需要翻译的语言,右边是完成百分比。
选择“中文(中国)”|Forms|Unit1,在右边第15行和20行填写翻译后的中文。保存并关闭。
打开Project Manager,编译MultiLanguages.enu和MultiLanguages.chs, Delphi会在相应的子目录生成资源动态库,但后缀不是DLL而是ENU和CHS。
更改StatusBar为黑底绿字
各位道友大家好, 祝大家新年快乐. 请问一下, 我如果要做到如标题的效果, 该如何写呢?? 底下是我用来Try的程式, 但无法正确work. 请指教,
(原程式省略)
首先, 启动 Statusbars.Panels 的属性编辑器(从 Object Inspector 中, 点一下 Panels 属性右边的'...'小按钮), 确定各 Panels 的 Sytle 是否为: OwnerDraw (若为 Text, 则 OnDrawPanel 事件不会有作用的).
其次
procedure TForm1.StatusBar1DrawPanel(StatusBar: TStatusBar;
Panel: TStatusPanel; const Rect: TRect); begin
Panel.Style:=psOwnerDraw; // 这行可以去掉
// StatusBar.Canvas.Brush.Color:=clGreen; // StatusBar.Canvas.Font.Color:=clBlack;
// 如果如您的标题 -- 黑底绿字, 那是不是应该改成 --
StatusBar.Canvas.Brush.Color:=clBlack;
StatusBar.Canvas.Font.Color:=clGreen;
StatusBar.Canvas.FillRect(Rect); // 显示文字:
StatusBar.Canvas.TextRect(Rect, Rect.Left, Rect.Top, Panel.Text);
end;
界面色彩渐变效果是通过用渐变的画刷刷绘依次相邻的矩形块实现的。下面列举实例说明:
1.新建一个表单,假设其Width为500,设置一个按钮Button1,按此按钮将把表单置为由左
向右由黄变白的渐变效果。
2.Button1按钮的代码如下:
procedure TForm1.Button1Click(Sender: TObject);
var i,j:Integer;
Dct:TRect;
begin
j:=Form1.height;
//获得表单高度
for i:=0 to 255 do
//此处设置RGB()中一个颜色值
begin
Canvas.Brush.Color:=RGB(255,255,i);
//每次画矩形的画刷颜色
Dct:=Rect(i,2,0,(i,1),2,j);
//每次刷绘的矩形区域
Canvas.FillRect(Dct);
//填充颜色
end;
end;
界面设计,让属性页更吸引人
步骤如下:
1. 设定 TForm.BorderWidth := 6
2. 添加一个TPanel
3. TPanel同底部对齐
4. 设定 TPanel.Height := 30
5. 添加 TButtons 到 TPanel
6. 设定 TButton.Top := 6
7. 按钮间间距为8
8. 添加一个TPageControl
9. 添加一个TTabSheet
10. 设定 TPageControl.BorderWidth := 12
如果添加 TBevels, 把它们对齐到顶部或底部,它们会摞到一起去的。同时对齐labels到左边通过设定TLabel.Left := 0。