您现在的位置: 捷凌网安 >> 编程语言 >> Delphi编程 >> 正文
Delphi的“动态窗体”技术实际应用

作者:佚名 责任编辑:左决 点击数: 更新时间:2008-2-16 5:51:30

var
list:TStrings;
FirstLine:String;
iPos : Integer;
Form : TForm;
begin
Result := nil;
if FileExists(FileName)=False then
ExIT;
Form := TForm.Create(Application);
list := TStringList.Create;
try
list.LoadFromFile(FileName);
if list.Count=0 then
ExIT;
FirstLine := list[0];
iPos := Pos(': ',FirstLine);
if iPos = 0 then //找不到': ',格式不对
ExIT;
list[0]:=Copy(FirstLine,1,iPos)+' TForm';
DeleteErrorLines(list);
StringToComponent(list.Text,Form);
Result := Form;
except
Form.Free;
Result := nil;
end;
list.Free;
end;
原理就是读入DFM文件后把窗体的类别偷换成Tform。其中还有一个函数:
procedure DeleteErrorLines(list:TStrings);
var
i:Integer;
line:String;
begin
if list.Count=0 then
ExIT;

i:=0;
while i<list.Count do
begin
line := Trim(list[i]);
if Copy(line,1,2)='On' then
list.Delete(i)
else
Inc(i);
end;
end;
这个函数是把凡是含有“On”开头的行删除,应为在Delphi中,所有控件的事件都是以“On”开头,删除了这样的行,就能保证StringToComponent(list.Text,Form);不出错,用以上的两个函数就可以写一个DFM窗体察看器了,到目前为止,我还没有搜到哪个人发布了DFM窗体察看器。这样我们就完成了第2个要求。


实际应用中,一个窗体几乎肯定会有事件处理函数,所以我们要达成第1个要求。我这儿提供了两个方案,各有优缺点:
方案一:
程序员在开发时,在窗体的FormCreate(…)中,用LoadTextForm(…)生成窗体文件,然后把窗体上的控件全部移到本窗体上,最后查找窗体上的控件,动态设置事件处理函数。这个方法要求有一套好的控件命名规则,而且开发比较烦琐,享受不到Delphi的IDE所见即所得,自动生成事件关联代码的好处了。不过对Form文件的制作人员限制很小,他们可以直接用Delphi来制作窗体。
方案二:
用这个函数
procedure ReadForm(aFrom : TComponent;aFileName :string='');
var
FrmStrings : TStrings;
begin
RegisterClass(TPersistentClass(aFrom.ClassType));
FrmStrings:=TStringlist.Create ;
try
if trim(aFileName)='' then FrmStrings.LoadFromFile( gsPathInfo+'\'+aFrom.Name+'.txt')
else FrmStrings.LoadFromFile(aFileName);
while aFrom.ComponentCount>0 do aFrom.Components[0].Destroy ;
aFrom:=StringToComponent(FrmStrings.Text,aFrom)
finally
FrmStrings.Free;
end;
UnRegisterClass(TPersistentClass(aFrom.ClassType));
end;
在FormCreate中调用ReadForm(self,…)。
这个方案没有第一个方案的限制,但是要求开发人员必须先完成一个完整的Form文件交给Form文件制作人员, Form文件的制作人员不能修改控件的name,不能添加或删除控件,而且必须保留开发人员给定所有事件处理函数,不能修改函数名。不过很多问题可以写一个Form编辑器来保证不出问题。
具体代码就不写了。
我想,肯定还有跟好的方案来解决动态窗体的问题,希望大家讨论。
(以上代码使用Delphi6编写)
最后,我给出一个我实际项目中的有关动态窗体的函数的UnIT
{*****************************************
模块编号:J001DfmFunc
模块名称:Dfm窗体函数集单元
作者:刘爱军
建立日期:2002年12月2日
最后修改日期:
说明:本UnIT包含了一些函数,用于根据Delphi窗体文件格式的文件动态创建窗体
*******************************************}

unIT J001DfmFunc;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, DBCtrls, Grids, DBGrids, Buttons, StdCtrls,
ComCtrls,dbcgrids, buttonComps,Tabs,QryGlobal;

type
TAllComponentClass = Array of TPersistentClass;

procedure InITClassType(ClassArray:TAllComponentClass);

function ComponentToString(Component: TComponent): string;
function StringToComponent(Value: string; Instance:TComponent): TComponent;
procedure RegisterAllClasses(aAllCmpClass:TAllComponentClass);
procedure UnRegisterAllClasses(aAllCmpClass:TAllComponentClass);
function GetObjectString(list:TStrings;BegLine:Integer=0;TypeString:string=''):string;
function LoadTextForm(FileName:String):TForm;
function LoadTextForm2(FileName:String;out ErrMsg:string):TForm;
procedure DeleteErrorLines(list:TStrings);
procedure ReadForm(aFrom : TComponent;aFileName :string='');
const
RegisteredCompoentClassCount = 32;//数组大小

var
AllCmpClass : TAllComponentClass; //存放控件类

implementation

//初始化可以解析的类,可随需要增加
procedure InITClassType(ClassArray:TAllComponentClass);
begin
SetLength(AllCmpClass,RegisteredCompoentClassCount);
AllCmpClass[0] := TForm;
AllCmpClass[1] := TGroupBox;
AllCmpClass[2] := TPanel;
AllCmpClass[3] := TScrollBox;
AllCmpClass[4] := TLabel;
AllCmpClass[5] := TButton;
AllCmpClass[6] := TBITBtn;
AllCmpClass[7] := TSpeedButton;
AllCmpClass[8] := TStringGrid;
AllCmpClass[9] := TImage;
AllCmpClass[10] := TBevel;
AllCmpClass[11] := TStaticText;
AllCmpClass[12] := TTabControl;
AllCmpClass[13] := TPageControl;
AllCmpClass[14] := TTabSheet;
AllCmpClass[15] := TDBNavigator;
AllCmpClass[16] := TDBText;
AllCmpClass[17] := TDBEdIT;
AllCmpClass[18] := TDBMemo;
AllCmpClass[19] := TDBGrid;
AllCmpClass[20] := TDBCtrlGrid;
AllCmpClass[21] := TMemo;
AllCmpClass[22] := TSplITter;
AllCmpClass[23] := TCheckBox;
AllCmpClass[24] := TEdIT;
AllCmpClass[25] := TListBox;
AllCmpClass[26] := TComboBox;
AllCmpClass[27] := TDateTimePicker;
AllCmpClass[28] := TImageButton;
AllCmpClass[29] := TTabSet;
AllCmpClass[30] := TTreeView;
AllCmpClass[31] := TListView;

end;

procedure RegisterAllClasses(aAllCmpClass:TAllComponentClass);
var
i:Integer;
begin
for i:=0 to RegisteredCompoentClassCount-1 do
RegisterClass(aAllCmpClass[i]);
end;

procedure UnRegisterAllClasses(aAllCmpClass:TAllComponentClass);
var
i:Integer;
begin
for i:=0 to RegisteredCompoentClassCount-1 do
UnRegisterClass(aAllCmpClass[i]);
end;

function ComponentToString(Component: TComponent): string;
var
BinStream:TMemoryStream;
StrStream: TStringStream;
s: string;
begin
BinStream := TMemoryStream.Create;
try
StrStream := TStringStream.Create(s);
try
BinStream.WrITeComponent(Component);
BinStream.Seek(0, soFromBeginning);
ObjectBinaryToText(BinStream, StrStream);
StrStream.Seek(0, soFromBeginning);
Result:= StrStream.DataString;
finally
StrStream.Free;

end;
finally
BinStream.Free
end;
end;

function StringToComponent(Value: string; Instance:TComponent): TComponent;
var
StrStream:TStringStream;
BinStream: TMemoryStream;
begin
StrStream := TStringStream.Create(Value);
try
BinStream := TMemoryStream.Create;
try
ObjectTextToBinary(StrStream, BinStream);
BinStream.Seek(0, soFromBeginning);
Result := BinStream.ReadComponent(Instance);

finally
BinStream.Free;
end;
finally
StrStream.Free;
end;
end;

function GetObjectString(list:TStrings;BegLine:Integer=0;TypeString:string=''):string;

上一页  [1] [2] [3] 下一页

  • 上一篇文章:

  • 下一篇文章:
  •  
    最进更新
    普通文章VC++设计超强仿QQ自动伸缩窗04-17
    推荐文章基于HOOK和MMF的Win密码渗透04-17
    推荐文章几种VC++数据库开发技术的相04-17
    普通文章多线程、Socket技术及委托技04-11
    推荐文章VB.Net连接各种数据库的几种04-11
    普通文章VB.NET中的多窗体编程:升级04-11
    普通文章用VB.NET定制Windows控件04-11
    普通文章VB.NET中监视文件夹的变化04-11
    普通文章VB.NET中对象的克隆04-11
    推荐文章VB.NET中的TextBox控件详解04-11
     
    推荐文章
    推荐文章基于HOOK和MMF的Win密码渗透04-17
    推荐文章几种VC++数据库开发技术的相04-17
    推荐文章VB.Net连接各种数据库的几种04-11
    推荐文章VB.NET中的TextBox控件详解04-11
    推荐文章在VB.NET中进行抓屏04-11
    推荐文章VB.Net开发的长内容自动分页04-11
    推荐文章VB.NET中快速访问注册表技巧04-11
    推荐文章PHP5手动最简安装方法03-07
    推荐文章完全讲解PHP+MySQL的分页显示03-07
    推荐文章Linux Shell元字符知识笔记02-21
     
    热点文章 
    普通文章VC++设计超强仿QQ自动伸缩窗04-17
    推荐文章基于HOOK和MMF的Win密码渗透04-17
    推荐文章几种VC++数据库开发技术的相04-17
    普通文章VB.NET中的多窗体编程:升级04-11
    普通文章用VB.NET定制Windows控件04-11
    普通文章VB.NET中对象的克隆04-11
    推荐文章VB.NET中的TextBox控件详解04-11
    普通文章VB/VB.NET/C#导出到Excel的方04-11
    普通文章如何通过VB.NET获取网卡地址04-11
    普通文章VB.NET中使用ListView控件的04-11

    | 设为首页 | 加入收藏 | 联系站长 | 广告服务 | 友情链接 | 版权申明 | 网站地图 |

    在线交流 捷凌网安主群:51649627
    Copyright 2007-2008 © 捷凌网安. All rights reserved.
    备案序号:蜀ICP备08001812号