Soru TOpenDialog ile bir dizin seçme


İster yeni bir bileşen indiriyor olsun, ister Delphi tarafından sağlananları kullanarak, tercihen Delphi tarafından sağlananları kullanarak TOpenDialog ile bir dizin seçebileceğim çeşitli yolları bilmek isterim.

Bundan önce, SelectDirectory komutunu kullanıyorum ama programımın kullanıcıları için belirtilen dizini aramasının zor olacağını düşünüyorum.

Ben SelectDirectory 'zayıf' düşünüyorum çünkü istediğiniz dizini ararken uzun bir süreç olabilir. Örneğin, Uygulama Veri dizinine gitmek istiyorsunuz. Oraya gitmek ne kadar uzun ya da zor olurdu? Sonunda, kullanıcılar istedikleri dizine bile ulaşamayabilirler.

Kullanıcının dizinleri orada üstteki dizin adres çubuğuna kopyalayıp yapıştırabileceği bir şeye ihtiyacım var.

enter image description here

Bütün cevaplarınız için teşekkür ederim.


44
2017-09-14 20:38


Menşei


@peter Bence en iyi seçeneğiniz, Vista + 'da fdoPickFolders ve XP ve aşağıdaki SelectDirectory' un SHBrowseForFolder sürümüyle TFileOpenDialog. - David Heffernan
İhtiyacınız olan şey, bir formu ve bazı beyinleri kullanarak kendi klasörünüzü taramaktır. - opc0de
Klasör koduna göz atma. Gelecek için imkansız kanıt ve iyi yapmak çok zor. - David Heffernan
@David Bence FindFirst ve FindNext çok ileri bir kanıttır. - opc0de
Çeşitli ücretsiz Windows yazılımlarında gördüğüm hızlı ve kirli bir şekilde: kaydetme iletişim kutusunu kullan ve sonucun dosya adını görmezden gel. üzerinde SelectDirectoryfonksiyonu: sadece bir sarıcı SHBrowseForFolderAncak, modern kabuk özelliklerinin tümünü kullanmaz (düzenleme kontrolünü içerir - BIF_EDITBOX {v 4.71}). Bunun yerine doğrudan bu işlevi kullanmanızı veya birinin hazır ambalajını kullanmayı öneririm. - Premature Optimization


Cevaplar:


Kullanabilirsiniz TFileOpenDialog (Vista + 'da):

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

Şahsen her zaman TFileOpenDialog Vista + ve kullanarak geri SelectDirectory (iyi olanı!) XP'de şöyle:

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)

62
2017-09-14 20:45



Hayır, Windows sürümünde bu tür dallanmalardan hoşlanmıyorum. Ayrıca, birleştirme, bu solo performans OP tarafından talep edilen farklı yollardan yoksundur. - Premature Optimization
TFileOpenDialog! = TOpenDialog ... TOpenDialog böyle bir seçeneğe sahip değil ve TFileOpenDialog FireMonkey'de mevcut değil - Flash Thunder


Bildiğiniz iki aşırı fonksiyonun olduğunu biliyorsunuz FileCtrl.SelectDirectory Tamamen farklı diyaloglar üretir, değil mi?

SelectDirectory(s, [], 0);

Ekran görüntüsü http://privat.rejbrand.se/oldseldir.png

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

Ekran görüntüsü http://privat.rejbrand.se/newseldir.png


53
2017-09-14 21:02



"Välf mapp" emin adım "Select Directory" +1 - David Heffernan
@David: Peki, diyaloğun 'doğuşunun' bir kanıtı olarak düşünün! - Andreas Rejbrand
Gerçekten, iki cevabınızı bir araya getirmeniz ve Vista + ile XP arasındaki davranış değişikliği hakkında biraz tartışma eklemelisiniz. - David Heffernan
Biliyorsunuz, aslında bu proc'un iki versiyonu olduğunu bilmiyordum. Ben hiç kullanmadım - ama epik ben kabuk ile dans etmek zorunda değildi - teşekkürler! - Jon Lennart Aasenden
Bence aynı şeyi kullanamazsın s Root parametresi ve Directory parametresi için değişken (ikinci ve üçüncü parametre SelectDirectory('Select a directory', s, s, []);) - manlio


Sadece aşağıdaki kodu XP ve Vista, Win7'de iyi çalışıyor gibi görünüyor. Bir kullanıcının bir dizin seçmesi için bir UI sağlar. TOpenDialog kullanır, ancak bir dizin seçme amacıyla görünümü temizlemek için birkaç mesaj gönderir.

Windows tarafından sağlanan sınırlı yeteneklerden muzdarip olduktan sonra, kullanıcılara göz atabilecekleri ve seçebilecekleri tanıdık bir kullanıcı arayüzüne sahip olmak için bir zevk. Klasör rahatça.

Böyle bir şeyi uzun zamandır arıyordum, bu yüzden burada yayınlayacağımı düşündüm, böylece başkaları bundan faydalanabilir.

İşte Win 7'de nasıl göründüğü:

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
2017-09-05 13:58



Bunu beğendim, ama son adımda klasörü iki kez seçmek zorunda olmanız rahatsız edici. Ve bir ağaçtaki son dizin dışında hiçbir şey seçemezsiniz. - Aaron


Sadece dahil

FileCtrl.pas

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

Masaüstü dahil olmak üzere tüm dizinleri görmek istiyorsanız ikinci argümanı boş bırakın. Herhangi bir geçerli Yol için ikinci argümanı ayarlarsanız, diyaloğunuz bu klasöre giden o yola sahip olur ve bunun ötesine geçemezsiniz.

Örneğin:

SelectDirectory('Your caption','C:\',sDir) ötesinde bir şey seçmenize izin vermez C:\, sevmek D:\ veya E:\  vb.

Yani boş bırakmak güzeldir.


6
2017-11-28 19:44





Eğer kullanıyorsanız JVCL TJvSelectDirectory uygulamasını kullanabilirsiniz. Bununla bir özelliği ayarlayarak eski ve yeni stil arasında geçiş yapabilirsiniz. Örneğin:

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; 

2
2017-07-17 07:59