DLL封装的窗体使用DEV控件后,主程序退出报错

pengzhenpe java高级工程师  2013-06-25 11:13:30
出错情况说明:
1.DELPHI版本:Delphi2010, DEV控件版本12.1.5
2.系统总的框架是:窗体都封装成DLL,供主程序调用
3.调用DLL代码如下
DLL代码:
library Login;

{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }

uses
SysUtils,
Classes,
Forms,
Windows,
Messages,
ADODB,
Frm_Login in 'Frm_Login.pas' {FrmLogin},
UPublic in '..\Public\UPublic.pas';

{$R *.res}

var
DLLApp: TApplication;

function CallLoginForm(var App: TApplication;Conn:TADOConnection): Boolean;export; stdcall;
begin
DBcon:=Conn;
{获取调用窗体的Application,显而易见的功能是 能使你的窗体融合到调用程序中。通过它还能进行很多操作}
Application:= App;//将DLL的Application转为App
FrmLogin:= TFrmLogin.Create(App);
FrmLogin.ShowModal;
end;

{重写Dll入口函数,否则程序会出错}
procedure DLLUnloadProc(Reason: Integer); register;
begin
{DLL取消调用时,发送DLL_PROCESS_DETACH消息,此时将DLL的Application返回为本身}
if Reason = DLL_PROCESS_DETACH then Application:=DLLApp;
end;

exports
CallLoginForm;

begin
{在DLL入口预先储存DLL的Application}
DLLApp:=Application;
{DllProc:DLL入口函数指针。Delphi定义为 DllProc: TDLLProc;}
{在此指向我们自己定义的函数}
DLLProc := @DLLUnloadProc;
end.

调用DLL主程序代码:
定义:
var
frmMain: TfrmMain;
//加载调用界面
//登录
function CallLoginForm(var App: TApplication;Conn:TADOConnection):Boolean;stdcall; external 'Login.dll';
调用:
CallLoginForm(Application,UPublic.SqlServerDBConn);
4.问题说明:DLL封装的窗体在不使用DEV控件,使用Delphi自带控件情况下,一切正常,没有问题。
放入DEV控件后,主程序调用DLL窗体正常,功能使用也正常,就是在主程序退出时就会报错
---------------------------
PEIS.exe - 应用程序错误
---------------------------
"0x01ca5132" 指令引用的 "0x039c90a0" 内存。该内存不能为 "read"。


要终止程序,请单击“确定”。
---------------------------
确定
---------------------------

经过2天网上资料查找,有2中说法比较多
1.DLL窗体释放时没处理好。
这个可能性应该比较小了,因为毕竟在没有使用DEV控件情况下一切正常
2.皮肤控件问题导致
个人觉得这个的可能很大,因为DEV控件是需要使用皮肤的


求大神们帮忙看下,帮小弟解决解决,实在是不知道怎么处理了。
...全文
323 点赞 收藏 14
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
iamduo 2013-07-10
楼主: 你可以多请教请教 jiang。 似乎,你想做的事情,他已经有一个完整的解决方案了。
回复
iamduo 2013-07-10
#10 标准答案。 多谢。 我也碰到了。就是这么解决的。
回复
musa2008 2013-06-27
我也遇到过这个问题。
回复
pengzhenpe 2013-06-26
引用 8 楼 FengLinYuShu 的回复:
在DLL中增加初始化和退出函数即可!新旧版本的稍有区别 -------------- WebXone - BS程序利器
能具体说说函数怎么加?和函数怎么些吗? 谢谢了。
回复
jiangzs188136923 2013-06-26
dxInitializeGDIPlus; 这个很重要!
回复
jiangzs188136923 2013-06-26
begin CoInitialize(nil); dxInitializeGDIPlus; DllApplication := Application; //DllApplication保存的是 DLL APP变量指针 DLLProc := @DLLUnloadProc; end. library hxjxc; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. } uses sharemem, SysUtils, Classes, Windows, Forms, ActiveX, dxGDIPlusAPI, Controls, uModel in '..\hxComm\uModel.pas' {Modelfrm}; {$R *.res} procedure DLLUnloadProc(Reason: Integer); register; begin if Reason = DLL_PROCESS_DETACH then begin Application := DllApplication; PubDMFrm := nil; PubShareInfoObj := nil; DoSetStatus := nil; dxFinalizeGDIPlus; CoUninitialize; end; end; procedure SetDataPoint(APubDMObj: TDataModule; AShareInfo: TPubShareInfo; app: TApplication; DoSetStatusFun: TDoSetStatus); stdcall; begin PubDMFrm := TPubDMFrm(APubDMObj); PubShareInfoObj := AShareInfo; DoSetStatus := @DoSetStatusFun; end; function FindDllFormClass(aClassName: string): TMyFormClass; stdcall; begin Result := TMyFormClass(GetClass(aClassName)); end; function ShowDllForm(aClassName: string; Parent: TApplication; Parent2: TWinControl): TMyForm; stdcall; var aDllForm: TMyForm; aDllFormClass: TMyFormClass; begin Result := nil; aDllFormClass := TMyFormClass(GetClass(aClassName)); if aDllFormClass = nil then Exit; if Parent2 <> nil then Application.Handle := Parent2.Handle else Application.Handle := Parent.Handle; //showmodel aDllForm := aDllFormClass.Create(Application); if Parent2 <> nil then aDllForm.ParentWindow := Parent2.Handle ;//将容器设置为父窗口 // else aDllForm.ParentWindow := Parent.Handle; Result := aDllForm; end; exports FindDllFormClass, SetDataPoint, ShowDllForm; begin CoInitialize(nil); dxInitializeGDIPlus; DllApplication := Application; //DllApplication保存的是 DLL APP变量指针 DLLProc := @DLLUnloadProc; end.
回复
林石公 2013-06-25
估计是GDI+的问题
回复
Blessed_Chuan 2013-06-25
添加Vcl引用
回复
pengzhenpe 2013-06-25
没人知道怎么处理吗
回复
pengzhenpe 2013-06-25
你最后怎么处理的呢?
回复
feiba7288 2013-06-25
我也遇到,Dev的问题,我觉得是他的bug
回复
碧树西风 2013-06-25
在DLL中增加初始化和退出函数即可!新旧版本的稍有区别 -------------- WebXone - BS程序利器
回复
pengzhenpe 2013-06-25
没有大神帮忙吗
回复
pengzhenpe 2013-06-25
添加VCL引用试过了,不行
回复
相关推荐
发帖
Delphi
创建于2007-08-02

4923

社区成员

Delphi 开发及应用
申请成为版主
帖子事件
创建了帖子
2013-06-25 11:13
社区公告
暂无公告