往DLL动态库函数传送对象时出错(50分)

  • 主题发起人 主题发起人 siaosa
  • 开始时间 开始时间
S

siaosa

Unregistered / Unconfirmed
GUEST, unregistred user!
往DLL动态库函数传送对象时出错<br>在一个DLL项目中申明以下函数,这样对吗?<br>function fBool_ExistMDIForm(MainForm,MDIForm:TForm):Boolean;stdcall;<br>//MainForm为MDI主表单,MDIForm为MDI子表单<br>var<br>&nbsp; i:Integer;<br>begin<br>&nbsp; i:=0;<br>&nbsp; while i&lt;MainForm.MDIChildCount do<br>&nbsp; begin<br>&nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; if MainForm.MDIChildren.Name=MDIForm.Name then<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//如果找着同名的子表单则程序退出循环<br>&nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;i:=i+1;<br>&nbsp; &nbsp; end;<br>&nbsp; end;<br><br>&nbsp; &nbsp;if MainForm.MDIChildren.Name=MDIForm.Name then<br>&nbsp; &nbsp; &nbsp; Result:=True &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //找到同名的表单返回真,否则退回假<br>&nbsp; &nbsp;else<br>&nbsp; &nbsp; &nbsp; Result:=False;<br>end;<br><br>调用方式在MDI子表单的OnActivate代码中调用,Form1是MDI主表单名<br>&nbsp; if fBool_ExistMDIForm(Form1,self) then<br>&nbsp; begin<br>&nbsp; &nbsp; &nbsp;showmessage('已经运行了一个实例');<br>&nbsp; end;<br><br>程序在运行时报错 Access violation at address 00281f0e in modul 'XXXXXX.DLL'. Read of address 00000008<br><br>如果将DLL中的.Name改成.Caption,程序不报错,但运行结果不对,不知道为什么。<br>
 
老兄還沒搞好嘛,改用句柄不行嗎 &nbsp;
 
在dll中,mdi主窗口的mdichilcount和children不能正确返回其值!所以出错
 
TO:kycheung<br>用句柄怎么弄? 我不知道,给个示例行吗?
 
示例是沒有啦,我以前也做過這樣一個DLL文件用來檢測主窗體是否已運行。直接用窗體名稱是不能在另外一個程序中找到。所以在函數參數傳遞時要用句柄
 
TO:kycheung<br>能把您DLL的原码发给我看一下吗?
 
兄 弟,不是 我不舍得,是程序放在家里,現在在上班啊!如果不怕遲,晚上發給你!<br>kycheung@yeah.net
 
个人认为,最好不要在DLL里面控制主form的东西
 
TO:kycheung<br>我的email: lxsmake@163.net<br>先谢过了
 
兄弟,Form.Name是个string类型。你试试两端项目文件中加上ShareMem单元试试。<br><br>不过我有一个好办法:<br>在项目两端分别定义一个消息常量和两个响应值:<br>const<br>&nbsp; WM_QUERYMAINFORM = WM_USER + 400;<br>&nbsp; RESPONSE_AGREE = $1888;<br>&nbsp; RESPONSE_DENY = $1889;<br>然后在主Form端中加一个消息句柄:<br>&nbsp; procedure WmQueryMainForm(var message: TMessage); message WM_QUERYMAINFORM;<br>&nbsp; var<br>&nbsp; &nbsp; P: PChar;<br>&nbsp; &nbsp; S: string;<br>&nbsp; &nbsp; I: Integer;<br>&nbsp; begin<br>&nbsp; &nbsp; message.Result := RESPONSE_AGREE;<br>&nbsp; &nbsp; P := PChar(Pointer(message.LParam));<br>&nbsp; &nbsp; S := StrPas(P);<br>&nbsp; &nbsp; for I := 0 to Pred(MDIChildCount) do<br>&nbsp; &nbsp; &nbsp; if AnsiUpperCase(S) = AnsiUpperCase(MDIChildren.ClassName) then<br>&nbsp; &nbsp; &nbsp; begin<br>&nbsp; &nbsp; &nbsp; &nbsp; message.Result := RESPONSE_DENY;<br>&nbsp; &nbsp; &nbsp; &nbsp; Break;<br>&nbsp; &nbsp; &nbsp; end;<br>&nbsp; end;<br>在子Form端的Form中加入一个类方法:<br>class function QueryMainForm(MainForm: TForm):Boolean;<br>var<br>&nbsp; P: PChar;<br>&nbsp; S: string;<br>begin<br>&nbsp; S := ClassName;<br>&nbsp; P := StrAlloc(Succ(Length(S));<br>&nbsp; try<br>&nbsp; &nbsp; StrPCopy(P, S);<br>&nbsp; &nbsp; Result := SendMessage(MainForm.Handle, WM_QUERYMAINFORM, 0, Integer(P)) = RESPONSE_AGREE;<br>&nbsp; finally<br>&nbsp; &nbsp; StrDispose(P);<br>&nbsp; end;<br>end;<br>注意,必须是类方法,在建立这个子Form前调用,如果成功则建立这个子Form否则,报错。<br>只能根据类名来查询而不能根据名称,因为类名是类方法而名称是实例方法。<br>
 
barton您的方法好像不是调用DLL吧?
 
奇了怪了,为什么不是调用DLL?明明给你说是宿主程序和DLL端的。<br>宿主程序项目无需引用子ChildForm的单元,DLL程序项目也无需引用MainForm的单元。<br>这种方式好象是Borland标准的方式。<br><br>如果在D5或以前的版本,不建议采用这种方式,但从D6开始,Delphi大量缩减了Forms单元<br>可能产生的目标二进制代码,所以将Forms单元分开进多个项目中并不会对目标二进制文件<br>的大小产生太大的影响。因此我个人认为,Borland正是出于对多个项目协同工作的方便出<br>发的。<br><br>如果以上代码稍加改进,可以用在不同的进程间的代码共享;如果在加上Socket机制,可以<br>在不同的主机上进行代码共享。这一点我已经实现了。我有个项目在windows下已经完全摆脱<br>DCOM/CORBA实现了远程调用(包括调用远程主机上的Form),当然远程主机上必须启动一个类<br>似服务器的程序,将远程主机上的Windows消息翻译成TCP/IP包,发送给远程的宿主程序。这<br>样,宿主程序可以非常非常小(可以只包括一个主Form甚至只包括一个MainProc,最小可以只<br>有50K大小),而功能可以非常非常强大。
 
function fBool_ExistMDIForm(MainForm,MDIForm:TForm):Boolean;stdcall;<br>其中MainForm、MDIForm的类型不应该定义成TForm的。<br>应定义本身的类。<br>
 
procedure TfrmMain.CreateMDIChildForm(FormClass: TFormClass);<br>var<br>&nbsp; newForm:TForm;<br>&nbsp; i:integer;<br>&nbsp; bFound:Boolean;<br>begin<br>&nbsp; newForm:=nil;<br>&nbsp; bFound:=False;<br>&nbsp; for i:=0 to MDIChildCount-1 do<br>&nbsp; &nbsp; if &nbsp;MDIChildren is formClass then begin<br>&nbsp; &nbsp; &nbsp; &nbsp; newForm:=MDIChildren;<br>&nbsp; &nbsp; &nbsp; &nbsp; bFound:=True;<br>&nbsp; &nbsp; &nbsp; &nbsp; break; &nbsp; //查找是否存在FormClass类的窗体<br>&nbsp; &nbsp; end;<br>&nbsp; &nbsp;try<br>&nbsp; &nbsp;if not bFound then<br>&nbsp; &nbsp; newForm:=formClass.Create(Self); //不存在,创建<br>&nbsp; &nbsp; newForm.show;<br>&nbsp; &nbsp;except<br>&nbsp; &nbsp; &nbsp;NewForm.free;<br>&nbsp; &nbsp;end;<br>end;<br>//------------------------------------------------------------------------------<br>这是一个创建子窗体的过程,你可以修改后封装进Dll中
 
接受答案了.
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部