网站首页/技术开发列表/内容

第10章 动态链接库编程(二)

技术开发2022-07-12阅读
10.3.2.2 服务器程序的编写 

  服务器程序必须包含对DLL的调用代码,如: 

  function GetGlobalMem: THandle; far; external 'c:\dlls\glbmem';

  通过调用该函数,服务器可以获得全局内存块的句柄。

  在写入数据前,服务器必须锁定全局内存,以避免在写入过程中Windows移动该内存块的位置。

  函数GlobalLock锁定全局内存并返回指向该内存块的指针: 

  pMem := GlobalLock(hMem);

  对pMem的任何修改都会反映到全局内存块中。

  对内存块进行操作后,调用GlobalUnLock进行解锁。内存块操作之后尽早解锁,有利于Windows充分利用内存资源。

  服务器写入数据的实现代码如下。 

  var

  hMem: THandle;

  pMem: PChar;

  begin

  hMem := GetGlobalMem; {获得全局内存块的句柄}

  if hMem <> 0 then

  begin

  pMem := GlobalLock(hMem); {加锁全局内存块}

  if pMem <> nil then

  begin

  StrPCopy(pMem,Memo1.text); {向全局内存块写入数据}

  GlobalUnlock(hMem); {解锁全局内存块}

  end

  else

  MessageDlg('Couldnot Lock memory block',mtWarning,[mbOK],0);

  end; 

  10.3.2.3 客户程序的编写 

  客户程序几乎是服务器程序的翻版。唯一的区别在于一个是写入数据,一个是下载数据。

  下面是客户从全局内存块下载数据的程序清单。 

  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); {解锁全局内存块}

  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函数或过程的调用完全一致,不再赘述。读者可参看下面的例子。 

  10.4.2 窗体重用实例 

  下面我们通过一个具体的实例来说明窗体重用的设计过程。我们在一个名为passform.dll 的文件中储存了一个口令设置窗口和一个口令检查窗口。而后在一个Delphi 编写的程序和一个VB编写的程序中进行调用。事实证明这种方法是完全可行的。

  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;

  var

  SetPassWordForm: TSetPassWordForm;

  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用于保护窗口所占用内存资源在任何情况下都能正常释放,读者可参看第十二章。

[1] [2]  下一页

……

相关阅读