主窗体的调用程序
function TForm1.Dllfrmshow(frm:integer;dllname:string):boolean;
var
  DLLHandle: THandle;
  DLLSub: InvokeDLLForm;
begin
DLLHandle :=LoadLibrary(PChar(extractfilepath(application.ExeName)+'dll\'+dllname));if DLLHandle = 0 then
begin
showmessage('调入失败!');
exit;
end;if DllHandle_rk[frm] = 0 then
begintry
  if DLLHandle <> 0 then
  begin
    DllHandle_rk[frm]:= DLLHandle;
    @DLLSub := GetProcAddress(DLLHandle, 'CreateDLLForm');
    if Assigned(DLLSub) then
      DLLForm := DLLSub(Application, Screen);
  end;
except
  FreeLibrary(DLLHandle);
  end;end
else
exit;
end;
dll的程序
unit DLLFormUnit;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, StdCtrls, ExtCtrls, DB, ADODB, Grids, DBGrids;
 const   MyMessage   =wm_user+100;   
  type   
      TMyMessage=record   
          s1:pchar;   
          s2:pchar;   
      end;   
  type
  basemsg=packed Record
    puserid:string;
  end;
  TfrmDLLForm = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
  function openform(pbase:basemsg):Thandle;
  function save:boolean;stdcall;var
  frmDLLForm: TfrmDLLForm;
    aa:string;
implementationuses Unit1;{$R *.dfm}function openform(pbase:basemsg):Thandle;
begin
showmessage(pbase.puserid);end;function save:boolean;stdcall;
begin
  showmessage('保存!');
end;end.
现在我在主窗体中如何调用dll中定义的save函数,而如果我在主窗体里定义一个公共变量dll程序里又如何取到这个变量!!等待高手解决问题,谢谢我听说用传消息的方式可以调用和传变量但如何实现请高手指教!谢谢 

解决方案 »

  1.   

    to WuChenCan 
    能不能麻烦你给个例子主窗口如何用消息传递变量给dll,谢谢
      

  2.   

    搶分來的
    1、咳,都沒export怎麼調用save?
    2、可以把主窗體的公用變量傳到save,save可以定義成可接收參數的
      

  3.   

    呵,主窗体调用dll函数的问题我已经解决了,现在就还差如何把主窗体的变量传给dll子窗体,而dll子窗体里有如何修改主窗体的变量!麻烦那位大哥给个例子!!小弟万分感激,谢谢
      

  4.   

    如果說dll子窗要用這個變量的話,可以通過傳遞參數解決,但要修改的話,就不能直接修改了。可以通過消息修改;
    1、自定一個消息(如WM_MyMsg = WM_USER + 100);
    2、在主窗寫一個相關消息處理函數(可取msg.lParam更新此變量)
    3、在dll窗裡,如果需要修改,則通過sendmessage(handle,自定義消息,0,integer(修改的值))
      

  5.   

    to Avan_Lau(OnlyYou) 能不能在我的例子上修改呢?麻烦您了,谢谢!
    dll窗体代码unit DLLFormUnit;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Menus, StdCtrls, ExtCtrls, DB, ADODB, Grids, DBGrids;  type
      basemsg=packed Record
        userid:string;
      end;type
      TfrmDLLForm = class(TForm)
        Label1: TLabel;
        Button1: TButton;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
     
    varimplementationuses Unit1;{$R *.dfm}procedure TfrmDLLForm.Button1Click(Sender: TObject);
    begin
    我想在这个按纽事件里修改主窗体的公共变量aa的值
    主窗体.aa:='sssss';(类似于这个样,用消息如何实现麻烦您帮我用消息的方式修改一下谢谢)
    end;end.
    exe主窗体代码
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Menus, Buttons, ComCtrls, ToolWin, ExtCtrls, StdCtrls;
      type
      basemsg=packed Record
        userid:string;
      end;
    type
      InvokeDLLForm = function(App: TApplication; Scr: TScreen): TForm;
      TForm1 = class(TForm)
        ToolBar1: TToolBar;
        BitBtn1: TSpeedButton;
        BitBtn2: TSpeedButton;
        BitBtn3: TSpeedButton;
        BitBtn4: TSpeedButton;
        ToolButton3: TToolButton;
        BitBtn5: TSpeedButton;
        BitBtn6: TSpeedButton;
        BitBtn7: TSpeedButton;
        BitBtn8: TSpeedButton;
        BitBtn9: TSpeedButton;
        bitbtn11: TSpeedButton;
        bitbtn12: TSpeedButton;
        BitBtn10: TSpeedButton;
        MainMenu1: TMainMenu;
        N111: TMenuItem;
        SBar: TStatusBar;
        Timer1: TTimer;
        N1: TMenuItem;
        Image1: TImage;
        N2: TMenuItem;
        procedure BitBtn10Click(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure N1Click(Sender: TObject);
        procedure N2Click(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
           private
        { Private declarations }
      public
       DllHandle_rk:array[0..150] of Thandle;//DLL文件存放入口 
        { Public declarations }
      end;var
      Form1: TForm1;
      DLLForm: TForm;
      Windowsid:integer;
      aa:string;
    implementation
    {$R *.dfm}procedure TForm1.BitBtn1Click(Sender: TObject);
    begin
    aa:='qw';
    end;end;end.
      

  6.   

    dll窗体代码 unit   DLLFormUnit; interface uses 
        Windows,   Messages,   SysUtils,   Variants,   Classes,   Graphics,   Controls,   Forms, 
        Dialogs,   Menus,   StdCtrls,   ExtCtrls,   DB,   ADODB,   Grids,   DBGrids;     type 
        basemsg=packed   Record 
            userid:string; 
        end; 
    //這裡定義消息,建議再開一個單元,存放此類常量
    const
      WM_ModifyAA = WM_USER + 100;
    type 
        TfrmDLLForm   =   class(TForm) 
            Label1:   TLabel; 
            Button1:   TButton; 
            procedure   FormClose(Sender:   TObject;   var   Action:   TCloseAction); 
            procedure   Button1Click(Sender:   TObject); 
        private 
            {   Private   declarations   } 
        public 
            {   Public   declarations   } 
        end; 
      
    var implementation uses   Unit1; {$R   *.dfm} 
    procedure   TfrmDLLForm.Button1Click(Sender:   TObject); 
    var
      tmpStr:string;
    begin 
    我想在这个按纽事件里修改主窗体的公共变量aa的值 
    主窗体.aa:='sssss';(类似于这个样,用消息如何实现麻烦您帮我用消息的方式修改一下谢谢) 
      tmpStr:='sssss';
    sendmessage(mainform.handle,wm_ModifyAA,0,Integer(tmpStr));
    end; end. 
    exe主窗体代码 
    unit   Unit1; interface uses 
        Windows,   Messages,   SysUtils,   Variants,   Classes,   Graphics,   Controls,   Forms, 
        Dialogs,   Menus,   Buttons,   ComCtrls,   ToolWin,   ExtCtrls,   StdCtrls; 
        type 
        basemsg=packed   Record 
            userid:string; 
        end; 
    //這裡定義消息,建議再開一個單元,存放此類常量
    const
      WM_ModifyAA = WM_USER + 100;
    type 
        InvokeDLLForm   =   function(App:   TApplication;   Scr:   TScreen):   TForm; 
        TForm1   =   class(TForm) 
            ToolBar1:   TToolBar; 
            BitBtn1:   TSpeedButton; 
            BitBtn2:   TSpeedButton; 
            BitBtn3:   TSpeedButton; 
            BitBtn4:   TSpeedButton; 
            ToolButton3:   TToolButton; 
            BitBtn5:   TSpeedButton; 
            BitBtn6:   TSpeedButton; 
            BitBtn7:   TSpeedButton; 
            BitBtn8:   TSpeedButton; 
            BitBtn9:   TSpeedButton; 
            bitbtn11:   TSpeedButton; 
            bitbtn12:   TSpeedButton; 
            BitBtn10:   TSpeedButton; 
            MainMenu1:   TMainMenu; 
            N111:   TMenuItem; 
            SBar:   TStatusBar; 
            Timer1:   TTimer; 
            N1:   TMenuItem; 
            Image1:   TImage; 
            N2:   TMenuItem; 
            procedure   BitBtn10Click(Sender:   TObject); 
            procedure   Timer1Timer(Sender:   TObject); 
            procedure   N1Click(Sender:   TObject); 
            procedure   N2Click(Sender:   TObject); 
            procedure   BitBtn1Click(Sender:   TObject); 
        private 
           {   Private   declarations   } 
    //這裡寫消息處理過程
           procedure WMModifyAA(var msg: TMessage);message WM_ModifyAA;
        public 
          DllHandle_rk:array[0..150]   of   Thandle;//DLL文件存放入口   
            {   Public   declarations   } 
        end; var 
        Form1:   TForm1; 
        DLLForm:   TForm; 
        Windowsid:integer; 
        aa:string; 
    implementation 
    {$R   *.dfm} procedure   TForm1.BitBtn1Click(Sender:   TObject); 
    begin 
    aa:='qw'; 
    end; 
    //實現示例
    procedure   TForm1.WMModifyAA(var msg: TMessage);
    begin 
    aa:= PChar(msg.LParam); 
    end; 
    end; end. 
      

  7.   

    to Avan_Lau(OnlyYou) 在编译dll时候这句出错 是不是mainform.handle 没定义呀,请告知谢谢sendmessage(mainform.handle,wm_ModifyAA,0,Integer(tmpStr)); 
      

  8.   

    to   Avan_Lau(OnlyYou)
    还有好像在执行dll发送消息回传到主窗体时候没触发到下面的事件,难道下面的事件不是如果有消息传送时自动触发的吗?如果我想在触发dll传送消息时在不触发主窗体任何控件事件的情况下改变变量的值如何实现,有没有在回传消息事自动触发某个事件呢?请告知,万分感谢
    procedure       TForm1.WMModifyAA(var   msg:   TMessage); 
    begin   
    aa:=   PChar(msg.LParam);   
    end; 
      

  9.   

    回復如下:
    1、sendmessage(mainform.handle,wm_ModifyAA,0,Integer(tmpStr));   
    其中,maiform.handle只是表示,你應該傳入你想要處理的變量所在的窗體的handle,請不要照抄!
    2、應該是mainform沒有收到此消息的緣故,要確認兩點:
      1)、主窗體的application要傳給dll,並把dll的appliaction替換;
      2)、檢查你所傳遞的handle是否為目的窗體的handle;
    3、想要"在回传消息事自动触发某个事件",請把事件處理函數寫在消息處理過程即可;
    4、散分吧,哈哈
      

  10.   

    to Avan_Lau(OnlyYou) 
    sendmessage(mainform.handle,wm_ModifyAA,0,Integer(tmpStr));   
    mainform.handle这个我该如何写,"主窗體的application要傳給dll,並把dll的appliaction替換"这个地方我该如何处理,能不能麻烦大哥在我的上面给个完整的例子呢?麻烦您了,谢谢!!!
      

  11.   

    to  Avan_Lau(OnlyYou)   
    我已把主窗体的Handle 传给了dll,在dll那边我定义了一个变量为  fhandle:Thandle;然后把主窗体的Handle复给它 发送信息时用的是
    sendmessage(fhandle,wm_ModifyAA,0,Integer(tmpStr));
    但为何主窗体的那个过程还是没反应呢?请告知谢谢!
    procedure TForm1.WM_ModifyAA(var msg: TMessage);
    begin
     showmessage(PChar(msg.LParam));
    end;
        
      

  12.   

    to     Avan_Lau(OnlyYou)  能不能再帮我看看我的原程序看问题出在那,麻烦您了,谢谢dll程序
    unit DLLFormUnit;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Menus, StdCtrls, ExtCtrls, DB, ADODB, Grids, DBGrids;  type
      basemsg=packed Record
        phandle:Thandle;
        userid:string;
      end;
    const 
        WM_ModifyAA= WM_USER + 200;type
      TfrmDLLForm = class(TForm)
        Label1: TLabel;
        Button1: TButton;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
      function openform(pbase:basemsg):Thandle;
      function save:boolean;stdcall;
      function Windowmax:boolean;stdcall;  
    var
      frmDLLForm: TfrmDLLForm;
      puserid:string;
      fhandle:Thandle;
    implementationuses Unit1;{$R *.dfm}procedure TfrmDLLForm.FormClose(Sender: TObject; var Action: TCloseAction);
    var
        tmpStr:string;
    begin
    tmpStr:='111';
    //sendmessage(Handle,wm_ModifyAA,0,Integer(tmpStr));
    freeandnil(frmDLLForm);
    freeandnil(Form1);
    end;procedure TfrmDLLForm.Button1Click(Sender: TObject);
    var
        tmpStr:string;
    begin
    tmpStr:='111';
    //sendmessage(HWND_BROADCAST,WM_ModifyAA,0,Integer(tmpStr));
    sendmessage(fhandle,WM_ModifyAA,0,Integer(tmpStr));
    //postMessage(fhandle,WM_ModifyAA,0,Integer(tmpStr));
    //showmessage(inttostr(fhandle));
    end;function save:boolean;stdcall;
    begin
      showmessage('保存111111!');
    end;function Windowmax:boolean;stdcall;
    begin
    frmDLLForm.WindowState:= wsMaximized;
    end;
    function openform(pbase:basemsg):Thandle;
    begin
    fhandle:=pbase.phandle;
    puserid:=pbase.userid;
    end;
    end.
    主程序
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Menus, Buttons, ComCtrls, ToolWin, ExtCtrls, StdCtrls;
    const 
        WM_ModifyAA= WM_USER + 100;
      type
      basemsg=packed Record
      phandle:Thandle;
      userid:string;
      end;type
      InvokeDLLForm = function(App: TApplication; Scr: TScreen): TForm;
      TForm1 = class(TForm)
        ToolBar1: TToolBar;
        BitBtn1: TSpeedButton;
        BitBtn2: TSpeedButton;
        BitBtn3: TSpeedButton;
        BitBtn4: TSpeedButton;
        ToolButton3: TToolButton;
        BitBtn5: TSpeedButton;
        BitBtn6: TSpeedButton;
        BitBtn7: TSpeedButton;
        BitBtn8: TSpeedButton;
        BitBtn9: TSpeedButton;
        bitbtn11: TSpeedButton;
        bitbtn12: TSpeedButton;
        BitBtn10: TSpeedButton;
        MainMenu1: TMainMenu;
        N111: TMenuItem;
        SBar: TStatusBar;
        Timer1: TTimer;
        N1: TMenuItem;
        Image1: TImage;
        N2: TMenuItem;
        procedure BitBtn10Click(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
        procedure N1Click(Sender: TObject);
        function Dllfrmshow(frm:integer;dllname:string):boolean;
        procedure N2Click(Sender: TObject);
        procedure BitBtn1Click(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
           private
        { Private declarations }
      procedure WM_ModifyAA(var msg: TMessage);message WM_ModifyAA;
      public
       DllHandle_rk:array[0..150] of Thandle;//DLL文件存放入口
       dllProcAddr:array[0..150] of  FarProc;//激活程序入口   
        { Public declarations }
      end;var
      Form1: TForm1;
      DLLForm: TForm;
      Windowsid:integer;
      Pbase:basemsg;
    implementation
    //function save:boolean;far;external 'prjDLL.dll';{$R *.dfm}function TForm1.Dllfrmshow(frm:integer;dllname:string):boolean;
    type
    Windowmax= function :boolean;stdcall;
    openform =function (pbase:basemsg):Thandle;
    var
      DLLHandle: THandle;
      DLLSub: InvokeDLLForm;
      Tf:Windowmax;
      Tf2:openform;
      Tp,Tp2:TFarProc;
    begin
    DLLHandle :=LoadLibrary(PChar(extractfilepath(application.ExeName)+'dll\'+dllname));
    if DLLHandle = 0 then
    begin
    showmessage('调入失败!');
    exit;
    end;Windowsid:=frm;//////////////////////载入函数
    Tp:=GetProcAddress(DLLHandle,PChar('Windowmax'));  ////窗口最大化函数
    Tp2:=GetProcAddress(DLLHandle,PChar('openform')); /////open dll函数
    //////////////////////载入函数
    if DllHandle_rk[frm] = 0 then
    begin
    DllHandle_rk[frm]:= DLLHandle;
    try
      if DllHandle_rk[frm] <> 0 then
      begin
        @DLLSub := GetProcAddress(DllHandle_rk[frm], 'CreateDLLForm');
        if Assigned(DLLSub) then
          DLLForm := DLLSub(Application, Screen);////////////////////传递pbase类给dll
    Pbase.userid :='aa';
    Pbase.phandle:=Handle;
    if Tp2<>nil
    then
    begin
    Tf2:=openform(Tp2);
    Tf2(pbase);
    end;
    ////////////////////传递pbase类给dll 
    end;
    except
      FreeLibrary(DllHandle_rk[frm]);
    end;end
    else
    if Tp<>nil
    then
    begin
    Tf:=Windowmax(Tp);
    Tf();
    end;
    end;
    procedure TForm1.BitBtn10Click(Sender: TObject);
    begin
    self.Close;
    end;procedure TForm1.Timer1Timer(Sender: TObject);
    begin
    sbar.panels[3].Text:=formatdatetime('hh"时"mm"分"ss"秒"',time());
    end;procedure TForm1.N1Click(Sender: TObject);
    begin
    Dllfrmshow(1,'prjDLL.dll');
    end;procedure TForm1.N2Click(Sender: TObject);
    begin
    Dllfrmshow(2,'prjDLL2.dll');
    end;end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    FreeLibrary(DllHandle_rk[1]);
    end;procedure TForm1.WM_ModifyAA(var msg: TMessage);
    begin
    // inherited;
    //showmessage('sdfsdf');
    showmessage(Pchar(msg.LParam));
    end;end.
      

  13.   

    1、以下代碼寫在dll工程文件裡
    procedure   DLLEntryPoint(dwReason:   DWord); 
    begin 
        case   dwReason   of 
            DLL_PROCESS_ATTACH:;//在這裡記錄原來的application 
            DLL_PROCESS_DETACH:;//在這裡還原原來的application   
            DLL_THREAD_ATTACH:   ; 
            DLL_THREAD_DETACH:   ;   
        end; 
    end; begin //以下兩行寫在dll工程文件自帶的begin..end
        DllProc   :=@DLLEntryPoint; 
        DLLEntryPoint(DLL_PROCESS_ATTACH); 
    end. 
    2、你在CreateDllForm時有傳application,這時你把dll的application的handle換成傳進來的那個application的handle
      

  14.   

    to Avan_Lau 
    谢谢你的帮助,如何给你结贴加分呢?我咋找不到这个连接呢?
      

  15.   

    問題解決了嗎?
    結帖可以參考這個:
    http://topic.csdn.net/t/20021009/07/1080330.html
      

  16.   

    需要修正的段落
    1、
    //////////////////////载入函数 
    Tp:=GetProcAddress(DLLHandle,PChar('Windowmax'));     ////窗口最大化函数 
    Tp2:=GetProcAddress(DLLHandle,PChar('openform'));   /////open   dll函数 
    //////////////////////载入函数 
    不需要聲明tp和tp2,只要用tf和tf2就好,如下
    if dllhandle<>0 then
    begin
      @Tf:=GetProcAddress(DLLHandle,PChar('Windowmax'));     ////窗口最大化函数 
      @Tf2:=GetProcAddress(DLLHandle,PChar('openform'));   /////open   dll函数 
    end;
    2、
    ////////////////////传递pbase类给dll 
    Pbase.userid   :='aa'; 
    Pbase.phandle:=Handle; 
    if   Tp2 <> nil 
    then 
    begin 
    Tf2:=openform(Tp2); 
    Tf2(pbase); 
    end; 
    ////////////////////传递pbase类给dll  
    這樣就好:
    Pbase.userid   :='aa'; 
    Pbase.phandle:=Handle; 
    Tf2(pbase); 另外,你的程序結構非常亂!這樣很容易出錯,重新整理一下。
      

  17.   

    to Avan_Lau 
    非常感谢您的帮助和建议,我该如何结这贴给您分呢?还有我又开了个新贴有个新问题一个调用Dll子窗体如何释放的问题!
    http://topic.csdn.net/u/20071212/16/115592f0-dee2-49e2-9ef5-738bf8feee6d.html
    您能不能帮我看看为什么主窗体关闭时候回出错,万分感谢!
      

  18.   

    問題解決了嗎? 
    結帖可以參考這個: 
    http://topic.csdn.net/t/20021009/07/1080330.html
      

  19.   

    消息的问题已经解决了,十分感谢,但我现在碰到了主窗体关闭时出错的问题,我想应该是函数调用的时候在主窗体关闭的时候函数地址没有释放之类的,能不能帮我看看谢谢!!
    http://topic.csdn.net/u/20071212/16/115592f0-dee2-49e2-9ef5-738bf8feee6d.html 还有这贴我该如何结贴给你分呢?