想法:
做一个通用的MDI主程序,菜单从数据表中动态创建!数据表中保存我需要用到的DLL,子窗体的名称等等!不同的系统,只用修改这个数据表内的数据,并拷贝相应的DLL就可以使用!
要实现的功能:
点击菜单动态的调用指定的DLL中的子窗体!
要求:
在DLL中写一个通用的函数或过程来创建并显示子窗体!
注意:同一个DLL中有N多个子窗体!现在需要的是这个DLL需要怎么写?也就是这个通用的函数或过程怎么写?

解决方案 »

  1.   

    利用包实现,通过传入父窗体句柄
    主窗体代码,下面代码中通过getdllname,getformname从数据表中获取dll和form名
    procedure TFrmMain.rundll(pDllName:String;pName:String);
    var
      dllHandle:Cardinal;
      ShowForm:TShowForm;
    begin
      dllHandle := LoadLibrary(PChar(pDllName));
      if dllHandle = 0 then
      begin
        Application.MessageBox(pChar('DLL[' + pDllName + ']无法载入'),
                               '错误', MB_ICONINFORMATION + MB_OK);
        Exit;
      end;
      if dllHandle <> 0 then
      begin
        ShowForm := GetProcAddress(dllHandle,'ShowForm');
        if @ShowForm <> nil then
        begin
          try
            ShowForm(Application, FrmMain, Screen, pchar(getFormName(pName)));
          except
            Application.MessageBox(pChar('[' + getFormName(pName) + ']打开失败'), '错误', MB_ICONINFORMATION + MB_OK);
          end;
        end;
      end;
    end;包中的showform
    procedure ShowForm(pApp: TApplication; pForm: TForm; pScr: TScreen; pFormName: PChar); cdecl;
    var
      Frm_New_Cls: TFormClass;
      Frm_New: TForm;
      LPtr: PLongint;
    begin
      Application:=pApp;
      Application.Handle := pApp.Handle;
      LPtr := @Application.MainForm;
      LPtr^ := longint(Application.MainForm);
      Screen := pScr;
      Frm_New_Cls := TFormClass(FindClass('T' + pFormName));
      OpenForm(Frm_New_Cls, Frm_New, pApp);
      Frm_New.FormStyle := fsMDIChild;
    end;dll的资源文件里加上
    var
       DllApplication:TApplication;
       DllScreen:TScreen;
    {$R *.res}
    procedure DllUnLoadProc(Reason: Integer);register;
    begin
      if Reason = DLL_PROCESS_DETACH then
        begin
          Application := DllApplication;
          Screen := DllScreen;
        end;
    end;exports ShowForm;begin
      DllApplication := Application;
      DllScreen := Screen;
      DllProc := @DLLUnloadProc;
    end.
    测试能用
    给分把
      

  2.   

    用COM来实现是最好的。
    IMy业务=interfaced
      {GUID}
      procedure show(app,scr:Integer;mainHandle:THandle);
    end;TMy业务=class(tcomobject,IMy业务)
    public
      procedure show(app,scr:Integer;mainHandle:THandle);
    end;procedure show(app,scr:Integer;mainHandle:THandle);
    var
     form:tform;
    begin
      //创建窗体
    end;不同的GUID对应不同的业务,主窗体不用管子窗体内部是如何操作的。只要将必须的结果通过消息进行交互就可以了。
      

  3.   

    请 andyyinchong 上传 OpenForm(Frm_New_Cls, Frm_New, pApp);的OpenForm过程!
    谢谢!
    还有就是你说的包是要怎么写?我是新手!请多指点下!谢谢!
      

  4.   

    这个忘记传了
    function OpenForm(FormClass: TFormClass; var NewForm; AOwner:
      TComponent): boolean;
    var
      i: integer;
      New_Form: TForm;
    begin
      result := false;
      for i := 0 to Screen.FormCount - 1 do
      begin
        if Screen.Forms[i].ClassType = FormClass then
        begin
          New_Form := Screen.Forms[i];
          if New_Form.WindowState = wsMinimized then
            ShowWindow(New_Form.handle, SW_SHOWNORMAL)
          else
            ShowWindow(New_Form.handle, SW_SHOWNA);
          if (not New_Form.Visible) then
            New_Form.Visible := True;
          New_Form.BringToFront;
          New_Form.Setfocus;
          TForm(NewForm) := New_Form;
          result := true;
          exit;
        end;
      end;
      New_Form := TForm(FormClass.NewInstance);
      TForm(NewForm) := New_Form;
      New_Form.Create(AOwner);
    end;
      

  5.   

    请 andyyinchong 上传getFormName(pName)的getFormName!
    如果我不用getFormName(pName),而且只用pName的话,
    ShowForm中的  Frm_New_Cls := TFormClass(FindClass('T' + pFormName));
    就报错拉!
    错误信息: Class TChild_Form1 not Found.
      

  6.   

    感谢 andyyinchong 
    这个问题困扰我很久拉!终于搞定拉!谢谢!