问题:当调用DLL成功后显示的是默认的输入窗体(上面有个打印钮),在单击"打印"时报错,如何调出打印预览的窗体;
一个程序有共有两个窗体,一个是输入用的(sgdgd_tj.pas),一个是打印预览用的(SGDGD_TJDY.pas).两个窗体的FORMSTYLE都是FSNORMAL,确定正常后做成了DLL.代码如下:library dll_1;
uses
  SysUtils,
  ActiveX,
  windows,
  Classes,
  sgdgd_tj in 'sgdgd_tj.pas' {Form1},
  SGDGD_TJDY in 'SGDGD_TJDY.pas' {Form12};
  procedure _DllProc(Reason: Integer);
begin  if Reason = DLL_PROCESS_ATTACH then
    CoInitialize(nil)
  else if Reason = DLL_PROCESS_DETACH then    CoUninitialize;
end;{$R *.res}
 exports
  myshowform1,
  mycloseform1;
begin
   DLLProc := @_DllProc;
  _DllProc(DLL_PROCESS_ATTACH);end.调用的主程序如下:unit dll_tes;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  Ttest = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  test: Ttest;
  formref:longint;
function myshowform1(ahandle:thandle):longint;stdcall;
procedure mycloseform1(aformref:longint);stdcall;implementation
function myshowform1;external 'dll_1.dll';
procedure mycloseform1;external 'dll_1.dll';{$R *.dfm}procedure Ttest.Button1Click(Sender: TObject);
begin
formref:=myshowform1(application.handle);
end;procedure Ttest.Button2Click(Sender: TObject);
begin
   mycloseform1(formref);
    test.Close;end;procedure Ttest.FormClose(Sender: TObject; var Action: TCloseAction);
begin
mycloseform1(formref);
end;end.

解决方案 »

  1.   

    我用forefox浏览器,没看清你代码,字母都变形了,呵呵.
    记得要从主程序中把句柄传入到DLL中.这样好多东东都不会出错了.
      

  2.   

    给你一段介绍看看吧,应该有用的
    用delphi制作dll小结一 Dll的制作一般分为以下几步:
    1 在一个DLL工程里写一个过程或函数
    2 写一个Exports关键字,在其下写过程的名称。不用写参数和调用后缀。
    二 参数传递
    1 参数类型最好与window C++的参数类型一致。不要用DELPHI的数据类型。
    2 最好有返回值[即使是一个过程],来报出调用成功或失败,或状态。成功或失败的返回值最好为1[成功]或0[失败].一句话,与windows c++兼容。
    3 用stdcall声明后缀。
    4 最好大小写敏感。
    5 无须用far调用后缀,那只是为了与windows 16位程序兼容。三 DLL的初始化和退出清理[如果需要初始化和退出清理]
    1 DLLProc[SysUtils单元的一个Pointer]是DLL的入口。在此你可用你的函数替换了它的入口。但你的函数必须符合以下要求[其实就是一个回调函数]。如下:
    procedure DllEnterPoint(dwReason: DWORD);far;stdcall;
    dwReason参数有四种类型:
    DLL_PROCESS_ATTACH:进程进入时
    DLL_PROCESS_DETACH进程退出时
    DLL_THREAD_ATTACH 线程进入时
    DLL_THREAD_DETACH 线程退出时
    在初始化部分写:
    DLLProc := @DLLEnterPoint;
    DllEnterPoint(DLL_PROCESS_ATTACH);
    2 如Form上有TdcomConnection组件,就Uses Activex,在初始化时写一句CoInitialize (nil);
    3 在退出时一定保证DcomConnection.Connected := False,并且数据集已关闭。否则报地址错。四 全局变量的使用
    在widnows 32位程序中,两个应用程序的地址空间是相互没有联系的。虽然DLL在内存中是一份,但变量是在各进程的地址空间中,因此你不能借助dll的全局变量来达到两个应用程序间的数据传递,除非你用内存映像文件。五 调用静态载入
    1 客户端函数声名:
    1)大小写敏感。
    2)与DLL中的声明一样。
    如: showform(form:Tform);Far;external'yproject_dll.dll';
    3)调用时传过去的参数类型最好也与windows c++一样。
    4)调用时DLL必须在windows搜索路径中,顺序是:当前目录;Path路径;windows;widows\system;windows\ssystem32;六 调用动态载入
    1 建立一种过程类型[如果你对过程类型的变量只是一个指针的本质清楚的话,你就知道是怎么回事了]。如:
    type
    mypointer=procedure(form:Tform);Far;external;
    var
    Hinst:Thandle;
    showform:mypointer;
    begin
    Hinst:=loadlibrary('yproject_dll');//Load一个Dll,按文件名找。
    showform:=getprocaddress(Hinst,'showform');//按函数名找,大小写敏感。如果你知道自动化对象的本质就清楚了。
    showform(application.mainform);//找到函数入口指针就调用。
    Freelibrary(Hinst);
    end;七 在DLL建立一个TForM
    1 把你的Form Uses到Dll中,你的Form用到的关联的单元也要Uses进来[这是最麻烦的一点,因为你的Form或许Uses了许多特殊的单元或函数]
    2 传递一个Application参数,用它建立Form.八 在DLL中建立一个TMDIChildForM
    1 Dll中的MDIForm.FormStyle不用为fmMDIChild.
    2 在CreateForm后写以下两句:
    function ShowForm(mainForm:TForm):integer;stdcall
    var
    Form1: TForm1;
    ptr:PLongInt;
    begin
    ptr:=@(Application.MainForm);//先把dll的MainForm句柄保存起来,也无须释放,只不过是替换一下
    ptr^:=LongInt(mainForm);//用主调程序的mainForm替换DLL的MainForm。MainForm是特殊的WINDOW,它专门管理Application中的Forms资源.
    //为什么不直接Application.MainForm := mainForm,因为Application.MainForm是只读属性
    Form1:=TForm1.Create(mainForm);//用参数建立
    end;
    备注:参数是主调程序的Application.MainForm
    九 示例:
    DLL源代码:
    library Project2;uses
    SysUtils,
    Classes,
    Dialogs,
    Forms,
    Unit2 in 'Unit2.pas' {Form2};{$R *.RES}
    var
    ccc: Pchar;procedure OpenForm(mainForm:TForm);stdcall;
    var
    Form1: TForm1;
    ptr:PLongInt;
    begin
    ptr:=@(Application.MainForm);
    ptr^:=LongInt(mainForm);
    Form1:=TForm1.Create(mainForm);
    end;procedure InputCCC(Text: Pchar);stdcall;
    begin
    ccc := Text;
    end;procedure ShowCCC;stdcall;
    begin
    ShowMessage(String(ccc));
    end;exports
    OpenForm;
    InputCCC,
    ShowCCC;
    begin
    end.调用方源代码:
    unit Unit1;interfaceuses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    StdCtrls;type
    TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;var
    Form1: TForm1;implementation{$R *.DFM}
    procedure OpenForm(mainForm:TForm);stdcall;External'project2.dll';
    procedure ShowCCC;stdcall;External'project2.dll';
    procedure InputCCC(Text: Pchar);stdcall;External'project2.dll';procedure TForm1.Button1Click(Sender: TObject);
    var
    Text: Pchar;
    begin
    Text := Pchar(Edit1.Text);
    // OpenForm(Application.MainForm);//为了调MDICHILD
    InputCCC(Text);//为了实验DLL中的全局变量是否在各个应用程序间共享
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
    ShowCCC;//这里表明WINDOWS 32位应用程序DLL中的全局变量也是在应用程序地址空间中,16位应用程序或许不同,没有做实验。end;
      

  3.   

    本人愚昧不是很懂,想请叫一下 OpenForm调用出来的是DLL的 mainForM窗本还是FORM1呀.
      

  4.   

    本人愚昧不是很懂,想请叫一下 上面的例子是从调用方传到DLL吧.如果是,那在DLL中的用法是不是直接在DLL.的
    引用单元中直接使用呀.
      

  5.   

    那们高人能给个详细的例子呀.(我的DLL是引用别的窗体单元的.不是在DLL中建的.)
      

  6.   

    http://blog.csdn.net/simonhehe/archive/2008/05/19/2458597.aspx
      

  7.   

     日志-病毒-网络-操作系统-安全-c#-asp.net-java-delphi-sql-oracle学习资源
     在这里可以找找http://japee.com.cn/jew/bbs.aspx
      

  8.   

    那位好心人帮俺详细注释一下,下面的代码.//调用窗体 Begin unit CMain;
    interface
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Menus, ExtCtrls, utchild;
    const
     WM_CALLBACK = WM_USER + 100;
    type
      TShowForm   = function (App: TApplication; CallProc: Pointer; FormID: Integer; ParentForm: TForm; ParentContralHandle: HWND): Tform; stdcall;
      TActiveForm = function : LongInt; stdcall;
      TCloseForm  = function : LongInt; stdcall;
      TfrmMain = class(TForm)
        MainMenu1: TMainMenu;
        Open1: TMenuItem;
        mmFileOpen: TMenuItem;
        mmFileClose: TMenuItem;
        Panel1: TPanel;
        mmFileOpenFrm: TMenuItem;
        mmFileCloseFrm: TMenuItem;
        Report1: TMenuItem;
        N1111: TMenuItem;
        Panel2: TPanel;
        Change1: TMenuItem;
        procedure mmFileOpenClick(Sender: TObject);
        procedure mmFileCloseClick(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure mmFileOpenFrmClick(Sender: TObject);
        procedure N1111Click(Sender: TObject);
        procedure Change1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        FLibHandle  : THandle;
        FShowForm   : TShowForm;
        FActiveForm : TActiveForm;
        FCloseForm  : TCloseForm;
        List : TList;
        //FFrm: TForm1;
        procedure CallPostMessage(ID:Integer);
        procedure BackCallMessage(var Msg: TMessage); message WM_CALLBACK;    procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
        function GetSysFocus: Integer;
      public
        { Public declarations }
        procedure WMACTIVATEAPP(var Msg: TMessage); message WM_ACTIVATEAPP;
      end;var
      frmMain: TfrmMain;
      FFrm: TForm1;
    implementation
    const id_SnapShot = 115; //定义热键标识符{$R *.dfm}
    procedure TfrmMain.WMHotKey(var Msg: TWMHotKey);
    var 
      H: THandle; 
    begin 
      if Msg.HotKey = id_SnapShot then
      begin 
        H := GetSysFocus;
        while IsWindow(H) and (H <> frmMain.Handle) do
        begin 
          SendMessage(H,WM_NEXTDLGCTL,0,0); 
          H := GetParent(H); 
        end; 
      end; 
    end; function TfrmMain.GetSysFocus: Integer;
    var 
      hOtherWin,OtherThreadID,hFocusWin:integer; 
    begin 
      hOtherWin:=GetForegroundWindow;
      OtherThreadID:=GetWindowThreadProcessID(hOtherWin,nil); 
      if AttachThreadInput(GetcurrentThreadID,OtherThreadID,True) then 
      begin 
        hFocusWin:=GetFocus; 
        result:=GetFocus; 
      if HFocusWin<>0 then 
      try 
      //
      finally 
        AttachThreadInput(GetcurrentThreadID,OtherThreadID,False); 
      end; 
      end 
      else result:=GetFocus; 
    end; procedure TfrmMain.WMACTIVATEAPP(var Msg: TMessage);
    begin 
      if Boolean(Msg.WParam) then 
        RegisterHotKey(frmMain.Handle, id_SnapShot, 0, VK_TAB)
      else 
        UnRegisterHotKey(frmMain.Handle, id_SnapShot);
    end; procedure CallBackProc(ID:Integer); stdcall;
    begin
      frmMain.CallPostMessage(ID);
    end;procedure TfrmMain.CallPostMessage(ID: Integer);
    begin
     PostMessage(self.Handle, WM_CALLBACK, ID, 0);
    end;procedure TfrmMain.BackCallMessage(var Msg: TMessage);
    begin
     if Msg.Msg = WM_CALLBACK then
     begin
       if Msg.WParam = FLibHandle then
       begin
         FreeLibrary(FLibHandle);
         FLibHandle := 0;
       end;
     end;
    end;procedure TfrmMain.mmFileOpenClick(Sender: TObject);
    var
     FarPointer : FarProc;
    begin
     if FLibHandle = 0 then
     begin
       try
         FLibHandle := LoadLibrary('Project2.dll');
       except
         FLibHandle := 0;
       end;
       if FLibHandle <> 0 then
       begin
         FarPointer  := GetProcAddress(FLibHandle, 'ShowForm');
         FShowForm   := FarPointer;
         FarPointer  :=  GetProcAddress(FLibHandle, 'ActiveForm');
         FActiveForm := FarPointer;
         FarPointer  := GetProcAddress(FLibHandle, 'CloseForm');
         FCloseForm  := FarPointer;
         if Assigned(FShowForm) then
           //FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle);
           List.add(FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle));
       end;
     end
     else
     begin
       if Assigned(FActiveForm) then
       begin
         FActiveForm;
       end;
     end;
    end;procedure TfrmMain.mmFileCloseClick(Sender: TObject);
    begin
     if FLibHandle <> 0 then
       FCloseForm;end;procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      if FLibHandle <> 0 then
        FCloseForm;
      if assigned(FFrm) then
        FreeAndNil(FFrm);
    end;procedure TfrmMain.mmFileOpenFrmClick(Sender: TObject);
    begin
      if not assigned(FFrm) then
      begin
        FFrm := TForm1.Create(nil);
        with FFrm do
        begin
          ParentWindow := panel1.Handle;
          align := alClient;
          BorderStyle := bsNone;
          BorderIcons := [];
        end;
      end;
      FFrm.Show;
    end;procedure TfrmMain.N1111Click(Sender: TObject);
    begin
      FFrm.Edit2.Text := 'abc';
      
    end;procedure TfrmMain.Change1Click(Sender: TObject);
    begin
      if FFrm.ParentWindow = Panel1.handle then
        FFrm.ParentWindow := Panel2.handle
      else
        FFrm.ParentWindow := Panel1.handle
    end;procedure TfrmMain.FormCreate(Sender: TObject);
    begin
      List := TList.Create;
    end;end.
    //调用窗体End
      

  9.   

    unit CMain; 
    interface 
    uses 
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs, Menus, ExtCtrls, utchild; 
    const 
     WM_CALLBACK = WM_USER + 100; 
    type 
      TShowForm   = function (App: TApplication; CallProc: Pointer; FormID: Integer; ParentForm: TForm; ParentContralHandle: HWND): Tform; stdcall; 
      TActiveForm = function : LongInt; stdcall; 
      TCloseForm  = function : LongInt; stdcall; 
      TfrmMain = class(TForm) 
        MainMenu1: TMainMenu; 
        Open1: TMenuItem; 
        mmFileOpen: TMenuItem; 
        mmFileClose: TMenuItem; 
        Panel1: TPanel; 
        mmFileOpenFrm: TMenuItem; 
        mmFileCloseFrm: TMenuItem; 
        Report1: TMenuItem; 
        N1111: TMenuItem; 
        Panel2: TPanel; 
        Change1: TMenuItem; 
        procedure mmFileOpenClick(Sender: TObject); 
        procedure mmFileCloseClick(Sender: TObject); 
        procedure FormClose(Sender: TObject; var Action: TCloseAction); 
        procedure mmFileOpenFrmClick(Sender: TObject); 
        procedure N1111Click(Sender: TObject); 
        procedure Change1Click(Sender: TObject); 
        procedure FormCreate(Sender: TObject); 
      private 
        { Private declarations } 
        FLibHandle  : THandle; 
        FShowForm   : TShowForm; 
        FActiveForm : TActiveForm; 
        FCloseForm  : TCloseForm; 
        List : TList; 
        //FFrm: TForm1; 
        procedure CallPostMessage(ID:Integer); 
        procedure BackCallMessage(var Msg: TMessage); message WM_CALLBACK;     procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY; 
        function GetSysFocus: Integer; 
      public 
        { Public declarations } 
        procedure WMACTIVATEAPP(var Msg: TMessage); message WM_ACTIVATEAPP; 
      end; var 
      frmMain: TfrmMain; 
      FFrm: TForm1; 
    implementation 
    const id_SnapShot = 115; //定义热键标识符 {$R *.dfm} 
    procedure TfrmMain.WMHotKey(var Msg: TWMHotKey); //主要是为了DLL内TAB键可用
    var  
      H: THandle;  
    begin  
      if Msg.HotKey = id_SnapShot then 
      begin  
        H := GetSysFocus; 
        while IsWindow(H) and (H  <> frmMain.Handle) do 
        begin  
          SendMessage(H,WM_NEXTDLGCTL,0,0);  
          H := GetParent(H);  
        end;  
      end;  
    end;  function TfrmMain.GetSysFocus: Integer; //获取光标所在
    var  
      hOtherWin,OtherThreadID,hFocusWin:integer;  
    begin  
      hOtherWin:=GetForegroundWindow; 
      OtherThreadID:=GetWindowThreadProcessID(hOtherWin,nil);  
      if AttachThreadInput(GetcurrentThreadID,OtherThreadID,True) then  
      begin  
        hFocusWin:=GetFocus;  
        result:=GetFocus;  
      if HFocusWin <>0 then  
      try  
      // 
      finally  
        AttachThreadInput(GetcurrentThreadID,OtherThreadID,False);  
      end;  
      end  
      else result:=GetFocus;  
    end;  procedure TfrmMain.WMACTIVATEAPP(var Msg: TMessage); //系统热键
    begin  
      if Boolean(Msg.WParam) then  
        RegisterHotKey(frmMain.Handle, id_SnapShot, 0, VK_TAB) 
      else  
        UnRegisterHotKey(frmMain.Handle, id_SnapShot); 
    end;  procedure CallBackProc(ID:Integer); stdcall; 
    begin 
      frmMain.CallPostMessage(ID); 
    end; procedure TfrmMain.CallPostMessage(ID: Integer); 
    begin 
     PostMessage(self.Handle, WM_CALLBACK, ID, 0); 
    end; procedure TfrmMain.BackCallMessage(var Msg: TMessage); 
    begin 
     if Msg.Msg = WM_CALLBACK then 
     begin 
       if Msg.WParam = FLibHandle then 
       begin 
         FreeLibrary(FLibHandle); 
         FLibHandle := 0; 
       end; 
     end; 
    end; procedure TfrmMain.mmFileOpenClick(Sender: TObject); //动态调用project2.DLl
    var 
     FarPointer : FarProc; 
    begin 
     if FLibHandle = 0 then 
     begin 
       try 
         FLibHandle := LoadLibrary('Project2.dll'); 
       except 
         FLibHandle := 0; 
       end; 
       if FLibHandle  <> 0 then 
       begin 
         FarPointer  := GetProcAddress(FLibHandle, 'ShowForm'); 
         FShowForm   := FarPointer; 
         FarPointer  :=  GetProcAddress(FLibHandle, 'ActiveForm'); 
         FActiveForm := FarPointer; 
         FarPointer  := GetProcAddress(FLibHandle, 'CloseForm'); 
         FCloseForm  := FarPointer; 
         if Assigned(FShowForm) then 
           //FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle); 
           List.add(FShowForm(Application, @CallBackProc, FLibHandle, self, panel1.Handle)); 
       end; 
     end 
     else 
     begin 
       if Assigned(FActiveForm) then 
       begin 
         FActiveForm; 
       end; 
     end; 
    end; procedure TfrmMain.mmFileCloseClick(Sender: TObject); 
    begin 
     if FLibHandle  <> 0 then 
       FCloseForm; end; procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction); 
    begin 
      if FLibHandle  <> 0 then 
        FCloseForm; 
      if assigned(FFrm) then 
        FreeAndNil(FFrm); 
    end; procedure TfrmMain.mmFileOpenFrmClick(Sender: TObject); 
    begin 
      if not assigned(FFrm) then 
      begin 
        FFrm := TForm1.Create(nil); 
        with FFrm do 
        begin 
          ParentWindow := panel1.Handle; 
          align := alClient; 
          BorderStyle := bsNone; 
          BorderIcons := []; 
        end; 
      end; 
      FFrm.Show; 
    end; procedure TfrmMain.N1111Click(Sender: TObject); 
    begin 
      FFrm.Edit2.Text := 'abc'; 
       
    end; procedure TfrmMain.Change1Click(Sender: TObject); 
    begin 
      if FFrm.ParentWindow = Panel1.handle then 
        FFrm.ParentWindow := Panel2.handle 
      else 
        FFrm.ParentWindow := Panel1.handle 
    end; procedure TfrmMain.FormCreate(Sender: TObject); 
    begin 
      List := TList.Create; 
    end; end. 
    //调用窗体End ps:
    你如何声明的
     myshowform1, 
      mycloseform1; 这两个方法