动态链接库编程(二)
|
源代码网整理以下10.3.2.2 服务器程序的编写 源代码网整理以下 服务器程序必须包含对DLL的调用代码,如: 软件开发网 www.mscto.com
源代码网整理以下function GetGlobalMem: THandle; far; external "c:dllsglbmem"; 软件开发网 www.mscto.com
源代码网整理以下 通过调用该函数,服务器可以获得全局内存块的句柄。 源代码网整理以下 在写入数据前,服务器必须锁定全局内存,以避免在写入过程中Windows移动该内存块的位置。 源代码网整理以下 函数GlobalLock锁定全局内存并返回指向该内存块的指针: 源代码网整理以下pMem := GlobalLock(hMem); 源代码网整理以下 对pMem的任何修改都会反映到全局内存块中。 源代码网整理以下 对内存块进行操作后,调用GlobalUnLock进行解锁。内存块操作之后尽早解锁,有利于Windows充分利用内存资源。 源代码网整理以下 服务器写入数据的实现代码如下。 源代码网整理以下var 源代码网整理以下hMem: THandle; 源代码网整理以下pMem: PChar; 源代码网整理以下begin 软件开发网 www.mscto.com 源代码网整理以下hMem := GetGlobalMem; {获得全局内存块的句柄} 源代码网整理以下if hMem <> 0 then 源代码网整理以下begin 源代码网整理以下pMem := GlobalLock(hMem); {加锁全局内存块} 源代码网整理以下if pMem <> nil then 源代码网整理以下begin 源代码网整理以下StrPCopy(pMem,Memo1.text); {向全局内存块写入数据} 软件开发网 www.mscto.com
源代码网整理以下GlobalUnlock(hMem); {解锁全局内存块} 源代码网整理以下end 源代码网整理以下else 源代码网整理以下MessageDlg("Couldnot Lock memory block",mtWarning,[mbOK],0); 源代码网整理以下end; 源代码网整理以下10.3.2.3 客户程序的编写 源代码网整理以下 客户程序几乎是服务器程序的翻版。唯一的区别在于一个是写入数据,一个是下载数据。 软件开发网 www.mscto.com 源代码网整理以下下面是客户从全局内存块下载数据的程序清单。 源代码网整理以下var 源代码网整理以下hMem: THandle; 源代码网整理以下pMem: PChar; 源代码网整理以下begin 源代码网整理以下hMem := GetGlobalMem; {获得全局内存块的句柄} 源代码网整理以下if hMem <> 0 then 源代码网整理以下begin 源代码网整理以下pMem := GlobalLock(hMem); {加锁全局内存块} 源代码网整理以下if pMem <> nil then 源代码网整理以下begin 源代码网整理以下Memo1.text := StrPas(pMem); {从全局内存块读取数据} 源代码网整理以下GlobalUnlock(hMem); {解锁全局内存块} 软件开发网 www.mscto.com 源代码网整理以下end 源代码网整理以下else 源代码网整理以下MessageDlg("Couldnot Lock memory block",mtWarning,[mbOK],0); 源代码网整理以下end; 源代码网整理以下10.4 利用DLLs实现窗体重用 源代码网整理以下 实现窗体重用是Delphi DLLs功能中一个引人注目的特色。当你创建了一个令自己满意的通用窗体并希望能在不同应用程序中使用,特别是希望能在非Delphi 应用程序中使用时,把窗体做进一个动态链接库中是最适当的。这样即使用其它工具开发的应用程序,如C 、Visual Basic等,也都可以去调用它。 源代码网整理以下 包含窗体的DLLs有100K左右的部件库(Component Library)开销。可以通过把几个窗体编译成一个DLLs来最小化这笔开销。DLl中的不同窗体可以共享部件库。 源代码网整理以下10.4.1 利用DLLs实现窗体重用的一般步骤 源代码网整理以下 利用DLLs实现窗体重用的步骤是: 源代码网整理以下 1.在集成开发环境(IDE)中,按自己的需要设计一个窗体; 源代码网整理以下 2.编写一个用于输出的函数或过程。在该函数或过程中,设计的窗体被实例化; 源代码网整理以下 3.重复步骤1、2,直到完成所有重用窗体的设计; 源代码网整理以下 4.打开工程文件,进行修改,以适应生成 .dll文件的需要: 源代码网整理以下 (1).把保留字program设为library; 源代码网整理以下 (2).从uses子句中去掉Forms单元; 源代码网整理以下 (3).移去begin,end之间的所有代码; 源代码网整理以下 (4).在uses子句下,begin…end块之前,添加保留字exprots。exports 后是输出函数名或过程名。 源代码网整理以下 5.编译生成DLLs文件; 源代码网整理以下 6.在其它应用程序中调用重用窗体。 源代码网整理以下 重用窗体的调用同一般DLLs函数或过程的调用完全一致,不再赘述。读者可参看下面的例子。 软件开发网 www.mscto.com软件开发网 www.mscto.com 软件开发网 www.mscto.com 源代码网整理以下10.4.2 窗体重用实例 源代码网整理以下 下面我们通过一个具体的实例来说明窗体重用的设计过程。我们在一个名为passform.dll 的文件中储存了一个口令设置窗口和一个口令检查窗口。而后在一个Delphi 编写的程序和一个VB编写的程序中进行调用。事实证明这种方法是完全可行的。 软件开发网 www.mscto.com源代码网整理以下10.4.2.1 窗体重用DLLs的设计 源代码网整理以下 窗体重用DLLs的设计依照(10.4.1)中介绍的步骤进行。DLLs中的两个窗体 SetPassWordForm和GetPassWordForm分别用于设置和检查口令。它们的设计界面如图所示。 源代码网整理以下窗体类TSetPassWordForm定义了两个数据成员Verified和PassWord,用于记录口令确认状态和设置的口令。TSetPassWordForm的定义如下: 源代码网整理以下type 源代码网整理以下TSetPassWordForm = class(TForm) 源代码网整理以下Label1: TLabel; 源代码网整理以下Edit1: TEdit; 源代码网整理以下OKBtn: TBitBtn; 源代码网整理以下CancelBtn: TBitBtn; 源代码网整理以下procedure FormCreate(Sender: TObject); 源代码网整理以下procedure Edit1KeyPress(Sender: TObject; var Key: Char); 源代码网整理以下private 源代码网整理以下{ Private declarations } 源代码网整理以下Verified: Boolean; 源代码网整理以下public 源代码网整理以下{ Public declarations } 源代码网整理以下PassWord: PChar; 源代码网整理以下end; 源代码网整理以下 窗口生成时,对数据成员和部件状态进行初始化: 源代码网整理以下procedure TSetPassWordForm.FormCreate(Sender: TObject); 源代码网整理以下begin 源代码网整理以下Verified := False; 源代码网整理以下PassWord := StrAlloc(40); 源代码网整理以下OKBtn.Enabled := False; 源代码网整理以下Label1.Caption := "Please Input PassWord:"; 源代码网整理以下end; 源代码网整理以下 按钮OKBtn在程序启动时Enabled属性设置为False,直到口令被正确设置后Enabled属性才恢复为True。这样就保证了只有口令被正确设置后,口令设置窗口才能正常关闭。否则只能按Cancel按钮取消。 源代码网整理以下 在口令设置代码单元中定义了一个输出函数SetPassWord,用于生成口令设置窗口并返回设置的口令: 源代码网整理以下function SetPassWord(PWord: PChar): Boolean; 软件开发网 www.mscto.com 源代码网整理以下var 源代码网整理以下SetPassWordForm: TSetPassWordForm; 软件开发网 www.mscto.com 源代码网整理以下begin 源代码网整理以下Result := False; 源代码网整理以下SetPassWordForm := TSetPassWordForm.Create(Application); 源代码网整理以下try 源代码网整理以下with SetPasswordForm do 源代码网整理以下if ShowModal = mrOK then 源代码网整理以下begin 源代码网整理以下StrCopy(PWord,StrUpper(Password)); 源代码网整理以下Result := True; 源代码网整理以下end; 源代码网整理以下finally 源代码网整理以下SetPasswordForm.Free; 源代码网整理以下end; 源代码网整理以下end; 源代码网整理以下 口令成功设置,把PassWord的值拷贝给PWord输出,并返回True。应该注意的是由于 PWord本身就是指针类型,指向一个字符串的地址,因而虽然PWord用于输出,但在参数表中仍为传值参数,而不是传址参数。另外调用函数StrCopy,要求PWord在传入前已分配内存,否则会导致一个一般保护错。try...finally用于保护窗口所占用内存资源在任何情况下都能正常释放,读者可参看第十二章。 源代码网整理以下 在口令设置窗口中,为了确保用户记住了设置的口令,在用户输入并按回车键后,要求用户再次输入进行确认。只有用户重新输入的字符串与原设置口令相同,口令设置窗口才能正常关闭 。否则将原设置口令清空,要求用户再次输入。以上功能的实现在编辑框的OnKeyPress事件处理过程中。 源代码网整理以下procedure TSetPassWordForm.Edit1KeyPress(Sender: TObject; var Key: Char); 源代码网整理以下begin 源代码网整理以下if Edit1.text = " then Exit; 源代码网整理以下if Key = #13 then 源代码网整理以下begin 源代码网整理以下if Verified then 源代码网整理以下if StrPas(PassWord) = Edit1.text then 源代码网整理以下begin 源代码网整理以下OKBtn.Enabled := True; 源代码网整理以下Edit1.Enabled := False; 源代码网整理以下OKBtn.SetFocus; 源代码网整理以下end 源代码网整理以下else 源代码网整理以下begin 源代码网整理以下Verified := False; 源代码网整理以下MessageDlg("PassWord is InValid.",mtWarning,[mbOK],0); 软件开发网 www.mscto.com 源代码网整理以下Edit1.text := "; 源代码网整理以下PassWord := "; 源代码网整理以下Label1.Caption := "Please Input PassWord:"; 软件开发网 www.mscto.com 源代码网整理以下end 源代码网整理以下else 源代码网整理以下begin 软件开发网 www.mscto.com 源代码网整理以下Verified := True; 源代码网整理以下StrPCopy(PassWord,Edit1.text); 源代码网整理以下Edit1.text := "; 源代码网整理以下Label1.caption := "Please Verify PassWord:"; 源代码网整理以下end;[page] 源代码网整理以下Key := #0; 源代码网整理以下end; 源代码网整理以下end; 源代码网整理以下 口令检查窗口的实现相对简单,只定义了一个输出函数GetPassWord,用于生成口令检查窗口并返回口令检查的结果。 源代码网整理以下function GetPassword(Password: PChar): Boolean; 源代码网整理以下var 源代码网整理以下GetPasswordForm: TGetPasswordForm; 软件开发网 www.mscto.com 源代码网整理以下begin 软件开发网 www.mscto.com 源代码网整理以下Result := False; 源代码网整理以下GetPasswordForm := TGetPasswordForm.Create(Application); 源代码网整理以下try 源代码网整理以下with GetPasswordForm do 源代码网整理以下if ShowModal = mrOK then 软件开发网 www.mscto.com 源代码网整理以下if UpperCase(Edit1.Text) <> StrPas(StrUpper(Password)) then 源代码网整理以下MessageDlg("Invalid Password", mtWarning, [mbOK], 0) 源代码网整理以下else 源代码网整理以下Result := True; 源代码网整理以下finally 源代码网整理以下PasswordForm.Free; 源代码网整理以下end; 源代码网整理以下end; 源代码网整理以下 PassWord为输入的参数,不能为空,由调用以上函数的程序负责维护。 源代码网整理以下 窗口中用户输入口令时回显在屏幕上的字符由编辑框的PassWordChar属性确定。 源代码网整理以下 在DLLs的工程文件中,把两个输出函数写到exports子句中。 源代码网整理以下library PassForm; 源代码网整理以下uses 软件开发网 www.mscto.com 源代码网整理以下GetPass in "GETPASS.PAS" {PasswordForm}, 源代码网整理以下Setpass in "SETPASS.PAS" {SetPassWordForm}; 软件开发网 www.mscto.com 源代码网整理以下exports 源代码网整理以下GetPassword,SetPassWord; 软件开发网 www.mscto.com 源代码网整理以下begin 源代码网整理以下end. 源代码网整理以下10.4.2.2 Delphi应用程序调用重用窗体 源代码网整理以下 在Delphi应用程序中调用重用窗体,首先必须包含passform.dll的两个输出函数: 源代码网整理以下function GetPassword(Password: PChar): Boolean; 源代码网整理以下far; external "c:dllsPassForm"; 源代码网整理以下function SetPassword(PassWord: PChar): Boolean; 源代码网整理以下far; external "c:dllsPassForm"; 源代码网整理以下 这位于程序单元的implementation部分。 源代码网整理以下口令设置部分的实现代码为: 源代码网整理以下procedure TForm1.SetButtonClick(Sender: TObject); 源代码网整理以下begin 源代码网整理以下PassWord := StrAlloc(40); 源代码网整理以下if SetPassWord(PassWord) = False then 软件开发网 www.mscto.com 源代码网整理以下MessageDlg("PassWord is not set",mtInformation,[mbOK],0); 源代码网整理以下end; 源代码网整理以下 首先为口令字符串分配内存。当口令设置窗体按Cancel按钮取消时,显示相应的信息。 源代码网整理以下 口令检查部分的实现代码为: 源代码网整理以下procedure TForm1.TestButtonClick(Sender: TObject); 源代码网整理以下begin 源代码网整理以下if PassWord = nil then 软件开发网 www.mscto.com 源代码网整理以下begin 源代码网整理以下MessageDlg("Set password first", mtInformation, [mbOK], 0); 软件开发网 www.mscto.com 源代码网整理以下SetButton.SetFocus; 源代码网整理以下Exit; 源代码网整理以下end; 源代码网整理以下if GetPassword(PassWord) then 源代码网整理以下Label1.Caption := "You are Wellcome !" 源代码网整理以下else 源代码网整理以下Label1.Caption := "Sorry,You are InValid User."; 源代码网整理以下end; 软件开发网 www.mscto.com 源代码网整理以下 根据口令检查的结果,在标签框中显示相应的信息。 源代码网整理以下10.4.2.3 VB应用程序调用重用窗体 源代码网整理以下 VB是微软公司极力推荐的一个可视化开发工具。它虽然并不支持动态链接库的创建,但可以调用标准的Windows API动态链接库和用其它语言编写的动态链接库。为了验证所生成DLLs的普适性,我们用VB开发了一个简单的程序来调用passform.dll中储存的窗体。 源代码网整理以下下面是VB程序的完整代码,和Delphi程序的对应部分基本一致。 源代码网整理以下Option Explicit 源代码网整理以下Declare Function GetPassWord Lib "c:dllspassform.dll" (ByVal PassWord As String) As Integer 源代码网整理以下Declare Function SetPassWord Lib "c:dllspassform.dll" (ByVal PassWord As String) As Integer 源代码网整理以下Dim PassWord As String * 40 源代码网整理以下Sub Check_Click () 源代码网整理以下If PassWord = "" Then 源代码网整理以下MsgBox ("Enter sample password first") 源代码网整理以下SetPass.SetFocus 源代码网整理以下Else 源代码网整理以下If GetPassWord(PassWord) Then 源代码网整理以下StatusLbl.Caption = "You are Welcome!" 源代码网整理以下Else 源代码网整理以下StatusLbl.Caption = "Sorry,You are Invalid User." 源代码网整理以下End If 源代码网整理以下End If 源代码网整理以下End Sub 源代码网整理以下Sub SetPass_Click () 源代码网整理以下If SetPassWord(PassWord) = 0 Then 源代码网整理以下MsgBox ("PassWord is not Set.") 源代码网整理以下End If 源代码网整理以下End Sub 源代码网整理以下 有关VB编程的一些具体问题,读者可参看有关的VB参考书。 源代码网整理以下10.4.3 小结 源代码网整理以下 本章我们讨论的是动态链接库编程。许多可视化开发工具(如Visual Basic)不支持 DLLs的创建,而Delphi在这里又有上乘的表现。特别是窗体重用机制是Delphi对Windows下DLLs编程的一个重大改进。在一般的DLLs编程中也体现了Delphi快捷、方便的特点。动态链接库是 Windows下程序组织的一种重要方式,使用动态链接库可以极大地保护用户在不同开发工具、不同时期所做的工作。利用动态链接库,用户可以逐步去构筑自己的程序模块库,为今后的工作积累素材。 软件开发网 www.mscto.com源代码网推荐 源代码网供稿. |
