• Dll学习一_Dll 创建并动态引用窗体且释放窗体Demo


    1、新建Dll工程

    2、Dll工程全部代码

    library SubMain;
    
    { 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, Forms,
      Classes, Windows, Dialogs,
      SubMain_Unit in 'SubMain_Unit.pas' {Frm_SubMain};
    
    var
      AppHnd: Thandle;//应用程序的句柄变量
      AppScr: TScreen;//应用程序的环境变量
    {$R *.res}
    
    procedure DllEntryPoint(dwReason: DWord);
    begin
    
      case dwReason of
        DLL_PROCESS_ATTACH:
        begin
          AppHnd := Application.Handle;//备份Exe句柄
          AppScr := Screen;//备份Exe环境
        end;
        DLL_THREAD_ATTACH: ShowMessage('Create Thread'); //Dll文件中最好用Messagebox,ShowMessage部分环境中容易抽风
        DLL_THREAD_DETACH: ShowMessage('Free Thread'); //Dll文件中最好用Messagebox,ShowMessage部分环境中容易抽风 
        DLL_PROCESS_DETACH:
        begin
          if Frm_SubMain <> nil then FreeAndNil(Frm_SubMain);//防止Dll窗体未释放干净
          Application.Handle := AppHnd;      //恢复Exe句柄
          Screen := AppScr;//恢复Exe环境
        end;
      end;
    end;
    
    exports
      CreateFrm,DropFrm;//输出函数接口
    
    begin
      DllProc := @DllEntryPoint;
      DllEntryPoint(DLL_PROCESS_ATTACH);
    end.

    3、SubMain_Unit.pas源码

    unit SubMain_Unit;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, FyFun_Unit;
    
    type
      TFrm_SubMain = class(TForm)
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure FormDestroy(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
      procedure CreateFrm(AppHnd: THandle);export;stdcall;//接口函数声明
      procedure DropFrm; export;stdcall;//接口函数声明
    var
      Frm_SubMain: TFrm_SubMain;
    
    implementation
    
    {$R *.dfm}
    procedure CreateFrm(AppHnd: THandle);//窗体创建函数
    begin
      Application.Handle := AppHnd;
    
      if not Assigned(Frm_SubMain) then
        Frm_SubMain := TFrm_SubMain.Create(Application);
    
      Frm_SubMain.Show;
    end;
    
    procedure DropFrm;//窗体释放函数
    begin
      if Frm_SubMain <> nil then
        FreeAndNil(Frm_SubMain);
    end;
    procedure TFrm_SubMain.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      Action := caFree;//dll窗体关闭自动释放
    end;
    
    procedure TFrm_SubMain.FormDestroy(Sender: TObject);
    begin
      Frm_SubMain := nil;//dll窗体关闭自动释放
    end;
    
    end.
    4、调用文件Main.pas代码

    unit Main_Unit;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TCreateFrm = procedure(AppHnd: THandle); stdcall;
      TDropFrm = procedure; stdcall;
      TFrm_Main = class(TForm)
        Btn_1: TButton;
        Btn_2: TButton;
        Btn_3: TButton;
        Btn_4: TButton;
        procedure Btn_1Click(Sender: TObject);
        procedure Btn_2Click(Sender: TObject);
        procedure Btn_3Click(Sender: TObject);
        procedure Btn_4Click(Sender: TObject);
      private
        LibHandle: THandle;
        FormRef: LongInt;
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      Frm_Main: TFrm_Main;
    
    implementation
    
    {$R *.dfm}
    
    procedure TFrm_Main.Btn_1Click(Sender: TObject);		//动态加载Dll文件
    begin
      if LibHandle = 0 then
      begin
        LibHandle := SafeLoadLibrary('SubMain.dll');
        if LibHandle = 0 then
          raise Exception.Create('Not Found Dll File')
        else
          ShowMessage('Dll Loaded');
      end;
    end;
    
    procedure TFrm_Main.Btn_2Click(Sender: TObject);		//释放Dll文件
    begin
      if LibHandle > 0 then
      begin
        FreeLibrary(LibHandle);
        LibHandle := 0;
        ShowMessage('Dll UnLoaded');
      end;
    end;
    
    procedure TFrm_Main.Btn_3Click(Sender: TObject);		//读取Dll文件窗体并显示
    var
      CreateFrm: TCreateFrm;
    begin
      if LibHandle = 0 then
        raise Exception.Create('Place Load Dll File First');
    
      @CreateFrm := GetProcAddress(LibHandle,PChar('CreateFrm'));
      if @CreateFrm = nil then
        raise Exception.Create('Function Error');
    
      CreateFrm(Application.Handle);
    end;
    
    procedure TFrm_Main.Btn_4Click(Sender: TObject);		//释放Dll窗体
    var
      DropFrm: TDropFrm;
    begin
      @DropFrm := GetProcAddress(LibHandle,PChar('DropFrm'));
      if @DropFrm = nil then
        raise Exception.Create('Function Error');
    
      DropFrm;
    end;
    
    end.



  • 相关阅读:
    scrapy下载图片第一波
    scrapy之防ban策略
    xml之dtd约束
    Java jdbc相关
    XSS获取cookie
    反射型XSS & DVWA
    MySQL数据库设计规范
    SQL Server 查询指定时间是一年当中的第几周
    js验证15位或18位身份证
    C# Process.Start()
  • 原文地址:https://www.cnblogs.com/jupt/p/3922938.html
Copyright © 2020-2023  润新知