Выбор каталога с TOpenDialog

39

Мне бы очень хотелось узнать различные способы, которыми я мог бы выбрать каталог с помощью TOpenDialog, будь то загрузка нового компонента или использование того, что предоставляется Delphi, но предпочтительно использование того, что предоставляется Delphi.

До этого я использовал команду SelectDirectory, но я думаю, что было бы трудностью для пользователей моей программы искать указанный каталог.

Я думаю, что SelectDirectory является "слабым", потому что это может быть долгий процесс при поиске нужного вам каталога. Скажем, например, вы хотите перейти к каталогу данных приложения. Как долго или трудно было бы там перемещаться? В конце концов, пользователи могут даже не достичь желаемого каталога.

Мне нужно что-то подобное, когда пользователь может копировать и вставлять каталоги в адресную строку каталога наверху.

Изображение 683

Благодарим вас за все ваши ответы.

  • 0
    SelectDirectory использует системный диалог выбора собственной директории. Вы, кажется, хотите использовать что-то еще, но вы не говорите, что слабого в SelectDirectory, и вы не говорите, какие функции вы ищете в замене.
  • 0
    @ Дэвид: это не так просто. FileCtrl.SelectDirectory имеет две перегруженные реализации. Один из них создает диалог в стиле Windows 3.1, а другой - собственный диалог.
Показать ещё 10 комментариев
Теги:
delphi-2010

5 ответов

58
Лучший ответ

Вы можете использовать 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)
  • 0
    Нет, мне не нравится такое ветвление в версии для Windows. Кроме того, слияние, в этом сольном исполнении отсутствуют разные способы, как того требует OP.
  • 2
    TFileOpenDialog! = TOpenDialog ... TOpenDialog не имеет такой опции, а TFileOpenDialog не существует в FireMonkey
52

Вы знаете, что две перегруженные функции, называемые FileCtrl.SelectDirectory, создают совершенно разные диалоги, правильно?

SelectDirectory(s, [], 0);

Снимок экрана http://privat.rejbrand.se/oldseldir.png

SelectDirectory('Select a directory', s, s, []);

Снимок экрана http://privat.rejbrand.se/newseldir.png

  • 2
    «Välf mapp» наверняка превосходит «Выбрать каталог» +1
  • 0
    @ Дэвид: Ну, считай это доказательством «естественности» диалога!
Показать ещё 3 комментария
6

Просто нашел код ниже, который, кажется, отлично работает в XP и Vista, Win7. Он предоставляет пользовательский интерфейс для выбора каталога. Он использует TOpenDialog, но отправляет ему несколько сообщений, чтобы очистить внешний вид для целей выбора каталога.

Пострадав от ограниченных возможностей, предоставляемых самой Windows, приятно быть в состоянии дать моим пользователям знакомый интерфейс, где они могут просматривать и выбирать папку удобно.

Я долго искал что-то подобное, поэтому подумал, что я разместил его здесь, чтобы другие могли извлечь из этого выгоду.

Вот как это выглядит в Win 7:

Изображение 7769

//***********************
//** 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;
  • 2
    Мне это нравится, но немного раздражает, что на последнем шаге нужно дважды выбрать папку. И вы не можете выбрать ничего, кроме последнего каталога в дереве.
  • 0
    Независимо от того, что вы установили для InitialDir, он открывается в папке «Документы», что делает его бесполезным.
4

Просто включите

FileCtrl.pas

var
  sDir:String;
begin
  SelectDirectory('Your caption','',sDir);
end;

Просто оставьте второй аргумент пустым, если хотите увидеть все каталоги, включая рабочий стол. Если вы установите второй аргумент для любого допустимого пути, тогда ваш диалог будет иметь этот путь к верхней папке, и вы не сможете перемещаться дальше этого.

Например:

SelectDirectory('Your caption','C:\',sDir) не позволит вам выбрать что-либо за пределами C:\, например D:\ или E:\ и т.д.

Поэтому полезно оставить его пустым.

2

Если вы используете 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; 

Ещё вопросы

Сообщество Overcoder
Наверх
Меню