CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C++ Builder >  基础类

关于显示DLL中Frame的方法.急,高手请进!

楼主hongchen363(电脑爆)2006-05-03 23:23:00 在 C++ Builder / 基础类 提问

我在DLL中包含了一个Frame,Dll原程序如后.  
  现在的问题是如果何在项目表单中显示出此Frame.  
  请写出调用方法,谢谢!  
   
  #include   <vcl.h>            
  #include   <windows.h>  
  #include   "frame.h"         //此处为包含Frame的头文件,Frame中只有一个按钮.  
  #pragma   hdrstop  
   
  #pragma   argsused  
  int   WINAPI   DllEntryPoint(HINSTANCE   hinst,   unsigned   long   reason,   void*   lpReserved)  
  {  
        return   1;  
  }  
   
  //定义引出---------------------------------------------------------------------------  
  extern   "C"   __declspec(dllexport)   __stdcall   void   ShowFrame(TForm*   MainForm);  
   
  //显示Frame  
  __declspec(dllexport)   __stdcall   void   ShowFrame(TForm*   MainForm)  
  {  
            TFrame1   *Frame2;  
            Frame2=new   TFrame1(MainForm);  
            Frame2->Parent=MainForm;  
            Frame2->Align=alClient;  
            Frame2->Visible=true;  
  } 问题点数:100、回复次数:10Top

1 楼dxkh(沧海一粟)回复于 2006-05-04 09:21:27 得分 10

帮你顶。  
  学习Top

2 楼hongchen363(电脑爆)回复于 2006-05-04 15:01:24 得分 0

高手跑哪去了啊!  
  自己顶一下Top

3 楼day_dreamerabc(流浪牛)回复于 2006-05-04 15:07:15 得分 10

没有用过Frame,深表关注Top

4 楼jjwwang((空园歌独酌,春日赋闲居))回复于 2006-05-05 15:16:53 得分 0

参考一下吧.虽然是建立一下FORM.但意思一样.  
   
  There   are   lots   of   resources   and   solutions   out   there   on   the   internet   that   are   specific   to   this   problem,   however,   in   using   the   BusinessSkinForm   components,   that   are   tightly   integrated   with   the   VCL   and   messaging,   I   came   across   a   few   problems   with   the   standard   approaches.    
   
  The   final   solution   came   with   the   assistance   of   Steve   Woods   (aka   Reconics).    
   
  The   main   problem   with   storing   Forms   in   dlls   and   being   able   to   create   instances   of   them   from   within   a   host   exe   is   that   when   Delphi   compiles   up   a   dll,   it   has   its   own   TApplication   and   TScreen   instances   (as   well   as   other   info   as   to   be   discovered).    
   
   
  This   means   that   the   DLL   and   the   EXE   message   loops   are   different,   the   RTTI   information   is   different,   and   causes   lots   of   problems   like   the   well   know   "cannot   assign   a   TFont   to   a   TFont"   message.    
   
   
  So   how   do   we   Coax   the   form   in   the   DLL   to   think   it   is   part   of   the   EXE,   we   replace   the   Application   and   Screen   Object   in   the   DLL   with   the   reference   to   the   EXE's   Application   and   Screen.    
   
   
  This   is   a   standard   approach   that   you   will   find   on   the   net.   However   there   is   one   additional   element   that   needs   to   be   passed   from   EXE   to   DLL   and   this   is   the   tricky   one.    
   
   
  From   Steve   Woods   -    
   
  “The   problem   is   caused   by   the   ControlAtom   local   variable   in   the   Controls.pas   units.   When   the   controls   unit   initializes   it   creates   a   global   atom   based   on   the   string   'ControlOfs'   +   the   HInstance   and   thread   ID   of   the   application   and   stores   the   atom   in   the   ControlAtom   local   variable.    
   
  All   well   and   good.   Then   when   new   wincontrols   are   added   to   the   application   a   pointer   to   the   control   is   stored   under   the   window   handle   using   the   SetProp   API   function.   This   allows   Delphi   to   get   the   TWinControl   of   a   Handle.    
   
  The   CM_MouseEnter   etc.   events   are   generated   from   the   TApplication.DoMouseIdle   method.   In   order   to   get   the   current   wincontrol   under   the   mouse,   and   thus   pass   the   required   messages,   its   searches   for   a   property   with   a   Atom   equal   to   the   local   ControlAtom   variable   stored   in   the   Controls   units.    
   
  This   all   works   fine   for   standalone   apps   but   when   you   start   putting   forms   in   DLL's   the   following   happens:    
   
  The   controls   unit   is   initialized   again   for   the   DLL.   This   creates   a   new   global   atom   and   stores   it   in   the   Controls   unit   local   variable,   so   you   now   have   TWO   control   global   atoms,   one   for   the   main   app   and   one   for   the   DLL.    
   
  And   thus,   when   the   Application.DoMouseIdle   method   tries   to   find   a   property   stored   with   the   same   name   (atom)   as   the   application   on   a   DLL   form,   it   fails.   To   solve   this   I   had   to   hack   the   controls.pas   units   a   little.   I   added   a   routine   :   Function   GetControlAtom   :   Pointer   that   returns   @ControlAtom   from   the   controls   units.    
   
  Then   in   your   DLL's   you   initialize   by   passing   the   ControlAtom   from   the   application   Controls   units   and   set   this   value   in   the   Controls   unit   of   the   DLL:  
   
  eg    
   
  Library   ADLL;   Uses       ...       forms,       Controls,   //Add   this   here   so   it   initializes   unit   before   we   try   and   change   GetControlAtom;       ...    
  procedure   CreateForm(App   :   TApplication;Scr   :   TScreen;RealControlAtom   :   Integer);   Var       P   :   ^Word;   Begin       If   (OldApp   =   Nil)   Then       Begin           OldApp   :=   Application;           OldScr   :=   Screen;           P   :=   GetControlAtom;           OldAtom   :=   P^;           Application   :=   App;           Screen   :=   Scr;           P^   :=   RealControlAtom;       end;       TForm1.Create(Application.MainForm);   end;    
  and   make   sure   you   clean-up   before   you   unload   the   dll."    
   
  Stage   1)   The   ControlAtom   variable   is   private   to   the   controls.pas   unit   so   we   need   to   change   Controls.pas   for   the   EXE   and   DLL   projects    
   
   
  Take   a   copy   of   controls.pas   from   the   delphisourcevcl   directory   and   save   it   into   a   directory   that   the   EXE   project   and   DLL   project   can   access.    
   
  In   the   Interface   Section   add   the   function   declaration   for   the   function   that   will   return   the   address   of   the   current   ControlAtom   variable.    
   
   
      function   GetControlAtom   :   pointer;    
   
  In   the   implementation   section   add   the   GetControlAtom   function.    
   
   
      function   GetControlAtom   :   pointer;   begin   result   :=   @ControlAtom;   end;  
   
  We   now   have   an   exposed   function   that   will   return   the   address   of   the   Control   Atom   Variable.    
   
  Stage   2)   Setting   up   the   DLL   exported   functions    
   
   
  Add   the   modified   Controls.pas   to   the   project   so   it   appears   in   the   Project   manager.   Delphi   will   then   use   this   source   in   preference   to   the   standard   controls.dcu.    
   
  We   now   need   to   provide   a   DLLInitialization   procedure   and   a   DLLFinalization   Procedure.   The   DLLInitialization   must   be   called   before   trying   to   use   any   forms   from   the   DLL,   usually   this   is    
   
  called   just   after   loading   the   dll   into   memory.   The   DLLFinalization   procedure   should   be   called   before   the   DLL   is   unloaded   from   memory.    
   
  Below   is   an   example   of   the   code   needed   to   be   exposed   in   the   DLL.   Notice   the   dll   exports   3   functions/procedures   DLLInitiailize,   DLLFinalize   and   GetInstance    
   
  GetInstance   is   the   call   that   actually   returns   an   instance   of   a   the   dlls   Form.    
   
   
  library   plugin;   uses       ShareMem,       SysUtils,       Classes,       Windows,       Forms,       Controls   in   'Controls.pas',         pluginform   in   'pluginform.pas'   {MyPlugin};    
  {$R   *.res}    
  var         OldApp   :   TApplication;       OldScreen   :   TScreen;       OldControlAtom   :   TAtom;    
  procedure   DLLInitialize(App   :   TApplication;   Scr   :   TScreen;   RealControlAtom   :Integer);   var       x   :   pointer;       p   :   ^Word;   begin       If   (OldApp   =   Nil)   Then       Begin           //   store   away   the   current   application,   screen   and   control   atom           OldApp   :=   Application;           OldScreen   :=   Screen;           p   :=   GetControlAtom;           OldControlAtom   :=   p^;           //   Assign   the   EXE's   application,   screen   and   control   atom           Application   :=   App;           Screen   :=   Scr;           p^   :=   RealControlAtom;       end;       ASkin   :=   Skin;   end;   function   GetInstance(AOwner   :   TComponent)   :   TForm;   begin       //   create   an   instance   of   the   form       result   :=   TMyPlugin.create(Application.MainForm);   end;   procedure   DLLFinalize;   var       p   :   ^Word;   begin       //   restore   the   DLL's   application,   screen   and   control   atom       p   :=   GetControlAtom;       p^   :=   OldControlAtom;       Screen   :=   OldScreen;       Application   :=   OldApp;   end;   exports       GetInstance,   DLLInitialize,   DLLFinalize;   begin       OldApp   :=   nil;       OldScreen   :=   nil;       OldControlAtom   :=   0;   end.    
  Stage   3)   Setting   up   the   EXE.    
   
  Add   the   modified   Controls.pas   to   the   project   so   it   appears   in   the   Project   manager.   Delphi   will   then   use   this   source   in   preference   to   the   standard   controls.dcu.    
   
  Declare   some   procedure   /   function   types   to   be   used   to   reference   the   exported   procs   in   the   dll.    
   
   
  type       TDLLInitialize   =   procedure   (App   :   TApplication;   Scr   :   TScreen;   RealControlAtom   :  
                                   
  Top

5 楼hongchen363(电脑爆)回复于 2006-05-05 16:50:08 得分 0

显示DLL中的Form表单我是会的.  
   
  不过显示Frame就不行了.  
  Top

6 楼jjwwang((空园歌独酌,春日赋闲居))回复于 2006-05-05 17:44:45 得分 0

绝不是显示FORM的事情呀Top

7 楼jjwwang((空园歌独酌,春日赋闲居))回复于 2006-05-05 22:01:57 得分 80

/*  
  以下代码在WIN2003企业版+BCB6下通过.  
                                                  by   风归叶  
  转载请保证文档的完整性  
  */  
  //DLL  
  //---------------------------------------------------------------------------  
  #include   <System.hpp>  
  #include   <vcl.h>  
  #include   <windows.h>  
  #include   "AADD.h"  
  #pragma   hdrstop  
  //---------------------------------------------------------------------------  
  #pragma   argsused  
  TFrame   *f;  
  int   WINAPI   DllEntryPoint(HINSTANCE   hinst,   unsigned   long   reason,   void*   lpReserved)  
  {  
      if(   reason==DLL_PROCESS_DETACH   )  
          delete   f;  
   
      return   1;  
  }  
  //---------------------------------------------------------------------------  
  extern   "C"  
  {  
  __declspec(dllexport)   void   __stdcall   ShowFrame(TWinControl   *P);  
  }  
   
  void   __stdcall   ShowFrame(TWinControl   *P)  
  {  
      f   =   new   TFrame(P);  
      f->ParentFont   =   false;  
      f->Parent   =   P;  
      f->Font->Color   =   clRed;  
      f->Left   =   10;  
      f->Top   =   10;  
      f->Width   =   150;  
      f->Height   =   150;  
      f->Color   =   clRed;  
      ShowWindow(f->Handle,   SW_SHOW);  
  }Top

8 楼jjwwang((空园歌独酌,春日赋闲居))回复于 2006-05-05 22:02:28 得分 0

//---------------------------------------------------------------------------  
  #include   <System.hpp>  
  #include   <vcl.h>  
  #pragma   hdrstop  
   
  #include   "Unit1.h"  
  //---------------------------------------------------------------------------  
  #pragma   package(smart_init)  
  #pragma   resource   "*.dfm"  
  TForm1   *Form1;  
  HINSTANCE   h;  
  //---------------------------------------------------------------------------  
  __fastcall   TForm1::TForm1(TComponent*   Owner)  
                  :   TForm(Owner)  
  {  
  }  
  //---------------------------------------------------------------------------  
  void   __fastcall   TForm1::Button1Click(TObject   *Sender)  
  {  
      h   =   LoadLibrary(   "Project1.dll"   );  
      if(   !h   )  
      {  
          ShowMessage("LOAD   ERROR");  
          return;  
      }  
      typedef   void   __stdcall   PShowFrame(TWinControl   *F);  
      PShowFrame   *p   =   (PShowFrame   *)GetProcAddress(   h,   "ShowFrame"   );  
      if(   p   )  
        (*p)(   Form1   );  
  }  
  //---------------------------------------------------------------------------  
   
  void   __fastcall   TForm1::Button2Click(TObject   *Sender)  
  {  
      Caption   =   this->ControlCount;                  
  }  
  //---------------------------------------------------------------------------  
  void   __fastcall   TForm1::FormClose(TObject   *Sender,   TCloseAction   &Action)  
  {  
      FreeLibrary(   h   );  
  }  
  //---------------------------------------------------------------------------  
  Top

9 楼jjwwang((空园歌独酌,春日赋闲居))回复于 2006-05-05 22:02:45 得分 0

//---------------------------------------------------------------------------  
   
  #ifndef   Unit1H  
  #define   Unit1H  
  //---------------------------------------------------------------------------  
  #include   <Classes.hpp>  
  #include   <Controls.hpp>  
  #include   <StdCtrls.hpp>  
  #include   <Forms.hpp>  
  //---------------------------------------------------------------------------  
  class   TForm1   :   public   TForm  
  {  
  __published: //   IDE-managed   Components  
                  TButton   *Button1;  
                  TButton   *Button2;  
                  void   __fastcall   Button1Click(TObject   *Sender);  
                  void   __fastcall   Button2Click(TObject   *Sender);  
                  void   __fastcall   FormClose(TObject   *Sender,   TCloseAction   &Action);  
  private: //   User   declarations  
  public: //   User   declarations  
                  __fastcall   TForm1(TComponent*   Owner);  
  };  
  //---------------------------------------------------------------------------  
  extern   PACKAGE   TForm1   *Form1;  
  //---------------------------------------------------------------------------  
  #endifTop

10 楼hongchen363(电脑爆)回复于 2006-05-05 23:54:40 得分 0

苦等两天的问题终于成了!  
  在此特别感谢   jjwwang(风归叶)   朋友.  
  也感谢各位对此问题表示了关注的朋友!  
  结帖给分!      
     
  Top

相关问题

关键词

得分解答快速导航

  • 帖主:hongchen363
  • dxkh
  • day_dreamerabc
  • jjwwang

相关链接

  • CSDN Blog
  • 技术文档
  • 代码下载
  • 第二书店
  • 读书频道

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo