it-swarm.it

Selezione di una directory con TOpenDialog

Mi piacerebbe davvero conoscere i vari modi in cui ho potuto selezionare una directory con TOpenDialog, sia scaricando un nuovo componente o usando ciò che è fornito da Delphi, ma preferibilmente usando ciò che è fornito da Delphi.

Prima di questo, ho usato il comando SelectDirectory ma penso che sarebbe una difficoltà per gli utenti del mio programma cercare la directory specificata.

Penso che SelectDirectory sia "debole" perché può essere un processo lungo quando si cerca la directory desiderata. Supponiamo, ad esempio, che si desideri passare alla directory dei dati dell'applicazione. Quanto tempo o difficile sarebbe navigare lì? Alla fine, gli utenti potrebbero anche non raggiungere la directory desiderata.

Ho bisogno di qualcosa del genere in cui l'utente può copiare e incollare directory nella barra degli indirizzi della directory in alto.

enter image description here

Grazie per tutte le tue risposte.

47
ple103

Puoi usare TFileOpenDialog (su Vista +):

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

Personalmente, uso sempre TFileOpenDialog su Vista + e fallback usando SelectDirectory (quello buono!) Su XP, in questo modo:

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
Andreas Rejbrand

Sai che le due funzioni sovraccaricate chiamate FileCtrl.SelectDirectory produce dialoghi completamente diversi, giusto?

SelectDirectory(s, [], 0);

Screenshot

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

Screenshot

56
Andreas Rejbrand

Includi solo

FileCtrl.pas

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

Lascia vuoto il secondo argomento se vuoi vedere tutte le directory incluso il desktop. Se imposti il ​​secondo argomento su un percorso valido, la tua finestra di dialogo avrà quel percorso sulla cartella principale e non potrai spostarti oltre.

Per esempio:

SelectDirectory('Your caption','C:\',sDir) non ti consentirà di selezionare nulla oltre C:\, come D:\ o E:\ ecc.

Quindi è bene lasciarlo vuoto.

6
Shadab Mozaffar

Ho appena trovato il codice seguente che sembra funzionare bene in XP e Vista, Win7. Fornisce un'interfaccia utente per la selezione di una directory da parte dell'utente. Utilizza TOpenDialog, ma invia alcuni messaggi per ripulire l'aspetto per lo scopo di selezionare una directory.

Dopo aver sofferto delle funzionalità limitate fornite da Windows stesso, è un piacere poter offrire ai miei utenti un'interfaccia utente familiare in cui possono navigare e selezionare una cartella comodamente.

Ho cercato qualcosa del genere da molto tempo, quindi ho pensato di pubblicarlo qui in modo che altri possano trarne beneficio.

Ecco come appare in 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

Se si utilizza JVCL è possibile utilizzare TJvSelectDirectory. Con questo puoi passare dallo stile vecchio a quello nuovo impostando una proprietà. Per esempio:

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