DLL中的MDI窗口问题.(首次拜访大富翁,请多指教)(100分)

  • 主题发起人 主题发起人 rss
  • 开始时间 开始时间
R

rss

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢!小问题:
我在用CBuilder编程时,使用MYapp+DLL形式开发,问题是,主程序中的主Form定义为MDIForm,DLL中的Form定义为MDIChild,程序不能通过.DLL中的Form不能是MDI子窗口吗?该怎样实现?Delphi实现也可!
 
想在DLL中有Form,只需提供动态建立,初始化,访问它属性和数据的函数。
Form可以是任何类型。

Sample如下:(From <Delphi 3从入门到精通P648>)
Libraray FormDll;
uses
ScrollF in 'scrollf.pas'
exports
GetColor;
end;

在Scollf.pas除正常TForm1定义外,加上
一个function GetColor;

function GetColor(col:LongInt):LongInt;
begin
try
FormScroll:=TForm1.Create(Application);
with FormScroll do
begin
//init some data
if ShowModal = mrOK then
//set your return data
end;
finally
FormScroll.Free;
end;
Except
On E:Exception do
ShowMessage('Error in Form DLL');
end


end;
end;
 
Hmmm....
就我所知MDI子窗口在DLL中与一般窗口完全不同,
谁要是能搞定,我也愿意学习学习 :)
 
jiangtao的回答不正确,您没有理解我的意思,
是在主程序定义一个MDIForm,DLL中定义MDIChild,
您的例子所定义的窗口不能是MDIChild,不信试试,
如真能通过请Mail(rss@188.net)给我一个实例,谢谢!
dwwang明白我的意思,
这是个不难的难题,
但是肯定可以实现,Delphi本身的datadabse dekstop,
就使用了此技术.
 
OK,我想我已经发现答案了,
待我试验一下,就给出结果.

另:请教如何得知:
"Delphi本身的datadabse dekstop,就使用了此技术."

 
我猜测database desktop使用此技术,因为此程序是MDI式的应用,
但主程序只139kb,其他均在十余个DLL中,特别有dbdide32.dll,其
不同的MDI子窗口分布在不同的DLL中,其编程使用borland C++5,
我要实现的目的就是要分解重用程序,一个简单的数据库应用delphi程序
已过2M,另外,在PowerBuilder中这是很容易实现的.
dwwang,您如能实现太好了!,
我猜测把MDI主窗口,子窗口,放于同一个DLL可能可以,不过并没有解决问题.
 
我有一个问题,你现在通不过的程序中,
MDI主窗口是在EXE里还是DLL里?

另外,可不可以把你的创建MDI子窗口
的接口部分贴上来看看?
(即:DLL中创建子窗口的过程和主窗口的调用语句)
 
MDI主窗口在EXE中,MDI子窗口在DLL中.
DLL中:
C++builder:
int DLLW()
{
TMDIChild *Child;

//--- create a new MDI child window ----
Child = new TMDIChild(NULL)
//不能是Application
return 1;
}
Delphi:
Function DLLW(string name): Integer;stdcall;
begin
ChildForm:= TMdiChild.Create(Application);
ChildForm.Caption:=name;
Result:=1;
end;
调用(调用Cbuilder编的DLL):
CBilder:
void __fastcall TMainform::Mdichild(void)
{
HINSTANCE lib1;
MYPROC DLL1;
int re

lib1=LoadLibrary("D1.DLL");
DLL1=(MYPROC)GetProcAddress(lib1,"DLLW");
aa=DLL1()

FreeLibrary(lib1);
}
以上如是普通窗通过,MDI子窗则错,可能问题在TMdiChild.Create(Application)
的Application定义上.
 
>>"可能问题在TMdiChild.Create(Application)
的Application定义上."

应该是这个问题,有两点我怀疑:
1.Delphi的DLL中TMdiChild.Create(Application)
这个Application是从哪里来的呢?
2.既然Delphi的DLL中可以用TMdiChild.Create(Application)
为什么CB中必须用NULL呢?
 
到底该如何可以解决?
 
我知道MDI子窗口在create的时候需要检查
Application.Mainform.ClientHandle.
因此同意你所说的
"可能问题在TMdiChild.Create(Application)的Application定义上."

我并不是故意调胃口,确实是想问上面那两个问题,
如果知道如何在Delphi的DLL中获取正确的Application对象,
或者知道"new TMDIChild(NULL)"中的NULL对Application
有什么影响,从而就可以知道问什么不能创建MDI子窗口了.

我设想的解决方案:如果new TMDIChild(NULL)中的参数
也是TApplication类的话,就把当前运行程序的Application
传给DLL中的函数 -- int DLLW(MyApp:TApplication)
然后new TMDIChild(MyApp).

由于只是设想,所以才问上面那两个问题 :)
 
sorry,I misunderstand your qustion.
问题的关键我找到了,

从 Forms.Pas可以看到下面这一段:

procedure TCustomForm.CreateWindowHandle(const Params: TCreateParams);
var
CreateStruct: TMDICreateStruct;
begin
if (FormStyle = fsMDIChild) and not (csDesigning in ComponentState) then
begin
if (Application.MainForm = nil) or
(Application.MainForm.ClientHandle = 0) then
raise EInvalidOperation.Create(SNoMDIForm);
。。。

procedure TCustomForm.SetFormStyle(Value: TFormStyle);
var
OldStyle: TFormStyle;
begin
if FFormStyle <> Value then
begin
if (Value = fsMDIChild) and (Position = poDesigned) then
Position := poDefault;
if not (csDesigning in ComponentState) then DestroyHandle;
OldStyle := FFormStyle;
FFormStyle := Value;
if ((Value = fsMDIForm) or (OldStyle = fsMDIForm)) and not Ctl3d then
Color := NormalColor;
if not (csDesigning in ComponentState) then UpdateControlState;
if Value = fsMDIChild then Visible := True;
end;
end;


问题的关键是在Dll中如何将其Application.MainForm设成应用程序中MainForm
遗憾的是MainForm是一个read only property,我可不想改souce code

用VC/BC都不会有这个问题,因为他们根本没有象Delphi/C++ Builder
TApplication这种变量

我想是否可以在Dll Form的Createwnd中直接将WndClassName ='MDICLEINT',
I'll try it!

 
还是不成功.另:Child = new TMDIChild(NULL)
//不能是Application
有误,应为 Child = new TMDIChild(Application)
//也可是NULL
dwwang,如您成功请mail(rss@188.net)一个实例,delphi,Cbuilder均可.
 
搞定,强行修改application.mainform即可
例子给你e-mail过去
主要就是:

function ShowForm(mainForm:TForm):TForm;stdcall
var
Form1: TFormDll;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);
ptr^:=LongInt(mainForm);
Form1:=TFormDLL.Create(mainForm);
Form1.Show;
result:=Form1;
end;
 
rss:
可否把你的程序寄给我,我来试验另一种方法.
 
(我的脑子大概出了点儿问题 :))

jiangtao:请把你的例子寄给我一份好吗?谢谢。
 
OK,我自己做了试验,但是成功了一半:
按照声明过程的办法可以成功,
但按照LoadLibrary却不正常?
 
哇!连续四个帖子真够累的。

jiangtao:我收到你的信之前自己也试了一下,
按照你说的强行改Mainform的办法,结果见上一个帖子。
另外你的那些其它过程好像并不需要,只需要你前面贴的那个就可以。
 
感谢两位高手赐教,由于我只在工作时间上网,所以刚看到两位
的高见,我昨天回家后也想到问题在MainForm,没有机器没试.
例子收到,已成功运行,静态调用dll,动态调用dll均成功,
但我将此方法转到Cbuilder时还有问题,我再试试.

dwwang说动态调用不成功,我看了程序,问题在dll中:
exports DLLCreateChild index 1
//以索引访问
改为:
exports DLLCreateChild name DLLCreateChild;
就可.
再次表示谢意.
 
Hi,不要就这样结束嘛!
转到Cbuilder时还有什么问题,也继续讨论一下。
说实话,论坛里高水平的问题也不是特别多,
好不容易碰到一个,不要就此罢手!
 
后退
顶部