zoukankan      html  css  js  c++  java
  • delphi中dll综合运用的例子(动态加载插件)

    1,新建dll客户端模块
    ---------------dll工程文件PlugIns.dll-------------------------------
    library PlugIns;

    { Important note about DLL memory management: ShareMem must be the
    first unit in your library's USES clause AND your project's (select
    Project-View Source) USES clause if your DLL exports any procedures or
    functions that pass strings as parameters or function results. This
    applies to all strings passed to and from your DLL--even those that
    are nested in records and classes. ShareMem is the interface unit to
    the BORLNDMM.DLL shared memory manager, which must be deployed along
    with your DLL. To avoid using BORLNDMM.DLL, pass string information
    using PChar or ShortString parameters. }

    uses
    SysUtils,
    Classes,
    PlugInFrm in 'PlugInFrm.pas' {FrmPlugIns};

    {$R *.res}

    //输出接口函数
    exports
    ShowDLLForm,GetCaption;

    begin
    end.

    -------------新建模块PlugInFrm.pas的窗体文件---------------
    unit PlugInFrm;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;

    type
    TFrmPlugIns = class(TForm)
        Label1: TLabel;
    private
        { Private declarations }
    public
        { Public declarations }
    end;

    //定义ShowDLLForm,用于打开本窗体
    function ShowDLLForm(AHandle: THandle; ACaption: string): Boolean; Stdcall;

    //输出标题
    function GetCaption: Pchar; stdcall;

    implementation

    {$R *.dfm}

    //输出标题
    function GetCaption: Pchar; stdcall;
    begin
    Result := '插件演示NO1';
    end;

    //打开本窗体
    function ShowDLLForm(AHandle: THandle; ACaption: string): Boolean;
    var
    DLL_Form: TfrmPlugins;
    begin
    result := true;
    try
        application.Handle := AHandle; //传递应用程序地址
        DLL_Form := TFrmPlugins.Create(Application);//创建窗体
        try
          DLL_Form.caption := Acaption;//给窗体标题赋值
          DLL_Form.ShowModal; //模式显示窗体
        finally
          DLL_Form.Free;
        end;
    except
        result := false;
    end;
    end;

    end.

    2,新建工程主模块

    -------------------新建主窗体文件MainFrm.pas--------------
    unit MainFrm;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, Menus;

    type
    TFrmMain = class(TForm)
        MainMenu1: TMainMenu;
        N1: TMenuItem;
        N2: TMenuItem;
        N_Plugins: TMenuItem;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
    private
        { Private declarations }
        FForm: TForm;
        procedure LoadPlugIns; //初始化插件 ,也就装载插件,并在菜单提供调用
        procedure PlugInsClick(Sender: TObject); //插件菜单点击事件
        procedure FreePlugIns; //释放插件
    public
        { Public declarations }
    end;

    var
    FrmMain: TFrmMain;

    implementation

    {$R *.dfm}

    type
    //定义接口函数类型
    TShowDLLForm = function(AHandle: THandle; ACaption: string): Boolean; Stdcall;
    TGetCaption = function: Pchar; StdCall;

    EDLLLoadError = class(Exception);
    //定义TTestPlugIn类,存放caption,Address,call等信息
    TTestPlugIn = class
        Caption: string;//存取加载后,GetCaption返回的标题
        Address: THandle; //存取加载DLL的句柄
        Call: Pointer; //存取ShowDLLForm函数句柄
    end;

    var
    ShowDllForm: TShowDllForm; //声明接口函数类型
    Plugins: TList; //存放每一个DLL加载后的相关信息
    StopSearch: Boolean;

    //查找文件,并存于Files中
    procedure SearchFileExt(const Dir, Ext: string; Files: TStrings);
    var
    Found: TSearchRec;
    Sub: string;
    i: Integer;
    Dirs: TStrings;
    Finished: Integer;
    begin
    StopSearch := False;
    Dirs := TStringList.Create;
    Finished := FindFirst(Dir + '*.*', 63, Found);
    while (Finished = 0) and not (StopSearch) do
    begin
        if (Found.Name[1] <> '.') then
        begin
          if (Found.Attr and faDirectory = faDirectory) then
            Dirs.Add(Dir + Found.Name) //Add to the directories list.
          else
            if Pos(UpperCase(Ext), UpperCase(Found.Name)) > 0 then
              Files.Add(Dir + Found.Name);
        end;
        Finished := FindNext(Found);
    end;
    FindClose(Found);
    if not StopSearch then
        for i := 0 to Dirs.Count - 1 do
          SearchFileExt(Dirs[i], Ext, Files);
    Dirs.Free;
    end;

    //初始化插件 ,也就装载插件,并在菜单提供调用
    procedure TfrmMain.LoadPlugIns;
    var
    Files: TStrings;
    i: Integer;
    TestPlugIn: TTestPlugIn;
    NewMenu: TMenuItem;
    GetCaption: TGetCaption;
    begin
    Files := TStringList.Create;
    Plugins := TList.Create;
    //查找指定目录下的.dll文件,并存于Files对象中
    SearchFileExt(ExtractFilepath(Application.Exename), '.dll', Files);
    //加载查找到的DLL
    for i := 0 to Files.Count - 1 do
    begin
        TestPlugIn := TTestPlugIn.Create;
        TestPlugIn.Address := LoadLibrary(PChar(Files[i]));
        if TestPlugIn.Address = 0 then
          raise EDLLLoadError.Create('装载' + PChar(Files[i]) + '失败');
        try
          @GetCaption := GetProcAddress(TestPlugIn.Address, 'GetCaption');
          TestPlugIn.Caption := GetCaption;
          TestPlugIn.Call := GetProcAddress(TestPlugIn.Address, 'ShowDLLForm');
          PlugIns.Add(TestPlugIn);
          //创建菜单,并将菜单标题,Onclick事件赋值
          NewMenu := TMenuItem.Create(Self);
          NewMenu.Caption := TestPlugIn.Caption;
          NewMenu.OnClick := PlugInsClick;
          NewMenu.Tag := i;
          N_plugins.Add(NewMenu); //每次在菜单下新增一个模块菜单
        except
          raise EDLLLoadError.Create('初始化失败');
        end;
    end;
    Files.Free;
    end;

    //插件菜单点击事件
    procedure TfrmMain.PlugInsClick(Sender: TObject);
    begin
    //根据菜单的tag属性对应函数调用的地址
    @showDllForm := TTestPlugIn(PlugIns[TMenuItem(Sender).Tag]).Call;
    //执行showDllForm函数
    if not showDllForm(application.Handle, TTestPlugIn(PlugIns[TMenuItem(Sender).Tag]).caption) then
        showmessage('打开窗体错误');
    end;

    //释放插件
    procedure TfrmMain.FreePlugIns;
    var
    i: Integer;
    begin
    //将加载的插件全部释放
    for i := 0 to PlugIns.Count - 1 do
    begin
        FreeLibrary(TTestPlugIn(PlugIns[i]).Address);
    end;
    //释放plugIns对象
    PlugIns.Free;
    end;

    procedure TfrmMain.FormCreate(Sender: TObject);
    begin
    LoadPlugIns;
    end;

    procedure TfrmMain.FormDestroy(Sender: TObject);
    begin
    FreePlugins;
    end;


    end.
    -------------------------end-----------------------

    每天早上敲醒自己的不是闹钟,是夢想!
  • 相关阅读:
    Taobao OpenERP Connector 简要说明
    OpenERP 搜索过滤: 过去三个月
    openerp编辑与非编辑下隐藏按钮的方法
    javascript入门系列演示·三种弹出对话框的用法实例
    Linux Ubuntu 开机自动启动项设置方法 例:svn服务
    Linux下SVN(Subversion)自动启动脚本
    PgSql备份pg_dump与还原手记pg_restore(转)可以直接跳转至最后面的示例进行查看
    windows下cmd命令行显示UTF8字符设置(CHCP命令)
    Python一些特殊用法(map、reduce、filter、lambda、列表推导式等)
    Linux的fuser命令解析
  • 原文地址:https://www.cnblogs.com/yplong/p/2344810.html
Copyright © 2011-2022 走看看