Delphi6调用Delphi2009 DLL选目录后窗口失焦问题求助
问题分析与解决办法
为啥会出现这个失焦问题?
这个坑其实是跨版本Delphi模块调用时,窗口所有权没处理对导致的:
DLL里的对话框没绑定父窗口:你在DLL中创建
TFileOpenDialog时传的是nil当父窗口。在Delphi 2009里直接调用的时候,VCL会自动把当前程序的活跃窗口当成对话框的“靠山”,对话框关了之后焦点自然回到主程序。但跨模块调用就不一样了——Delphi 6的主程序和Delphi 2009的DLL是两个独立的模块,VCL的自动父窗口机制跨模块失效了,对话框相当于“无主”状态,系统关了它之后就随便找个活跃窗口(比如资源管理器)把焦点切过去。新老VCL的差异:Delphi 2009的VCL在对话框管理上做了优化,但这种优化只在同模块内生效,跨版本调用就吃瘪了。
怎么解决?
核心思路就是给对话框明确指定父窗口,让系统知道“这个对话框是属于Delphi 6主程序的”,具体分两步改:
第一步:修改DLL里的函数,加个父窗口句柄参数
把原来的函数改成接受HWND类型的父窗口参数,然后把这个句柄绑定到对话框上:
function _SelectDirectory(AParentWnd: HWND; ADirPath: ShortString): ShortString; stdcall; var OpenDlg: TFileOpenDialog; begin Result := ''; OpenDlg := TFileOpenDialog.Create(nil); try OpenDlg.Options := OpenDlg.Options + [fdoPickFolders]; // 关键:把对话框和主程序窗口绑定 OpenDlg.ParentWindow := AParentWnd; if DirectoryExists(ADirPath) then OpenDlg.DefaultFolder := ADirPath; if OpenDlg.Execute then begin Result := OpenDlg.FileName; end; finally OpenDlg.Free; end; end;
记得加上stdcall,不然跨版本Delphi调用时参数栈处理会出错,踩更大的坑。
第二步:Delphi 6调用时传入主窗口句柄
调用DLL函数的时候,把主程序窗口的Handle传进去,比如:
// 先声明DLL导出的函数 function _SelectDirectory(AParentWnd: HWND; ADirPath: ShortString): ShortString; stdcall; external '你的DLL文件名.dll'; // 调用示例 var SelectedDir: string; begin // 把主窗口句柄传进去,告诉对话框它的“主人”是谁 SelectedDir := _SelectDirectory(Application.MainForm.Handle, 'C:\初始路径'); end;
万一还不行?试试这个额外操作
如果改完还是偶尔失焦,可以在调用DLL前先把主窗口激活,确保它是当前最活跃的窗口:
Application.MainForm.BringToFront; Application.MainForm.SetFocus; SelectedDir := _SelectDirectory(Application.MainForm.Handle, 'C:\初始路径');
这样操作之后,系统就能明确对话框的归属,关闭后焦点肯定会回到你的Delphi 6程序,不会跳去资源管理器了。
内容的提问来源于stack exchange,提问作者TomR
相关产品推荐
相关产品推荐

