第三方控件
1.InforPower4000
TwwDbLookupComboBox
主要属性:
LookupTable 下拉列表显示的数据源
LookupField 下拉列表中显示的字段
Selected 查询数据
动态库使用说明:
1.初始化及资源释放
DLL虽然在内存中只有一个副本,但是隶属于调用者不同的进程空间,如果企图初始化公共变量来达到多进程共享是不可行的,同时也要注意公共变
量改带来的冲突问题。
在Library 工程单元的 begin...end 部分进行dll的初始化工作。
假如想在dll结束时有对应代码,则可以利用dll自动创建的ExitProc过程变量,这是一个退出过程的指针。类似委托变量,因此建立一个自己的过程
,并将该过程的地址赋予给ExitProc,那么在动态库卸载的时候就会执行这部分代码,一般在这个方法中实现还原原有被改变的状态,如
Application;
另外,因为ExitProc是dll创建时就存在的,所以在begin...end 部分就应该进行此操作。同时建立一个临时指针变量用来保存ExitProc值,在自己
的退出过程中将ExitProc还原回来。这样做是为了进行自己的退出操作后,能完成缺省的DLL退出操作(与在重载的 Destroy方法中的Inherited意义
一样的,完成了自己的Destroy,还需要进行缺省的父类Destroy才完整)
Library MyDll;
uses
Sysutils,
Classes,
Forms;
var
oldExitProc:pointer; //公共变脸个,为保存最初的ExitProc指针,以便赋回值
oldApp:TApplication;
procedure MyExitProc;
begin
//与初始化对应的结束代码
ExitProc:=oldExitProc; //自己的退出过程记住将ExitProc赋回,其他需要赋回的也在这里操作
Application:=oldApp;
end;
procedure ShowForm(app:TApplication);
begin
application:=app;
if not Assigned(Form1) then
form1:=TForm1.Create(application);
form.show;
end;
exports
ShowForm;
begin
//保存初始值
oldApp:=Application;
ExitProc:=@MyExitProc;
end.
动态调用:
type
IMyInf=interface
procedure ShowForm(app:TApplication);stdcall;
end;
TMyProc=procedure(app:TApplication);stdcall; //这里的stdcall一定要保持与动态库一致
TMyImp=class(TInterfacedObject,IMyInf)
private
h:Cardinal;
FMyProc:TMyProc;
protected
public
constructor Create;
procedure ShowForm(app:TApplication);stdcall;
end;
inf:=TMyImp.Create;
inf.ShowForm(application);
inf:=nil;
第三种方法和ExitProc类似,在System单元中预定义了一个指针变量DllProc(该方法需要引用Windows 单元)。在使用DllProc 时,必须先写好一个
具有以下原型的程序:
Procedure DllHandler(dwReason:DWord);stdcall;
并在Library 的begin...end 之间,将这个DllHandler程序的地址赋值给DLLProc,这是就可以根据参数Reason 的值分别作出相应的处理。示例如下
:
Library MyDll;
procedure MyDllHandler(dwReason:DWord);
begin
case dwReason of
DLL_Process_ATTACH:
; //进程进入时
DLL_Process_Detach:
;//进程退出时
DLL_Thread_Attach:
; //线程进入时
DLL_Thread_Detach:
; //线程退出时
end;
end;
begin
//初始化代码
DllProc:=@MyDllHandler;
MyDllHandler(Dll_Process_Attach);
end;
可见,通过DLLProc在处理多进程时比ExitProc更强大和灵活。
Bytes数组与string 类型的转换
string
string=Ansistring =长字符串,理论上不受长度限制,但其实受限于最大寻址范围2的32次方=4GKb
变量str 名字是一个指针,指向位于堆内存的字符序列;字符序列起始于@str[1]
@Str[1] 偏移负16个字节的空间存储着字符串长度、引用计数等信息。字符序列以
null结束。
string[n]
string[n]=ShortString=短字符串,最多容纳255个字符,实际长度是字符串长度+1,
是Delphi 的简单类型。
Str[0]存储着字符的个数,第一个字符从Str[1]开始存放,不以null结束。
字节数组转string
var
buf:array[0..100] of byte;
str:string[32]; //仅仅开辟一个32个空间的内存,由于第1位没有用Setlength初始化,
导致长度不定
i:integer;
begin
for i:=50 to 81 do
buf[i]:=Ord('A')+i-50; //测试数据
SetLength(str,32);
Move(buf[50],str[1],length(str));
showMessage(str);
end;
其实就是用MOVE 函数把字节数组拷贝到字符数组中,拷贝过程中会自动完成字节码到
字符码的转换。
这里重新认识一下SetLength,SetLength 有2个功能:
1.对ShortString 类型进行设置长度(专门针对其第一位进行设置)
2.对动态数组进行设置
把buf 内容赋值给AnsiString
string 和 string[] 不一样,string 是一个动态数组,还没有分配空间,而
string[] 已经分配了空间,只不过str[0]处没有赋值,这时如果用Move的话,会
把Byte 数组中的数据拷贝到string空间中,而string[]还没有分配内存,肯定会
造成av错误。
var
buf:array[0..100] of byte;
str:string;
i:integer;
begin
for i:=50 to 81 do
buf[i-50]:=ord('A')+i-50;
setLength(str,32);
Move(buf[0],str[1],length(str));
showMessage(str);
end;
string 转为字节数组
var
buf:array[0..100] of byte;
str:string;
begin
str:='abcdefg';
move(str[1],buf[0],length(str));//注意,这里从str[1]开始赋值的
showMessageFmt('%.2d,%.2d,%.2d,%.2d',[buf[3],buf[2],buf[1],buf[0]]);
end;