如何完全释放DLL窗体?让他再次打开时还和第一次一样
dll里的数据集组件共享的exe的数据连接,现在是第一次运行都很正常,但关闭后再打开查询,就各种问题了。
----------------------------------------------------
调用dll打开dllform
Delphi(Pascal) code
procedure TMainFrm.N11Click(Sender: TObject);
begin
uPublicMethod.OpenDllFrm('BatchWageRecord.dll', '');
end;
Delphi(Pascal) code
function OpenDllFrm(DllName, Str: string): string;
var
DllHandle: THandle;
ShowFrm: TShowFrm;
begin
Result := '';
DllHandle := LoadLibrary(PAnsiChar(DllName));
if DllHandle <> 0 then
begin
@ShowFrm := GetProcAddress(DllHandle, 'ShowFrm');
if @ShowFrm <> nil then
ShowFrm(Application.Handle, DataModule1.conDB, Str)
else
begin
WriteWorkLog('加载 ' + DllName + ' 函数ShowFrm失败。', Dosp_GetSysTime);
Result := '打开窗体失败!';
end;
end
else
begin
WriteWorkLog('未找到' + DllName + ' ,加载失败。', Dosp_GetSysTime);
Result := '加载 ' + DllName + ' 失败!';
end;
end;
dll里的方法:
Delphi(Pascal) code
procedure ShowFrm(AHandle: THandle; Con: TADOConnection; Str: string); stdcall;
procedure GetUserInfo;
var
CharPos: Integer;
begin
CharPos := Pos('#', str);
UserID := Copy(Str, 1, CharPos - 1);
UserPassword := Copy(Str, CharPos + 1, Length(str) - CharPos);
end;
var
PerQueryFrm: TPerQueryFrm;
begin
Application.Handle := AHandle;
PerQueryFrm := TPerQueryFrm.Create(nil);
DataModule2 := TDataModule2.Create(nil);
GetUserInfo;
DataModule2.qry_DynamicQuery.Connection := Con;
DataModule2.sp_GetSysTime.Connection := Con;
DataModule2.qry_GetSalary.Connection := Con;
DataModule2.sp_GetWageHistory.Connection := Con;
PerQueryFrm.ShowModal;
end;
------------------------------------------------
关闭dllform
procedure TPerQueryFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DataModule2.qry_DynamicQuery.Close;
DataModule2.sp_GetSysTime.Close;
DataModule2.qry_GetSalary.Close;
DataModule2.sp_GetWageHistory.Close;
DataModule2.qry_DynamicQuery.Connection := nil;
DataModule2.sp_GetSysTime.Connection := nil;
DataModule2.qry_GetSalary.Connection := nil;
DataModule2.sp_GetWageHistory.Connection := nil;
end;
------解决方案--------------------
不用的时候就Free掉,比如PerQueryFrm.Free
或者只创建一次,后面调用时就直接显示,就不用再创建了,用AsSigned()判断
------解决方案--------------------
procedure TPerQueryFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DataModule2.qry_DynamicQuery.Close;
DataModule2.sp_GetSysTime.Close;
DataModule2.qry_GetSalary.Close;
DataModule2.sp_GetWageHistory.Close;
DataModule2.qry_DynamicQuery.Connection := nil;
DataModule2.sp_GetSysTime.Connection := nil;
DataModule2.qry_GetSalary.Connection := nil;
DataModule2.sp_GetWageHistory.Connection := nil;
Action := caFree;
end;
加一行
Action := caFree;
试一下
------解决方案--------------------
Action := caFree;
要知道如果是隐式链接,如果不引用DLL中的任何导出函数,则链接器会把该DLL从EXE的导入段中给取出的,最终导致DLL根本不会被加载到进程中。楼主需要用“进程查看器”之类的工具看下你的DLL是不是真的被加载到了EXE的地址空间了。
既然是DLL,那么DLL中最基本的DllMain含义楼主应该清楚吧,就像学习控制台编程,如果连main的含义都是一知半解就糟糕了。
要知道DllMain在 ul_reason_for_call等于DLL_PROCESS_ATTACH时,必须使DllMain函数返回TRUE,EXE才会成功加载该DLL的。
判断另一个窗体的名字或者线程ID