web-dev-qa-db-ja.com

TOpenDialogでディレクトリを選択する

TOpenDialogでディレクトリを選択するさまざまな方法を知りたいのですが、新しいコンポーネントをダウンロードするか、Delphiが提供するものを使用するか、Delphiが提供するものを使用することが望ましいです。

これに先立ち、私はSelectDirectoryコマンドを使用していましたが、プログラムのユーザーが指定されたディレクトリを探すのは難しいと思います。

SelectDirectoryが「弱い」と思うのは、必要なディレクトリを検索するときに時間がかかることがあるためです。たとえば、アプリケーションデータディレクトリに移動するとします。そこをナビゲートするのにどれくらい時間がかかりますか?最終的に、ユーザーは目的のディレクトリに到達することさえできません。

ユーザーがディレクトリをコピーして、上部のディレクトリアドレスバーに貼り付けることができるようなものが必要です。

enter image description here

答えてくれてありがとう。

47
ple103

TFileOpenDialog (Vista +の場合)を使用できます。

with TFileOpenDialog.Create(nil) do
  try
    Options := [fdoPickFolders];
    if Execute then
      ShowMessage(FileName);
  finally
    Free;
  end;

個人的には、Vista +では常にTFileOpenDialogを使用し、XPではSelectDirectory(良いもの!)を使用してフォールバックします。

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)
64

FileCtrl.SelectDirectoryと呼ばれる2つのオーバーロードされた関数は、まったく異なるダイアログを生成することを知っていますか?

SelectDirectory(s, [], 0);

Screenshot

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

Screenshot

56

含めるだけ

_FileCtrl.pas

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

デスクトップを含むすべてのディレクトリを表示する場合は、2番目の引数を空のままにします。 2番目の引数を有効なパスに設定すると、ダイアログには最上位フォルダーへのパスが設定され、それ以上移動することはできません。

例えば:

SelectDirectory('Your caption','C:\',sDir)では、_C:\_や_D:\_など、_E:\_を超えるものは選択できません。

したがって、空のままにしておくのは良いことです。

6
Shadab Mozaffar

XPおよびVista、Win7で正常に動作するように見える以下のコードを見つけました。ユーザーがディレクトリを選択するためのUIを提供します。TOpenDialogを使用します。ディレクトリを選択するために外観を変更します。

Windows自体が提供する限られた機能に悩まされた後、folderを快適に閲覧および選択できる使い慣れたUIをユーザーに提供できることは喜ばしいことです。

私はこのようなものを長い間探していたので、他の人がそれを利用できるようにここに投稿すると思いました。

Win 7では次のようになります。

screen capture

//***********************
//** 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;
6
RobertFrank

[〜#〜] 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; 
3
yonojoy