Jef*_*ffR 10 delphi openfiledialog delphi-7 topendialog
我正在尝试修改Delphi 7 Dialogs.pas以访问较新的Windows 7打开/保存对话框(请参阅使用Delphi创建Windows Vista Ready应用程序).我可以使用建议的修改显示对话框; 但是,诸如OnFolderChange和OnCanClose之类的事件不再起作用.
这似乎与将Flags:= OFN_ENABLEHOOK更改为Flags:= 0有关.当Flags设置为0时,将绕过TOpenDialog.Wndproc,并且不会捕获相应的CDN_xxxxxxx消息.
任何人都可以建议对D7 Dialogs.pas进行进一步的代码修改,既可以显示更新的常用对话框,又可以维护原始控件的事件功能?
谢谢...
您应该使用IFileDialog接口并调用其Advise()方法与的实现IFileDialogEvents接口.Delphi 7 Windows标题单元不包含必要的声明,因此必须从SDK标头文件中复制(和翻译)它们(或者可能已经有另一个标题翻译可用?),但除了额外的努力之外,不应该从Delphi 7(甚至更早的Delphi版本)中调用它有任何问题.
编辑:
好的,既然你没有以任何方式对答案做出反应,我会添加更多信息.关于如何使用接口的AC示例可以在这里获得.只要您拥有必要的导入单元,就可以轻松将其转换为Delphi代码.
我在Delphi 4中汇总了一个小样本.为简单起见,我创建了一个TOpenDialog后代(你可能会修改原始类)并IFileDialogEvents直接在其上实现:
type
TVistaOpenDialog = class(TOpenDialog, IFileDialogEvents)
private
// IFileDialogEvents implementation
function OnFileOk(const pfd: IFileDialog): HResult; stdcall;
function OnFolderChanging(const pfd: IFileDialog;
const psiFolder: IShellItem): HResult; stdcall;
function OnFolderChange(const pfd: IFileDialog): HResult; stdcall;
function OnSelectionChange(const pfd: IFileDialog): HResult; stdcall;
function OnShareViolation(const pfd: IFileDialog;
const psi: IShellItem; out pResponse: DWORD): HResult; stdcall;
function OnTypeChange(const pfd: IFileDialog): HResult; stdcall;
function OnOverwrite(const pfd: IFileDialog; const psi: IShellItem;
out pResponse: DWORD): HResult; stdcall;
public
function Execute: Boolean; override;
end;
function TVistaOpenDialog.Execute: Boolean;
var
guid: TGUID;
Ifd: IFileDialog;
hr: HRESULT;
Cookie: Cardinal;
Isi: IShellItem;
pWc: PWideChar;
s: WideString;
begin
CLSIDFromString(SID_IFileDialog, guid);
hr := CoCreateInstance(CLSID_FileOpenDialog, nil, CLSCTX_INPROC_SERVER,
guid, Ifd);
if Succeeded(hr) then begin
Ifd.Advise(Self, Cookie);
// call DisableTaskWindows() etc.
// see implementation of Application.MessageBox()
try
hr := Ifd.Show(Application.Handle);
finally
// call EnableTaskWindows() etc.
// see implementation of Application.MessageBox()
end;
Ifd.Unadvise(Cookie);
if Succeeded(hr) then begin
hr := Ifd.GetResult(Isi);
if Succeeded(hr) then begin
Assert(Isi <> nil);
// TODO: just for testing, needs to be implemented properly
if Succeeded(Isi.GetDisplayName(SIGDN_NORMALDISPLAY, pWc))
and (pWc <> nil)
then begin
s := pWc;
FileName := s;
end;
end;
end;
Result := Succeeded(hr);
exit;
end;
Result := inherited Execute;
end;
function TVistaOpenDialog.OnFileOk(const pfd: IFileDialog): HResult;
var
pszName: PWideChar;
s: WideString;
begin
if Succeeded(pfd.GetFileName(pszName)) and (pszName <> nil) then begin
s := pszName;
if AnsiCompareText(ExtractFileExt(s), '.txt') = 0 then begin
Result := S_OK;
exit;
end;
end;
Result := S_FALSE;
end;
function TVistaOpenDialog.OnFolderChange(const pfd: IFileDialog): HResult;
begin
Result := S_OK;
end;
function TVistaOpenDialog.OnFolderChanging(const pfd: IFileDialog;
const psiFolder: IShellItem): HResult;
begin
Result := S_OK;
end;
function TVistaOpenDialog.OnOverwrite(const pfd: IFileDialog;
const psi: IShellItem; out pResponse: DWORD): HResult;
begin
Result := S_OK;
end;
function TVistaOpenDialog.OnSelectionChange(
const pfd: IFileDialog): HResult;
begin
Result := S_OK;
end;
function TVistaOpenDialog.OnShareViolation(const pfd: IFileDialog;
const psi: IShellItem; out pResponse: DWORD): HResult;
begin
Result := S_OK;
end;
function TVistaOpenDialog.OnTypeChange(const pfd: IFileDialog): HResult;
begin
Result := S_OK;
end;
Run Code Online (Sandbox Code Playgroud)
如果在Windows 7上运行它,它将显示新对话框并仅接受带有txt扩展名的文件.这是硬编码的,需要通过OnClose对话事件来实现.还有很多工作要做,但提供的代码应该足以作为起点.