关于DLL中封装MDI窗体的问题.
一个很奇怪的现象,请高手解释一下怎幺会这样?
Dll里面封装MDI窗体,有时第一次运行程序时要报错,但是一行代码都不改你再运行一次就什幺问题都没有了,以后你再运行程序有时报错,有时不报错。程序运行时DLL里面的窗体也正常弹出,一切功能都能用。更奇怪的是DLL里面的窗体你弹多少个出来都没问题,关掉也没问题,但是不能全部关完,必须留一个,如果把窗体全关完,你再想新弹出一个DLL中的窗体,程序就报错。只要留一个窗体,那幺随你新建,随你关都不报错。这是怎幺回事?
我的DLL是动态装载的。编绎时Use Dynamic RTL和Build with Runtime Packages
都是点上的。
把窗体关完后再新建,在DLL里面这条语句报错:Child=new frmMDI(Application)报错:说什么Abstract Error错误.然后程序跳到Forms.hpp里面的/*TcurstomForm.CreateNew*/inline __fastcall virtual Tform(classes::Tcomponent *Aowner,int Dummy):TcustomForm(Aowner,Dummy){};这一行上.
问题点数:100、回复次数:13Top
1 楼Behard(我爱天安门)回复于 2002-11-26 11:48:37 得分 0
???
Top
2 楼smailsuper(天高云淡)回复于 2002-11-26 12:28:25 得分 0
Behard(想象休息中......这个星期去踢球) :
有什麼地方沒說清嗎?
Top
3 楼yuanque(无心快语)回复于 2002-11-26 12:52:21 得分 0
不明白,把关键的地方贴出来看看吧Top
4 楼smailsuper(天高云淡)回复于 2002-11-26 13:01:26 得分 0
//加载dll
void __fastcall TMainForm::LoadBiaoQian(AnsiString Path,TMenuItem *MenuName)
{
AnsiString sCaption;
AnsiString LoadPath=Path+"*.*";
TSearchRec sr;
HINSTANCE hinsts;
AnsiString (__stdcall *GetName)()=NULL;
if(FindFirst(LoadPath,faAnyFile,sr)==0 )
{
do{
if(ExtractFileExt(sr.Name).UpperCase()==".DLL")
{
hinsts=LoadLibrary((Path+sr.Name).c_str());
(FARPROC)GetName=GetProcAddress(hinsts,"GetDllName");
if(GetName)
{
sCaption=GetName(); //调用dll函数
TMenuItem *NewItem=new TMenuItem(MenuName);
NewItem->Caption=sCaption;
MenuName->Add(NewItem);
HPosList->Add(hinsts); // HposList=TList
NewItem->OnClick=DllPosClick;
break;
}
else
FreeLibrary(hinsts);
}
} while(FindNext(sr)==0);
FindClose(sr);
}
}
//调用dll中的函数
void __fastcall TMainForm::DllPosClick(TObject *Sender)
{
if(Connection1->Connected==false)
{
if(!ConnectToDB(Connection1)) // 检测数据库是否连接
return;
}
if(Connection1->Connected==true)
{
int iPos;
void (__stdcall *GetDll)(TApplication *,TADOConnection *,HWND,int)=NULL;
TMenuItem *DllMenu;
DllMenu=(TMenuItem *)((TMenuItem *)Sender)->Parent;
iPos=DllMenu->IndexOf((TMenuItem *)Sender);
(FARPROC)GetDll=GetProcAddress((HINSTANCE)(HPosList->Items[iPos]),"Execute");
if(GetDll)
{
// DllMenu->Items[iPos]->Enabled=false;
GetDll(Application,Connection1,Handle,iPos);
}
}
}
Top
5 楼smailsuper(天高云淡)回复于 2002-11-26 13:23:22 得分 0
是不是我说的不明白。简单点说就是比如我有个菜单名叫新建.我一点就新建一个子窗体,我建三个子窗体后,再把这三个子窗体关掉,然后我再点新建,这时程序就报错。如果我建三个子窗体后只关掉其中二个,然后再点新建,并不出错。这是怎么一回事?Top
6 楼smailsuper(天高云淡)回复于 2002-11-26 13:36:49 得分 0
急死了。UPTop
7 楼jishiping(JSP 季世平)回复于 2002-11-26 16:33:24 得分 5
不建议在DLL中使用MDIChild窗口,否则会有很多问题。有一段时间,我研究了一下,结果是解决了一个问题,又会出现其它地问题。总之,这是由VCL的限制,我个人觉得VCL在MDI这方面做的不好,反正就是不要将MDIChild做在DLL里。Top
8 楼smailsuper(天高云淡)回复于 2002-11-26 17:03:02 得分 0
我现在也觉得是这样了。但是骑虎难下了。经我不断测试发觉是我传到DLL里面的TADOConnection对象惹的祸,把他去掉就什么事也没了。加上他就出错。
能不能给个好的建义,让DLL能与主程序共享一个连接?
Top
9 楼Behard(我爱天安门)回复于 2002-11-27 09:34:05 得分 5
感觉象是没有处理好 Dll 中的 Application 的释放
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
if ( (reason==DLL_PROCESS_DETACH) && SaveApp )
Application = SaveApp ;
return 1;
}
//Dll.Cpp
TApplication* SaveApp = NULL ;
在调用 Dll 函数中加上
if ( SaveApp == NULL ) { SaveApp = Application ; }
Top
10 楼smailsuper(天高云淡)回复于 2003-01-03 11:02:57 得分 0
在DLL裡面new一個窗體的時候,不要用全局的窗體實例變量,用局部變量就行了Top
11 楼smailsuper(天高云淡)回复于 2003-01-03 11:05:56 得分 0
呵呵Top
12 楼ThinkX(秋天的树)回复于 2003-01-03 11:09:20 得分 10
去Delphi版,那里有很多的解答,在FAQ中有一篇,很不错。Top
13 楼smailsoft(七匹狼)回复于 2003-01-03 11:10:17 得分 80
game overTop




