主程序运行之后,自动发现一个自定义后缀名的文件,然后自动导入到程序,请问各位高手会不会

解决方案 »

  1.   

    如果是插件,那就是动态调入动态链接库的问题。。
    1) LoadLibrary
    函数L o a d L i b r a r y将D L L动态地装入内存。原型如下:
    H I N S TANCE LoadLibrary(
    LPCTSTR lpLibFileName // 指定模块所在的文件名
    ) ;
    2) GetProcAddress
    函数G e t P r o c A d d r e s s获取D L L中指定模块的地址。原型如下:
    FARPROC GetProcAddress(
    HMODULE hModule, // DLL模块的句柄
    LPCSTR lpProcName // 函数名称
    ) ;
    3) FreeLibrary
    函数F r e e L i b r a r y动态地卸载动态链接库,并释放资源。原型如下:
    BOOL FreeLibrary(
    HMODULE hLibModule // DLL模块的句柄
    ) ;
      

  2.   

    //用来测试插件的主窗体unit frmMain;interfaceuses
      Sharemem,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Menus;const cPLUGIN_MASK='*.wd';  cPLUGIN_DESCRIBE='DescribePlugin'; cPLUGIN_INIT = 'InitPlugin';//定义插件的描述信息和后缀名
    type
      TPluginDescribe = procedure(var Desc: string); stdcall;
      TPluginInit = procedure(ParentMenu: TMainMenu); stdcall;
      TForm1 = class(TForm)
        memPlugins: TMemo;
        mnuMain: TMainMenu;
        file1: TMenuItem;
        plus1: TMenuItem;
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public    procedure LoadPlugins;
        procedure LoadPlugin(sr: TSearchRec);
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.LoadPlugin(sr: TSearchRec);//将插件的动态库读入
    var
      Description: string;    LibHandle: Integer;  DescribeProc: TPluginDescribe;
      InitProc: TPluginInit;
    begin
      LibHandle := LoadLibrary(Pchar(sr.Name));
      if LibHandle <> 0 then
      begin
         // 查找 DescribePlugin.
         DescribeProc := GetProcAddress(LibHandle,
         cPLUGIN_DESCRIBE);
         if Assigned(DescribeProc) then
         begin
           // 调用 DescribePlugin.
           DescribeProc(Description);
            memPlugins.Lines.Add(Description);
            // 查找 InitPlugin.
           InitProc := GetProcAddress(LibHandle, 'InitPlugin');
           if Assigned(InitProc) then
           begin
              // 调用 InitPlugin.
               InitProc(mnuMain);
           end;
          end else begin
      MessageDlg('File "' + sr.Name +
      '" is not a valid plugin.',
      mtInformation, [mbOK], 0);
      end;
      end
      else
      begin
      MessageDlg('An error occurred loading the plugin "' +
      sr.Name + '".', mtInformation, [mbOK], 0);
      end;
    end;
    procedure TForm1.LoadPlugins;//查找插件
    var
      sr: TSearchRec;
      path: string;
      Found: Integer;
    begin
      path := ExtractFilePath(Application.Exename);
      try
      Found := FindFirst(path + cPLUGIN_MASK, 0, sr);
      while Found = 0 do begin
      LoadPlugin(sr);
      Found := FindNext(sr);
      end;
      finally
      FindClose(sr);
      end;
    end;
    procedure TForm1.FormCreate(Sender: TObject);
    begin
       LoadPlugins;
    end;end.//插件的实现,新建一个DLL工程,工程代码入下
    library Pplus2;{ 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
      Sharemem,//这里一定要加上
      SysUtils,
      Classes,
      plus2 in 'plus2.pas';{$E wd}{$R *.res}exports
       DescribePlugin,InitPlugin;//导出函数begin
    end.
    //然后添加一个空白的文件,里面是插件的具体代码
    unit plus2;
     
    interfaceuses Dialogs, Menus,Classes;
     
    type
      THolder = class
      public
      procedure ClickHandler(Sender: TObject);
      end;
     
      procedure DescribePlugin(var Desc: string);
      export; stdcall;
      procedure InitPlugin(ParentMenu: TMainMenu);
      export; stdcall;
     
    var
      Holder: THolder;
    implementation
     
    procedure DescribePlugin(var Desc: string);
    begin
      Desc := 'Test plugin 2 - Menu test';
    end;
     
    procedure InitPlugin(ParentMenu: TMainMenu);
    var
      i: TMenuItem;
    begin
      // 创建新菜单项.
     { NewItem('New item', TextToShortCut('Ctrl+N'),
                False, True, Action1.OnExecute, 0, 'Item1')  }
      i := NewItem('Plugin &Test', scNone, False, True,Holder.ClickHandler, 0, 'mnuTest');
      ParentMenu.Items[1].Add(i);
    end;
     
    procedure THolder.ClickHandler;
    begin
      ShowMessage('插件测试!');
    end;
     
    initialization
      Holder := THolder.Create;
     
    finalization
      Holder.Free;
     
    end.
    这个差价就是返回一个描述插件信息,以及在主窗体上增加一个菜单
      

  3.   

    上述例子中插件通过LoadPlugins过程载入到这个测试外壳中,这个过程在主窗口的FormCreate事件中调用,该过程使用FindFirst和FindNext函数在应用程序所在目录中查找插件文件。找到一个文件以后,就使用LoadPlugins过程将其载入。LoadPlugin方法展示了插件机制的核心。首先,插件被写成DLL。其次,通过LoadLibrary API它被动态的加载。一旦DLL被加载,我们就需要一个访问它所包含的过程和函数的途径。API调用GetProcAddress提供这种机制,它返回一个指向所需例程的指针。在上面的例子中,插件仅仅包含一个名为DescribePlugin的过程和一个InitPlugin的过程,由常数cPLUGIN_DESCRIBE以及cPLUGIN_INIT指定(过程名的大小写非常重要,传递到GetProcAddress的名称必须与包含在DLL中的例程名称完全一致)。如果在DLL中没有找到请求的例程,GetProcAddree将返回nil,这样就允许使用Assigned函数测定返回值。
      为了以一种易用的方式存储指向一个函数的指针,有必要为用到的变量创建一个特定的类型。注意,GetProcAddress的返回值被存储在一个变量中,DescribeProc,属于TpluginDescribe类型。下面是它的声明:
    type
      TPluginDescribe = procedure(var Desc: string); stdcall;
    以及PluginInit,类型声明如下:
    TPluginInit = procedure(ParentMenu: TMainMenu); stdcall;
      由于过程存在于DLL内部,它通过标准调用转换编译所有导出例程,因此需要使用stdcall指示字。这个过程使用一个var参数,当过程返回的时候它包含插件的描述。
      要调用刚刚获得的过程,只需要使用保存地址的变量作为过程名,后面跟上任何参数。就上面的例子而言,声明:
    DescribeProc(Description)
    将会调用在插件中获得的描述过程,并且用描述插件功能的字符串填充Description变量。