DLL 應用 - 設計可抽換的模組(4)
2008-04-09 04:28:15来源:互联网 阅读 ()
我交替使用了「建立物件」與「實體化」兩種詞彙,其實它們指的是同一件事情:建立某個類別的實體(instance)。
此技巧對於團隊開發也有好處,你只要公佈 TPlugin 和 TBaseForm 兩個單元,然後告訴組員照下面兩個步驟做就行了:
- 從 TBaseForm 衍生一個新類別(可以利用 Delphi 的物件寶庫來簡化這項工作)。
- 在這個新類別的單元的 Uses 子句裡加入 TPlugin 類別所屬的單元,並且在初始化階段把類別名稱指定給 g_ConcreteClass 變數。
在這個範例裡面,我們只有一個 TBaseForm 的後代,叫做 TForm1,因此在 TForm1 的單元裡面會有這一段:
uses DllExport; // TPlugin 類別實作放在這個單元裡面 ..... initialization g_ConcreteClass := TForm1;
TPlugin.Destroy
解構函式會呼叫 DestroyForm 使 Form 物件一併釋放掉,並且還原 DLL 的 application handle:
destructor TPlugin.Destroy; begin DestroyForm; Application.Handle := g_DllAppHandle; inherited Destroy; end;
其中 g_DllAppHandle 是一個全域變數,其宣告如下:
var g_DllAppHandle: THandle;
而我們必須在 DLL 初始化的時候將 DLL 本身的 application handle 保存起來:
initialization g_DllAppHandle := Application.Handle;
其實如果 DLL 專案有用 "Build with runtime package" 選項的話,這個保存及還原 application handle 的動作就可以免了。相反地,若不加上保存及還原的動作,而且 DLL 專案不使用 "Build with runtime package" 選項的話,當 DLL 被釋放時就會發生主視窗也被一併關閉的怪異情形。
擅用原始的力量
到此重要的部分應該都已經提到了,您可能會發現我並沒有對 TBaseForm 多做說明,原因是在這個範例程式中 TBaseForm 並沒有什麼特別之處,只是為日後擴充時預留的一個基礎類別,你也許會想要將各個模組共用的功能和視覺化介面集中在此類別以簡化各模組的撰寫工作,以及讓應用程式有一致的操作方式和行為,這部分每個人的需求不同,就請您自行發揮了。
如果你覺得以上的程式碼過於片段零散,無法獲得整體的概念,建議您直接看範例的原始碼,把範例程式執行一遍以觀察程式運作的過程,不了解的地方再回來文件裡尋找解釋,這樣也許會比較容易些。為了方便閱讀,我也把範例程式中比較重要的兩個單元分別列在表一和表二裡面了。
列表一. DllUtils.pasunit DllUtils;
interface
uses
Windows, Messages, SysUtils, Classes, Forms, Controls;
type
IPlugin = interface
[''''{D3F4445A-C704-42BC-8283-822541668919}'''']
function CreateForm(hMainForm: THandle): THandle;
procedure DestroyForm;
function ShowModalForm: Integer;
end;
TCreatePluginFunc = function (hApp: THandle): IPlugin; stdcall;
function DllCreatePlugin(hLib, hApp: THandle): IPlugin;
implementation
resourcestring
sErrorLoadingDLL = ''''無法載入模組!'''';
sErrorDllProc = ''''無法呼叫 DLL 函式: %s'''';
const
SDllCreatePluginFuncName = ''''CreatePlugin'''';
function DllCreatePlugin(hLib, hApp: THandle): IPlugin;
var
pProc: TFarProc;
CreatePluginFunc: TCreatePluginFunc;
begin
Result := nil;
if hLib = 0 then
Exit;
pProc := GetProcAddress(hLib, PChar(SDllCreatePluginFuncName));
if pProc = nil then
raise Exception.CreateFmt(sErrorDllProc, [SDllCreatePluginFuncName]);
CreatePluginFunc := TCreatePluginFunc(pProc);
Result := CreatePluginFunc(hApp);
end;
end.
列表二. DllExport.pas
unit DllExport;
interface
uses Windows, Classes, Forms, DllUtils, BaseFrm;
type
// Inherited from TInterfacedObject to be reference-counted.
TPlugin = class(TInterfacedObject, IPlugin)
private
FForm: TBaseForm;
public
destructor Destroy; override;
function CreateForm(hMainForm: THandle): THandle;
procedure DestroyForm;
function ShowModalForm: Integer;
end;
function CreatePlugin(hApp: THandle): IPlugin; export; stdcall;
exports
CreatePlugin;
var
g_ConcreteClass: TBaseFormClass := nil;
g_PluginIntf: IPlugin = nil;
g_DllAppHandle: THandle;
implementation
uses Dialogs, SysUtils;
function CreatePlugin(hApp: THandle): IPlugin;
begin
if hApp <> 0 then
Application.Handle := hApp; // Sync Application handle.
if g_PluginIntf = nil then
g_PluginIntf := TPlugin.Create;
Result := g_PluginIntf;
end;
{ TPlugin }
destructor TPlugin.Destroy;
begin
DestroyForm;
Application.Handle := g_DllAppHandle;
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
相关文章
IDC资讯:
主机资讯
注册资讯
托管资讯
vps资讯
网站建设
网站运营:
建站经验
策划盈利
搜索优化
网站推广
免费资源
网络编程:
Asp.Net编程
Asp编程
Php编程
Xml编程
Access
Mssql
Mysql
其它
服务器技术:
Web服务器
Ftp服务器
Mail服务器
Dns服务器
安全防护
软件技巧:
其它软件
Word
Excel
Powerpoint
Ghost
Vista
QQ空间
QQ
FlashGet
迅雷
网页制作:
FrontPages
Dreamweaver
Javascript
css
photoshop
fireworks
Flash
热门词条
最新资讯
热门关注
