兄弟们,帮忙解决一下DLL嵌入窗体的问题.

时间:2022-12-12 19:03:10
我的dll是显示一个窗体,我想把它嵌入到调用它的主程序的一个panel里面.但是始终不能成功.现象是dll中的窗体已经create,但是没用显示出来.不知什么原因.
源码如下:
dll文件:
TForm* DLL_EXP showmyform(TApplication *ParentApplication,TForm *pForm ,TWinControl * _panel, int is_new)
{
    Application =  ParentApplication;

    if ((is_new==0)&&(fm_data_proc==NULL))
     fm_data_proc=new Tfm_data_proc(pForm);
    else
    {
        delete fm_data_proc;
     fm_data_proc=new Tfm_data_proc(pForm);
    }
    fm_data_proc->Parent = pForm;
    fm_data_proc->Show();

    return fm_data_proc;
}

主程序调用:
showmyform(Application,Form1,Panel1,0);

然而我把builder with runtime package勾上就可以.
请兄弟们帮我.有疑问请email我:wangwl@tydic.com

9 个解决方案

#1


在DLL中传递对象指针是可以的,但RTTI将不可用。而VCL中的实现代码大量使用了RTTI,所以在编写DLL中,不要使用VCL对象类型的参数。
BPL的优点就是可以使用RTTI。当你使用动态包编译时,调用程序和DLL中的VCL代码都在同一个包中,这时就可以使用VCL对象的RTTI了。
建议解决方法:
1:不在DLL与调用程序(或DLL与DLL)之间传递VCL对象。改为传递窗口句柄。DLL中可以使用VCL对象,但只限于内部使用。
2:不改原程序,改用动态VCL包编译。
     ____     ____
     \ p \   / g /
      \ l \_/ n /
       \ a   o /
        \ i s /
         \ n /
          \_/

#2


兄台说得有道理,但是能不能把我上面给出的代码用传递窗口句柄的方法修改一下,小弟感谢不已。

#3


void DLL_EXP showmyform(HWND *ParentWin , int is_new)
{
    Application->Handle =  ParentHandle;

    if ((is_new==0)&&(fm_data_proc==NULL))
     fm_data_proc=new Tfm_data_proc(Application);
    else
    {
        delete fm_data_proc;
     fm_data_proc=new Tfm_data_proc(Application);
    }
    fm_data_proc->Parent = ParentWin;
    fm_data_proc->Show();

    return fm_data_proc;
}
主程序调用:
showmyform(Form1->Handle,0);

首先plainsong说得有道理,最好不在参数中使用VCL对象

#4


不要用dll了,dll已经落伍了。

#5


不要用dll了,dll已经落伍了。

#6


不要用dll了,dll已经落伍了。

#7


RedProgramer你的这个把dll中的窗体嵌入到主程序的form中是可以实现的,但是我想要把dll中的窗体嵌入到主程序的panel中就不行了,兄弟在努力一下,我回给分的。

#8


还有你的那一句 fm_data_proc->Parent = ParentWin 会报错的
[C++ Error] DllEntry.cpp(47): E2034 Cannot convert 'void * *' to 'TWinControl *'!!!!
我的实现是这样的
TForm* DLL_EXP FDataProc(HWND parent_handle, int is_new)
{

    if ((is_new==0)&&(fm_data_proc==NULL))
     fm_data_proc=new Tfm_data_proc(Application);
    else
    {
        delete fm_data_proc;
     fm_data_proc=new Tfm_data_proc(Application);
    }
   SetParent(fm_data_proc->Handle,parent_handle);
   //fm_data_proc->Parent = dynamic_cast<TForm*>(FindControl(parent_handle));
    fm_data_proc->Show();
    fm_data_proc->Visible = true;

    return fm_data_proc;
}
可以实现。如果用注释的那一句fm_data_proc->Parent = dynamic_cast<TForm*>(FindControl(parent_handle));窗体弹出来了,没有嵌进去。
如果改为调用改为showmydll(panel1->handle,0),也就是把dll中的窗体嵌入到主程序的panel中就不行了。在线等待高手解答。

#9


为你的窗体类加一个构造函数:
__fastcall TForm1::TForm1(HWND ParentWnd)
:TForm(ParentWnd)
{
}
然后在创建窗体时用这个构造函数创建,参数就是它的父窗口句柄。

还有一点,就是你应该把主程序的Application -> Handle传递过来,参数类型也是HWND,把它赋给DLL中的Application->Handle,否则你的DLL也会显示在任务栏上。不过对程序没什么影响。
◥███◣              ◢███◤
  ◥◣P◥◣          ◢◤G◢◤
  ◥◣L◥◣      ◢◤N◢◤
     ◥◣A◥◣  ◢◤O◢◤
        ◥◣I◥█◤S◢◤
          ◥◣  N  ◢◤
            ◥███◤
     

#1


在DLL中传递对象指针是可以的,但RTTI将不可用。而VCL中的实现代码大量使用了RTTI,所以在编写DLL中,不要使用VCL对象类型的参数。
BPL的优点就是可以使用RTTI。当你使用动态包编译时,调用程序和DLL中的VCL代码都在同一个包中,这时就可以使用VCL对象的RTTI了。
建议解决方法:
1:不在DLL与调用程序(或DLL与DLL)之间传递VCL对象。改为传递窗口句柄。DLL中可以使用VCL对象,但只限于内部使用。
2:不改原程序,改用动态VCL包编译。
     ____     ____
     \ p \   / g /
      \ l \_/ n /
       \ a   o /
        \ i s /
         \ n /
          \_/

#2


兄台说得有道理,但是能不能把我上面给出的代码用传递窗口句柄的方法修改一下,小弟感谢不已。

#3


void DLL_EXP showmyform(HWND *ParentWin , int is_new)
{
    Application->Handle =  ParentHandle;

    if ((is_new==0)&&(fm_data_proc==NULL))
     fm_data_proc=new Tfm_data_proc(Application);
    else
    {
        delete fm_data_proc;
     fm_data_proc=new Tfm_data_proc(Application);
    }
    fm_data_proc->Parent = ParentWin;
    fm_data_proc->Show();

    return fm_data_proc;
}
主程序调用:
showmyform(Form1->Handle,0);

首先plainsong说得有道理,最好不在参数中使用VCL对象

#4


不要用dll了,dll已经落伍了。

#5


不要用dll了,dll已经落伍了。

#6


不要用dll了,dll已经落伍了。

#7


RedProgramer你的这个把dll中的窗体嵌入到主程序的form中是可以实现的,但是我想要把dll中的窗体嵌入到主程序的panel中就不行了,兄弟在努力一下,我回给分的。

#8


还有你的那一句 fm_data_proc->Parent = ParentWin 会报错的
[C++ Error] DllEntry.cpp(47): E2034 Cannot convert 'void * *' to 'TWinControl *'!!!!
我的实现是这样的
TForm* DLL_EXP FDataProc(HWND parent_handle, int is_new)
{

    if ((is_new==0)&&(fm_data_proc==NULL))
     fm_data_proc=new Tfm_data_proc(Application);
    else
    {
        delete fm_data_proc;
     fm_data_proc=new Tfm_data_proc(Application);
    }
   SetParent(fm_data_proc->Handle,parent_handle);
   //fm_data_proc->Parent = dynamic_cast<TForm*>(FindControl(parent_handle));
    fm_data_proc->Show();
    fm_data_proc->Visible = true;

    return fm_data_proc;
}
可以实现。如果用注释的那一句fm_data_proc->Parent = dynamic_cast<TForm*>(FindControl(parent_handle));窗体弹出来了,没有嵌进去。
如果改为调用改为showmydll(panel1->handle,0),也就是把dll中的窗体嵌入到主程序的panel中就不行了。在线等待高手解答。

#9


为你的窗体类加一个构造函数:
__fastcall TForm1::TForm1(HWND ParentWnd)
:TForm(ParentWnd)
{
}
然后在创建窗体时用这个构造函数创建,参数就是它的父窗口句柄。

还有一点,就是你应该把主程序的Application -> Handle传递过来,参数类型也是HWND,把它赋给DLL中的Application->Handle,否则你的DLL也会显示在任务栏上。不过对程序没什么影响。
◥███◣              ◢███◤
  ◥◣P◥◣          ◢◤G◢◤
  ◥◣L◥◣      ◢◤N◢◤
     ◥◣A◥◣  ◢◤O◢◤
        ◥◣I◥█◤S◢◤
          ◥◣  N  ◢◤
            ◥███◤