Выбор каталога с TOpenDialog
Мне бы очень хотелось узнать, как я могу выбрать каталог с помощью TOpenDialog, будь то загрузка нового компонента или использование того, что предоставлено Delphi, но предпочтительно использование того, что предоставлено Delphi.
До этого я использовал команду SelectDirectory, но я думаю, что пользователям моей программы будет трудно найти указанную директорию.
Я думаю, что SelectDirectory является "слабым", потому что он может быть длительным процессом при поиске нужного каталога. Например, вы хотите перейти в каталог Application Data. Как долго или сложно будет там перемещаться? В конце концов, пользователи могут даже не достичь желаемого каталога.
Мне нужно что-то вроде этого, где пользователь может копировать и вставлять каталоги в адресную строку каталога там вверху.
Спасибо за все ваши ответы.
5 ответов
Вы можете использовать TFileOpenDialog
(на Vista+):
with TFileOpenDialog.Create(nil) do
try
Options := [fdoPickFolders];
if Execute then
ShowMessage(FileName);
finally
Free;
end;
Лично я всегда использую TFileOpenDialog
на Vista + и откат с помощью SelectDirectory
(хороший!) на XP, вот так:
if Win32MajorVersion >= 6 then
with TFileOpenDialog.Create(nil) do
try
Title := 'Select Directory';
Options := [fdoPickFolders, fdoPathMustExist, fdoForceFileSystem]; // YMMV
OkButtonLabel := 'Select';
DefaultFolder := FDir;
FileName := FDir;
if Execute then
ShowMessage(FileName);
finally
Free;
end
else
if SelectDirectory('Select Directory', ExtractFileDrive(FDir), FDir,
[sdNewUI, sdNewFolder]) then
ShowMessage(FDir)
Вы знаете, что две перегруженные функции называются FileCtrl.SelectDirectory
выдает совершенно разные диалоги, верно?
SelectDirectory(s, [], 0);
http://privat.rejbrand.se/oldseldir.png
SelectDirectory('Select a directory', s, s, []);
Просто включите
FileCtrl.pas
var
sDir:String;
begin
SelectDirectory('Your caption','',sDir);
end;
Просто оставьте второй аргумент пустым, если хотите увидеть все каталоги, включая рабочий стол. Если вы установили второй аргумент для любого допустимого пути, то ваш диалог будет иметь этот путь к верхней папке, и вы не сможете перейти дальше.
Например:
SelectDirectory('Your caption','C:\',sDir)
не позволит вам выбрать что-то кроме C:\
, лайк D:\
или же E:\
и т.п.
Так что хорошо оставить это пустым.
Только что нашел код ниже, который, кажется, отлично работает в XP и Vista, Win7. Он предоставляет пользовательский интерфейс для выбора каталога. Он использует TOpenDialog, но отправляет ему несколько сообщений, чтобы очистить внешний вид в целях выбора каталога.
После страданий от ограниченных возможностей, предоставляемых самой Windows, очень приятно иметь возможность предоставить моим пользователям знакомый пользовательский интерфейс, где они могут удобно просматривать и выбирать папки.
Я долго искал что-то подобное, поэтому подумал, что опубликую это здесь, чтобы другие могли извлечь из этого пользу.
Вот как это выглядит в Win 7:
//***********************
//** Choose a directory **
//** uses Messages **
//***********************
//General usage here:
// http://www.delphipages.com/forum/showthread.php?p=185734
//Need a class to hold a procedure to be called by Dialog.OnShow:
type TOpenDir = class(TObject)
public
Dialog: TOpenDialog;
procedure HideControls(Sender: TObject);
end;
//This procedure hides de combo box of file types...
procedure TOpenDir.HideControls(Sender: TObject);
const
//CDM_HIDECONTROL and CDM_SETCONTROLTEXT values from:
// doc.ddart.net/msdn/header/include/commdlg.h.html
// CMD_HIDECONTROL = CMD_FIRST + 5 = (WM_USER + 100) + 5;
//Usage of CDM_HIDECONTROL and CDM_SETCONTROLTEXT here:
// msdn.microsoft.com/en-us/library/ms646853%28VS.85%29.aspx
// msdn.microsoft.com/en-us/library/ms646855%28VS.85%29.aspx
CDM_HIDECONTROL = WM_USER + 100 + 5;
CDM_SETCONTROLTEXT = WM_USER + 100 + 4;
//Component IDs from:
// msdn.microsoft.com/en-us/library/ms646960%28VS.85%29.aspx#_win32_Open_and_Save_As_Dialog_Box_Customization
//Translation into exadecimal in dlgs.h:
// www.koders.com/c/fidCD2C946367FEE401460B8A91A3DB62F7D9CE3244.aspx
//
//File type filter...
cmb1: integer = $470; //Combo box with list of file type filters
stc2: integer = $441; //Label of the file type
//File name const...
cmb13: integer = $47c; //Combo box with name of the current file
edt1: integer = $480; //Edit with the name of the current file
stc3: integer = $442; //Label of the file name combo
var H: THandle;
begin
H:= GetParent(Dialog.Handle);
//Hide file types combo...
SendMessage(H, CDM_HIDECONTROL, cmb1, 0);
SendMessage(H, CDM_HIDECONTROL, stc2, 0);
//Hide file name label, edit and combo...
SendMessage(H, CDM_HIDECONTROL, cmb13, 0);
SendMessage(H, CDM_HIDECONTROL, edt1, 0);
SendMessage(H, CDM_HIDECONTROL, stc3, 0);
//NOTE: How to change label text (the lentgh is not auto):
//SendMessage(H, CDM_SETCONTROLTEXT, stc3, DWORD(pChar('Hello!')));
end;
//Call it when you need the user to chose a folder for you...
function GimmeDir(var Dir: string): boolean;
var
OpenDialog: TOpenDialog;
OpenDir: TOpenDir;
begin
//The standard dialog...
OpenDialog:= TOpenDialog.Create(nil);
//Objetc that holds the OnShow code to hide controls
OpenDir:= TOpenDir.create;
try
//Conect both components...
OpenDir.Dialog:= OpenDialog;
OpenDialog.OnShow:= OpenDir.HideControls;
//Configure it so only folders are shown (and file without extension!)...
OpenDialog.FileName:= '*.';
OpenDialog.Filter:= '*.';
OpenDialog.Title:= 'Chose a folder';
//No need to check file existis!
OpenDialog.Options:= OpenDialog.Options + [ofNoValidate];
//Initial folder...
OpenDialog.InitialDir:= Dir;
//Ask user...
if OpenDialog.Execute then begin
Dir:= ExtractFilePath(OpenDialog.FileName);
result:= true;
end else begin
result:= false;
end;
finally
//Clean up...
OpenDir.Free;
OpenDialog.Free;
end;
end;
Если вы используете JVCL, вы можете использовать TJvSelectDirectory. При этом вы можете переключаться между старым и новым стилем, устанавливая свойство. Например:
Dlg := TJvSelectDirectory.Create(Self);
try
Dlg.Title := MyTitle;
Dlg.InitialDir := MyStartDir;
Dlg.Options := Dlg.Options + [sdAllowCreate, sdPerformCreate];
Dlg.ClassicDialog := False; //switch style
if Dlg.Execute() then
NewDir := Dlg.Directory;
finally
Dlg.Free;
end;