五维网络域名:
  5dweb.yeah.net
  5dweb.126.com
  5dweb.iscool.net

电子信箱地址:
  [email protected]

编程维
编程技巧
上界
编程维
信息维
软件维
硬件维
另类维
下界
返回主页

五维网络2,值得您稍稍等待。

如何在程序执行时动态生成控件?
 
代码举例:

var
 MyBtn:TButton;
begin
 MyBtn:=TButton.Create(Form1);
 MyBtn.Parent:=Form1;
 MyBtn.Left:=10;
 MyBtn.Top:=10;
 MyBtn.OnClick:=MyOnClick;
 MyBtn.Show;
end;

注:MyOnClick 为自编的事件过程。

下面详细的介绍一下具体的编程方法:

一、运行时生成可视控件:以下以TEdit 控件为例
1.在Form的Public中定义TEdit控件
  Edit1:TEdit;
2.在需要生成的地方加入以下代码:
  Edit1:=TEdit.Create(Self);
  Edit1.Parent:=Form1;
  Edit1.Left:=20;
  Edit1.Top:=20;
  Edit1.Text:='Edit1 Text';
3.使用完毕后,释放分配的资源(注意,这是初学者容易忘记的地方)
  if  Assigned(Edit1) then Edit1.Free; 

二、运行时生成非可视控件:以下以TTimer控件为例
1.在Form的Public中定义TTimert控件
  Timer1:TTimber;
2.在需要生成的地方加入以下代码:
  Timer1:=TTimer.Create(Self); 
  Timer1.OnTimer:=YourTimerAction;
注:YourTimerAction是自己定义的OnTimer事件。
3.使用完毕后,释放分配的资源 
  if  Assigned(Timer1) then Timer1.Free; 

[上一页]      

 
如何共享某一控件的某一事件?
 
请看下面的例子:

假设一个按钮有如下的事件:
procedure TForm1.Button1Click(Sender: TObject);
begin
 Edit1.Text:='Clicked!';
end;

现在想在一个菜单选项中实现同样的功能,由于是做同样的事,
所以自然不用将代码重写一遍,只需在菜单选项的事件中这样写:
procedure TForm1.Item1Click(Sender: TObject);
begin
 Button1Click(Self);
end;

当然,如果您只是想实现上述的功能,其实完全不必这样写代码。
因为 Delphi 的 TActionList 控件就是来实现这样的功能的。而
事实上,在大多数情况下您并不知道该菜单选项的固定事件,也
就是说,往往需要动态的指定该菜单选项的事件。您可以这样写:
 ...
 Item1.OnClick:=Button1Click;
 ...

在需要的时候,执行上述代码后,您的菜单选项的OnClick事件就
发生了改变。

[上一页]      

 
如何在程序执行时动态定制菜单?
 
为叙述方便,把弹出式菜单定义给 Form1,用 1,2,3,4 来表示定制的菜单项的内容,以按钮 Button1 实现菜单项变化的激活。

1、在 Form1 上放置 PopupMenu1(TPopupMenu) 与 Button1(TButton),设置各种属性如下:

Form1
  PopupMenu:PopupMenu1
Button1
  Caption:菜单1234

2、为 Button1 赋以下事件响应:

procedure TForm1.Button1Click(Sender: TObject);
var
 MenuItem:array[1..4] of TMenuItem;
 I:Integer;
begin
 while PopupMenu1.Items.Count>0 do
 PopupMenu1.Items.Delete(0);
 for I:=1 to 4 do
 begin
  MenuItem[I]:=TMenuItem.Create(Self);
  MenuItem[I].Caption:=IntToStr(I);
  MenuItem[I].OnClick:=ShowIt;
  MenuItem1.Items.Add(MenuItem[I]);
 end;
end;

//注意,ShowIt 是程序中自制的 Procedure。

procedure TForm1.ShowIt(Sender:TObject);
begin
 with Sender as TMenuItem do
 ShowMessage(Caption);
end;

//当然,需要在程序中事先声明此过程。
//注意,在以上代码示例中并没有将生成的菜单选项进行释放;
//在实际程序中,必须在适当的时候,及时用 Free 方法清除。

[上一页]      

 
如何在 Delphi 中进行消息处理?
 
Delphi 是 Borland 公司提供的一种全新的 WINDOWS 编程开发工具.由于它采用了具有弹性的和可重用的面向对象 Pascal(object-orientedpascal) 语言,并有强大的数据库引擎(BDE),快速的代码编译器,同时又提供了众多出色的构件.受到广大编程人员的青睐.在众多的编程语言(如 VB,PowerBuilder,Powerpoint 等)中脱颖而出.其中一个 DELPHI 强于其他编程语言(如 VB4.0)的地方就是在DELPHI中可自定义消息,并可直接处理消息.这对于那些希望编写自己的构件(Component),或者希望截获.过滤消息的用户来说是必不可少的.因为编写构件一般要对相应的消息进行处理.下面就对 Delphi 中消息处理机制进行一下介绍。一.DELPHI VCL 中消息的传递 Delphi 中每一个 VCL(VisualComponentLibrary)构件(如 Tbutton,Tedit 等)都有一内在的消息处理机制,其基本点就是构件类接收到某些消息并把它们发送给适当的处理方法,如果没有特定的处理方法,则调用缺省的消息处理句柄。

下流程图说明了消息传递的一般途径,如图所示:
其中 mainwndproc 是定义在 Twincontrol 类中的一个静态方法,不能被重载(Override)。它不直接处理消息,而是交由 wndproc 方法处理,并为 wndproc 方法提供一个异常处理模块。Mainwndproc 方法声明如下:
procedure MainWndProc(var Message:TMessage); Wndproc 是在 TControl 类中定义的一个虚拟方法,由它调用 dispatch 方法来进行消息的分配,wndproc 方法声明如下:

procedure WndProc(var Message:TMessage);virtual;
dispatch 方法是在 TObject 根类中定义的,其声明如下:
procedure Tobject.dispatch(var Message);
传递给 dispatch 的消息参数必须是一个记录类型,且这个记录中第一个入点必须是
一个 cardinal 类型的域(field),它包含了要分配的消息的消息号码.例如:
type
 Tmessage=record
  Msg:cardinal;
  wparam:word;
  lparam:longint;
  result:longint;
 end;
而 Dispatch 方法会根据消息号码调用构件的最后代类中处理此消息的句柄方法.如果此构件和它的祖先类中都没有对应此消息的处理句柄,Dispatch 方法便会调用 Defaulthandler 方法.Defaulthandler 方法是定义于 TObject 中的虚拟方法,其声明如下:
procedure Defaulthandler(var Message);virtual; TObject 类中的 Defaulthandler 方法只是实现简单的返回而不对消息进行任何的处理.我们可以通过对此虚拟方法的重载,在子类中实现对消息的缺省处理.对于VCL中的构件而言,其 Defaulthandler 方法会启动 windows API 函数 Defwindowproc 对消息进行处理.

二.DELPHI 中的消息处理句柄
在 DELPHI 中用户可以自定义消息及消息处理句柄.消息处理句柄的定义有如下几个原则:消息处理句柄方法必须是一个过程,且只能传递一个 Tmessage 型变量参数. 方法声明后要有一个 message 命令,后接一个在 0 到 32767 之间的消息标号(整型常数).消息处理句柄方法不需要用 override 命令来显式指明重载祖先的一个消息处理句柄,另外它一般声明在构件的 protected 或 private 区.在消息处理句柄中一般先是用户自己对消息的处理,最后用 inherited 命令调用祖先类中对应此消息的处理句柄(有些情况下可能正相反).由于可能对祖先类中对此消息的处理句柄的名字和参数类型不清楚,而调用命令 inherited 可以避免此麻烦,同样如果祖先类中没有对应此消息的处理句柄,inherited 就会自动调用 Defaulthandler 方法.(当然如果要屏蔽掉此消息,就不用 inherited 命令了)。
消息处理句柄方法声明为:
procedure Mymsgmethod(var message:Tmessage);message Msgtype;
同样用户也可以定义自己的消息,用户自定义消息应从WM_USER开始.
自定义消息及消息处理句柄举例如下:

constmy_paint=Wm_user+1;
type
 Tmypaint=record
 msgid:cardinal;
 msize:word;
 mcolor:longint;
 msgresult:longint;
end;

type
 Tmycontrol=class(TCustomControl)
 protected
 procedure change(var message:Tmypaint);message my_paint;
 .....
 end;
 ......
procedure Tmycontrol.change(var message:Tmypaint);
begin
 size:=message.msize;{设置Tmybutton尺寸属性}
 color:=message.mcolor;{设置Tmybutton颜色属性}
 {dosomethingelse}
 inherited;{交由Tcustomcontrol处理}
end;
三.过滤消息
过滤消息又称消息陷阱。在一定情况下,用户可能需要屏蔽某些消息.或者截获某些消息进行处理。由以上介绍可以看出过滤消息一般有三种途径:(1).重载构件继承的虚拟方法wndproc.(2).针对某消息编写消息处理句柄.(3).重载构件继承的虚拟方法Defhandler,在其中对消息进行处理。其中常用的方法是方法(2),在上节中已介绍过了,方法(1)与方法(3)相似,这里只简单介绍一下方法(1)。
重载虚拟方法wndproc的一般过程如下:
procedure Tmyobject.wndproc(var message:Tmessage);
begin
 {...判断此消息是否该处理..}
 inherited wndproc(message);
 {未处理的消息交由父辈wndproc方法处理}
end;

由此可以看出在wndproc方法中处理消息的优势是可以过滤整个范围内的消息,
而不必为每个消息指定一个处理句柄,事实上Tcontrol构件中就是利用它来过
滤并处理所有的鼠标消息的(从WM_mousefirst到WM_mouselast,如下代码示).
同样利用它也可以阻止某些消息被发送给处理句柄。

procedure TControl.WndProc(var Message:TMessage);
begin
 if (Message.Msg>=WM_MOUSEFIRST) and (Message.Msg<=WM_MOUSELAST) then
 if Dragging
 then{处理拖曳事件}
 DragMouseMsg(TWMMouse(Message))
 else
 begin
  ...{处理其他鼠标消息}
 end;
 Dispatch(Message);
 {否则正常发送消息}
end;

下例为一简单的自定义构件例子:

Tmyedit类是从Tedit类派生出的一个新类,它的特点是在运行中不能获得焦
点,不能由键盘输入(有点类似Tlabel构件).我们可在其wndproc方法中过
滤出WM_setfocus,WM_mousemove消息并进行处理来达到上述要求,源程序如
下:
unit myedit;

interface

uses
Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,Dialogs,
StdCtrls;

type

 Tmyedit=class(TEdit)
 private
  {Privatedeclarations}
 protected
  {Protected declarations}
  {other fields and methods}
procedure wndproc(var message:Tmessage);override;
public
 {Public declarations}
published
 {Published declarations}
end;
procedure Register;
implementation
procedure Register;
begin
 RegisterComponents('Samples',[Tmyedit]);
end;
procedure Tmyedit.wndproc(var message:tmessage);
begin
 if message.msg=wm_mousemove then
 begin
  cursor:=crarrow;
  {设置光标为crarrow,而不是缺省的crBeam光标}
  exit;
 end;
 if message.msg=wm_SetFocus then exit;
 {屏蔽掉WM_setfocus消息,不让Tmyedit控件获得输入焦点}
 inherited wndproc(message);
 {其他消息交父辈wndproc处理}
end;
end.
您可以将Tmyedit加到ComponentPalette中检验其性能。由以上介绍可以看出,只有清楚了DelphiVCL中的消息处理机制,掌握好处理各种消息的方法和时机(必要时要借助各种工具,如winsight32,spy等),并结合OOP语言的特点,我们才可能编出高质量的构件。这当然要靠读者在实践中不断摸索,积累经验。

[上一页]      

 
如何在程序中关闭 Windows?
 
控制WINDOWS的开关:如关闭WINDOWS,重新启动WINDOWS等, ExitWindowsEx(UINT uFlags,DWORD dwReserved);是实现这一功能的API函数

首先定义常数
const
 EWX_FORCE=4; //关闭所有程序并以其他用户身份登录
 EWX_LOGOFF=0; //重新启动计算机并切换到MS-DOS方式
 EWX_REBOOT=2; //重新启动计算机
 EWX_SHUTDOWN=1;//关闭计算机

运行时给How赋值,让他等于EWX_SHUTDOWN或其他,调用以下语句

 ExitWindowsEx(How,0);

[上一页]      

 
如何来动态地改变屏幕的分辨率?
 
Windows 提供给我们两个 API 函数,可以动态调整显示器的分辨率,
他们是 EnumDisplaySettings() 和 ChangeDisplaySettings(),
下面这个例子就是了

function DynamicResolution(X,Y:Word):BOOL;
var
 lpDevMode:TDeviceMode;
begin
 Result:=EnumDisplaySettings(nil,0,lpDevMode);
 if Result then
 begin
  lpDevMode.dmFields:=DM_PELSWIDTH Or DM_PELSHEIGHT;
  lpDevMode.dmPelsWidth:=X;
  lpDevMode.dmPelsHeight:=Y;
  Result:=ChangeDisplaySettings(lpDevMode,0)=DISP_CHANGE_SUCCESSFUL; 
 end
end;

procedure TForm1.Button1Click(Sender:TObject);
begin
 if DynamicResolution(640,480) then
 ShowMessage('Now is 640*480');
end;

procedure TForm1.Button2Click(Sender:TObject);
begin
 if DynamicResolution(800,600) then
 ShowMessage('Now is 800*600');
end;

[上一页]      


版权所有 1997-1999 “五维网络2”由新天赋软件工作室制作
建议在 800*600 分辨率下,使用 Internet Explorer 浏览。