我正在使用TOpenDialog(在 Delphi 10.4 中)向用戶顯示我在他們的 Documents 檔案夾中為他們安裝的 PDF 檔案。在那個檔案夾中,我創建了一個檔案夾MyFolder10.2并將 PDF 檔案復制到那里。
代碼很簡單,過去一直有效,即使現在它仍然可以在我較慢的 Win10 機器上運行。但是在我更新更快的 Win10 計算機上,它只在某些時候有效。當它不起作用時,會打開一個檔案對話框,但在某個其他目錄中(不確定它來自哪里),并且它不會過濾組件.pdf中設定的檔案型別( )TOpenDialog。
有什么方法可以追查到這個謎團嗎?
docPath:= GetEnvironmentVariable('USERPROFILE') '\Documents\MyFolder10.2\';
OpenDocsDlg.InitialDir := docPath;
OpenDocsDlg.Execute;
uj5u.com熱心網友回復:
在 Vista 之前,它是APITOpenDialog的包裝器,用于映射到欄位。GetOpenFileName()TOpenDialog.InitialDirOPENFILENAME.lpstrInitialDir
在 Vista 及更高版本上,TOpenDialog(通常,取決于配置)包裝IFileDialog/ IFileOpenDialogAPI,其中TOpenDialog.InitialDir映射到IFileDialog.SetFolder()方法(而不是IFolderDialog.SetDefaultFolder(),正如人們所期望的那樣)。
根據OPENFILENAME檔案:
lpstrInitialDir型別:
LPCTSTR初始目錄。選擇初始目錄的演算法因平臺而異。
Windows 7的:
- 如果
lpstrInitialDir[TOpenDialog.InitialDir] 的值與應用程式第一次使用“打開”或“另存為”對話框時傳遞的值相同,則用戶最近選擇的路徑將用作初始目錄。- 否則,如果
lpstrFile[TOpenDialog.FileName] 包含路徑,則該路徑是初始目錄。- 否則,如果
lpstrInitialDiris not NULL [TOpenDialog.InitialDiris not empty],則指定初始目錄。- 如果
lpstrInitialDir為NULL [TOpenDialog.InitialDir為空]且當前目錄包含指定過濾器型別的任何檔案,則初始目錄為當前目錄。- 否則,初始目錄為當前用戶的個人檔案目錄。
- 否則,初始目錄是 Desktop 檔案夾。
Windows 2000/XP/Vista:
- 如果
lpstrFile[TOpenDialog.FileName] 包含路徑,則該路徑是初始目錄。- 否則,
lpstrInitialDir[TOpenDialog.InitialDir] 指定初始目錄。- 否則,如果應用程式過去使用過“打開”或“另存為”對話框,則選擇最近使用的路徑作為初始目錄。但是,如果應用程式長時間未運行,則其保存的選定路徑將被丟棄。
- 如果
lpstrInitialDir為NULL [TOpenDialog.InitialDir為空]且當前目錄包含指定過濾器型別的任何檔案,則初始目錄為當前目錄。- 否則,初始目錄為當前用戶的個人檔案目錄。
- 否則,初始目錄是 Desktop 檔案夾。
并且根據Common Item Dialog檔案:
控制默認檔案夾
Almost any folder in the Shell namespace can be used as the default folder for the dialog (the folder presented when the user chooses to open or save a file). Call
IFileDialog::SetDefaultFolderprior to callingShow[TOpenDialog.Execute()] to do so.The default folder is the folder in which the dialog starts the first time a user opens it from your application. After that, the dialog will open in the last folder a user opened or the last folder they used to save an item. See State Persistence for more details.
You can force the dialog to always show the same folder when it opens, regardless of previous user action, by calling
IFileDialog::SetFolder[TOpenDialog.InitialDir]. However, we do not recommended doing this. If you callSetFolderbefore you display the dialog box, the most recent location that the user saved to or opened from is not shown. Unless there is a very specific reason for this behavior, it is not a good or expected user experience and should be avoided. In almost all instances,IFileDialog::SetDefaultFolderis the better method.When saving a document for the first time in the Save dialog, you should follow the same guidelines in determining the initial folder as you did in the Open dialog. If the user is editing a previously existing document, open the dialog in the folder where that document is stored, and populate the edit box with that document's name. Call
IFileSaveDialog::SetSaveAsItem()with the current item prior to callingShow[TOpenDialog.Execute()].
Neither TOpenDialog nor TFileOpenDialog have properties that map to the IFileDialog.SetDefaultFolder() or IFileDialog.SetSaveAsItem() methods. However, the TFileOpenDialog.Dialog property does give you access to the underlying IFileDialog, so you can manually call these methods, such as in the TFileOpenDialog.OnExecute event.
uj5u.com熱心網友回復:
@Remy Lebeau 的詳細回答促使我再次嘗試修復一個我以前無法修復的有問題的常見場景,盡管進行了多次嘗試:我有一個帶有 TFileOpenDialog 和 TFileSaveDialog 的影像編輯 VCL 應用程式,通常用于編輯在已連接的 Android 設備上一張一張的一堆螢屏截圖保存在臺式電腦上。問題是 FileOpenDialog 的 DefaultFolder 在計算機上保存后沒有粘在打開的 Android 檔案夾上。現在這已根據我的喜好進行了修復,并且該解決方案可能對需要玩這些對話框的人感興趣。
測驗代碼:
unit Main;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
Winapi.ShlObj, Winapi.KnownFolders, Winapi.ActiveX;
type
TMainForm = class(TForm)
FileOpenDialog1: TFileOpenDialog;
FileSaveDialog1: TFileSaveDialog;
OpenButton: TButton;
SaveButton: TButton;
Memo1: TMemo;
procedure FileOpenDialog1Execute(Sender: TObject);
procedure FileSaveDialog1Execute(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure OpenButtonClick(Sender: TObject);
procedure SaveButtonClick(Sender: TObject);
private
FOpenShellItem: IShellItem;
FSaveShellItem: IShellItem;
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
function GetItemName(ShellItem: IShellItem; const Flags: Cardinal): string;
var
pszItemName: LPCWSTR;
begin
Result := '';
if ShellItem.GetDisplayName(Flags, pszItemName) = S_OK then
begin
Result := pszItemName;
CoTaskMemFree(pszItemName);
end;
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
pch: PChar;
begin
DesktopFont := True;
if SHGetKnownFolderPath(FOLDERID_Pictures, 0, 0, pch) = S_OK then
begin
FileOpenDialog1.DefaultFolder := pch;
FileSaveDialog1.DefaultFolder := pch;
CoTaskMemFree(pch);
end;
end;
procedure TMainForm.OpenButtonClick(Sender: TObject);
var
ShellItem: IShellItem;
ParentItem: IShellItem;
begin
if FileOpenDialog1.Execute(Handle) then
begin
if fdoAllowMultiSelect in FileOpenDialog1.Options then
FileOpenDialog1.ShellItems.GetItemAt(0, ShellItem)
else
ShellItem := FileOpenDialog1.ShellItem;
if ShellItem.GetParent(ParentItem) = S_OK then
FOpenShellItem := ParentItem;
Memo1.Lines.Add('Opened');
Memo1.Lines.Add('ItemParsingName: '
GetItemName(ShellItem, SIGDN_DESKTOPABSOLUTEPARSING));
Memo1.Lines.Add('ItemNormalName: '
GetItemName(ShellItem, SIGDN_NORMALDISPLAY));
Memo1.Lines.Add('ParentItemParsingName: '
GetItemName(ParentItem, SIGDN_DESKTOPABSOLUTEPARSING));
Memo1.Lines.Add('ParentItemNormalame: '
GetItemName(ParentItem, SIGDN_NORMALDISPLAY));
Memo1.Lines.Add('----------');
end;
end;
procedure TMainForm.SaveButtonClick(Sender: TObject);
var
ParentItem: IShellItem;
begin
if FileSaveDialog1.Execute(Handle) then
begin
if FileSaveDialog1.ShellItem.GetParent(ParentItem) = S_OK then
FSaveShellItem := FileSaveDialog1.ShellItem;
Memo1.Lines.Add('Saved');
Memo1.Lines.Add('ItemParsingName: '
GetItemName(FileSaveDialog1.ShellItem, SIGDN_DESKTOPABSOLUTEPARSING));
Memo1.Lines.Add('ItemNormalName: '
GetItemName(FileSaveDialog1.ShellItem, SIGDN_NORMALDISPLAY));
Memo1.Lines.Add('ParentItemParsingName: '
GetItemName(ParentItem, SIGDN_DESKTOPABSOLUTEPARSING));
Memo1.Lines.Add('ParentItemNormalName: '
GetItemName(ParentItem, SIGDN_NORMALDISPLAY));
Memo1.Lines.Add('----------');
end;
end;
procedure TMainForm.FileOpenDialog1Execute(Sender: TObject);
begin
if Assigned(FOpenShellItem) then
FileOpenDialog1.Dialog.SetFolder(FOpenShellItem);
end;
procedure TMainForm.FileSaveDialog1Execute(Sender: TObject);
begin
//Note the IFileSaveDialog typecast
if Assigned(FSaveShellItem) then
IFileSaveDialog(FileSaveDialog1.Dialog).SetSaveAsItem(FSaveShellItem);
end;
end.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/453968.html
上一篇:處理錯誤請求的自定義錯誤訊息
