系统介绍:
1.中文 XP SP3
2.日文 XP SP3代码如下:
==========================DLL==========================uses
Sharemem,
SysUtils,
Forms,
Messages,
Windows,
Classes,
ActiveX,
comObj,
untPRJ_1_Setup in 'untPRJ_1_Setup.pas' {frmPRJ_1_Setup},
udmData in '..\Common\udmData.pas' {dmData: TDataModule},
untCommon in '..\Common\untCommon.pas',
AES in '..\Common\AES.pas',
ElAES in '..\Common\ElAES.pas';{$R *.res}
var
DllApp: TApplication;
DLLScreen: TScreen;
TheForm: TForm;
TheClass: TPersistentClass;procedure RunDLL(DLLName, FormName, FormCaption: string;
APP: TApplication; SC: TScreen) stdcall;
begin
Application := App;
Screen := SC; RegisterClasses([TfrmPRJ_1_Setup]); TheClass := GetClass('T' + FormName); if (TheClass <> nil) and TheClass.InheritsFrom(TForm) then
begin
TheForm := TForm(TheClass.Create).Create(Application); //TheForm := TfrmPRJ_1_Setup.Create(Application, FormCaption);
//TheForm.Show;
try
TheForm.ShowModal;
finally
FreeAndNil(TheForm);
//TheForm.Free;
end;
end;
end;procedure DLLUnloadProc(dwReason: Dword);
begin
case dwReason of
//DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH:
//CoInitialize(nil);
DLL_PROCESS_DETACH:
begin
//CoUninitialize; Application := DLLApp;
Screen := DLLScreen; if TheForm <> nil then
FreeAndNil(TheForm); SendMessage(Application.Handle, WM_CLOSE, 0, 0);
FreeLibrary(Application.Handle);
end; DLL_THREAD_DETACH:
//CoUninitialize; end;
end; exports
RunDLL;begin
DLLApp := Application;
DLLScreen := Screen; DLLProc := @DLLUnloadProc;
DLLUnloadProc(DLL_PROCESS_ATTACH);
end.
==========================调用==========================
DPR文件
uses sharemem
type
TRunDLL = procedure(DLLName, FormName, FormCaption: string;
Application: TApplication; Screen: TScreen); stdcall;procedure TfrmMain.btnPRJ_1_SetupClick(Sender: TObject);
begin
RunDLLForm('PRJ_1_Setup.dll', 'frmPRJ_1_Setup', 'ノ靹テ', Application, Screen);
end;procedure TfrmMain.RunDLLForm(DLLName, FormName, FormCaption: string;
APP: TApplication; SC: TScreen) stdcall;
var
GetDllHWND: HWND;
RunDLL: TRunDLL;
begin
GetDllHWND := LoadLibrary(PChar(DllName));
if GetDllHWND = 0 then
begin
MessageBox(0, PChar('テサモミユメオステ鉸ェ '+DLLName+' オトホトシ」ャヌ・キネマウフミヌキ・訒。'),
'シモヤリDLLホトシハァーワ', MB_OK);
Exit;
end;
try
@RunDLL := GetProcAddress(GetDllHWND, 'RunDLL');
if Assigned(@RunDLL) then
begin
try
RunDLL(UpperCase(Trim(DLLName)), UpperCase(Trim(FormName)),
FormCaption, APP, SC); except
raise Exception.Create('T' + FormName + 'イサエ贇レ」。');
end;
end; finally
FreeLibrary(GetDllHWND);
end;
end;
在中文下编译、运行没问题,编译后的文件拿到日文下、运行没问题。
如果在日文下,编译使用相同代码后,宿主程序在呼出DLL窗体时也没问题。
但是,当DLL窗体关闭后,再关闭宿主程序,delphi就会报内存错误和runtime error这是为什么捏?
在此BS下日文系统- -
1.中文 XP SP3
2.日文 XP SP3代码如下:
==========================DLL==========================uses
Sharemem,
SysUtils,
Forms,
Messages,
Windows,
Classes,
ActiveX,
comObj,
untPRJ_1_Setup in 'untPRJ_1_Setup.pas' {frmPRJ_1_Setup},
udmData in '..\Common\udmData.pas' {dmData: TDataModule},
untCommon in '..\Common\untCommon.pas',
AES in '..\Common\AES.pas',
ElAES in '..\Common\ElAES.pas';{$R *.res}
var
DllApp: TApplication;
DLLScreen: TScreen;
TheForm: TForm;
TheClass: TPersistentClass;procedure RunDLL(DLLName, FormName, FormCaption: string;
APP: TApplication; SC: TScreen) stdcall;
begin
Application := App;
Screen := SC; RegisterClasses([TfrmPRJ_1_Setup]); TheClass := GetClass('T' + FormName); if (TheClass <> nil) and TheClass.InheritsFrom(TForm) then
begin
TheForm := TForm(TheClass.Create).Create(Application); //TheForm := TfrmPRJ_1_Setup.Create(Application, FormCaption);
//TheForm.Show;
try
TheForm.ShowModal;
finally
FreeAndNil(TheForm);
//TheForm.Free;
end;
end;
end;procedure DLLUnloadProc(dwReason: Dword);
begin
case dwReason of
//DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH:
//CoInitialize(nil);
DLL_PROCESS_DETACH:
begin
//CoUninitialize; Application := DLLApp;
Screen := DLLScreen; if TheForm <> nil then
FreeAndNil(TheForm); SendMessage(Application.Handle, WM_CLOSE, 0, 0);
FreeLibrary(Application.Handle);
end; DLL_THREAD_DETACH:
//CoUninitialize; end;
end; exports
RunDLL;begin
DLLApp := Application;
DLLScreen := Screen; DLLProc := @DLLUnloadProc;
DLLUnloadProc(DLL_PROCESS_ATTACH);
end.
==========================调用==========================
DPR文件
uses sharemem
type
TRunDLL = procedure(DLLName, FormName, FormCaption: string;
Application: TApplication; Screen: TScreen); stdcall;procedure TfrmMain.btnPRJ_1_SetupClick(Sender: TObject);
begin
RunDLLForm('PRJ_1_Setup.dll', 'frmPRJ_1_Setup', 'ノ靹テ', Application, Screen);
end;procedure TfrmMain.RunDLLForm(DLLName, FormName, FormCaption: string;
APP: TApplication; SC: TScreen) stdcall;
var
GetDllHWND: HWND;
RunDLL: TRunDLL;
begin
GetDllHWND := LoadLibrary(PChar(DllName));
if GetDllHWND = 0 then
begin
MessageBox(0, PChar('テサモミユメオステ鉸ェ '+DLLName+' オトホトシ」ャヌ・キネマウフミヌキ・訒。'),
'シモヤリDLLホトシハァーワ', MB_OK);
Exit;
end;
try
@RunDLL := GetProcAddress(GetDllHWND, 'RunDLL');
if Assigned(@RunDLL) then
begin
try
RunDLL(UpperCase(Trim(DLLName)), UpperCase(Trim(FormName)),
FormCaption, APP, SC); except
raise Exception.Create('T' + FormName + 'イサエ贇レ」。');
end;
end; finally
FreeLibrary(GetDllHWND);
end;
end;
在中文下编译、运行没问题,编译后的文件拿到日文下、运行没问题。
如果在日文下,编译使用相同代码后,宿主程序在呼出DLL窗体时也没问题。
但是,当DLL窗体关闭后,再关闭宿主程序,delphi就会报内存错误和runtime error这是为什么捏?
在此BS下日文系统- -
是不是DLL_PROCESS_DETACH: 里的这句
FreeLibrary(Application.Handle);
出问题了
不是啊~F8一直可以运行到程序结束,之后稍等一会弹出access violation at 0x00404e0c: read of address 0x035c4960
日文系统是D7和D2010在日文下 不管用7还是2010 都报错
感谢大家回复!我将string全部换成Pchar后也不行、SendMessage是我失误,复制时不小心把注释//删掉了。但是,我发现,静态调用DLL之后,就没问题了……
我再试试看动态调用哪里出的问题!
procedure RunDLL(DLLName, FormName, FormCaption: Pchar; APP: TApplication; SC: TScreen); stdcall; external 'PRJ_1_Setup.dll';procedure TForm1.Button1Click(Sender: TObject);
begin
//RunDLLForm(Pchar('PRJ_1_Setup.dll'), Pchar('frmPRJ_1_Setup'), Pchar(''), Application, Screen);
RunDLL(Pchar('PRJ_1_Setup.dll'), Pchar('frmPRJ_1_Setup'), Pchar(''), Application, Screen);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
RunDLLForm(Pchar('PRJ_1_Setup.dll'), Pchar('frmPRJ_1_Setup'), Pchar(''), Application, Screen);
RunDLL(Pchar('PRJ_1_Setup.dll'), Pchar('frmPRJ_1_Setup'), Pchar(''), Application, Screen);
end;
还发现个有意思的地方
先动态方法建立窗体 关闭
再静态方法建立窗体 关闭
最后关闭主程序
不报错 一切正常……
昨天的最新进展:
library Setting;uses
Sharemem,
SysUtils,
Forms,
Messages,
Windows,
Classes,
ActiveX,
comObj,
UntSetting in '..\Form\UntSetting.pas' { FrmSetting } ;
{$R *.res}var
DllApp: TApplication;
DllScr: TScreen;
TheForm: TForm;
TheClass: TPersistentClass;procedure OpenMe(Parent: THandle; DllName, FrmName: string; App: TApplication;
Scr: TScreen); stdcall;
begin
Application := App; //问题在这
Screen := Scr; RegisterClasses([TFrmSetting]);
TheClass := GetClass('T' + FrmName);
if (TheClass <> nil) and TheClass.InheritsFrom(TForm) then
begin
//Application.Handle := Parent;
TheForm := TForm(TheClass.Create).Create(Application);
try
TheForm.ShowModal;
finally
FreeAndNil(TheForm);
end;
end;
end;procedure DLLUnloadProc(dwReason: Dword);
begin
case dwReason of
DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH:
begin
{ 保存Dll初始的Application對象 }
DllApp := Application;
{ 保存Dll初始的Screen對象 }
DllScr := Screen;
// CoInitialize(nil);
end; DLL_PROCESS_DETACH:
begin
{ 還原Dll的Application對象 }
Application := DllApp;
{ 還原Dll的Screen對象 }
Screen := DllScr; if TheForm <> nil then
FreeAndNil(TheForm); FreeLibrary(Application.Handle); // CoUninitialize;
end; DLL_THREAD_DETACH:
begin
CoUninitialize;
end;
end;
end;exports OpenMe;begin
DllProc := @DLLUnloadProc;
DLLUnloadProc(DLL_PROCESS_ATTACH);end.
以上代码,在静态调用的时候没有问题
动态调用后,关闭主程序会报run time error后来我尝试将Application := App;注释掉
再将主窗体句柄传入DLL,如下:
Application.Handle := Parent;
动态,静态调用都没有问题很困惑啊...