2016-05-11 8 views
2

Der folgende Code führt auf verschiedenen Computern zu unterschiedlichen Ergebnissen. Eine Maschine gibt nur den Desktop-Ordner (nicht gewünscht), die andere gibt den Desktop-Ordner und Computer, zugeordnete Laufwerke (gewünscht).SelectDirectory enthält auf einigen Computern keine Laufwerke.

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Directory : String; 
begin 
    FileCtrl.SelectDirectory('Caption', 'Desktop', Directory, [sdNewUI, sdShowEdit]); 
end; 

One eine Maschine gibt es:

Bad Browse

Auf einem anderen gibt es:

Good Browse

Das fühlt sich an wie ein Fenster Einstellung, aber ich bin nicht sicher, wo Anfang. Verwenden von Delphi XE, Windows 10.

Alle Gedanken sind willkommen. Vielen Dank für Ihre Zeit.

+1

Wenn ich es wäre, würde ich den neuen allgemeinen Dateieingabedialog verwenden, der in Vista eingeführt wurde, der die native Ordnerauswahl ist –

+0

Um den root Desktop Namespace anzuzeigen, sollten Sie den 'Root' Parameter auf eine leere Zeichenfolge setzen ") anstelle von" Desktop ". –

+0

Danke @RemyLebeau! '' '' Anstelle von ''Desktop'' löste mein Problem. – user1627960

Antwort

3

Umgehung
Verwenden Sie einen TFileOpenDialog statt *.
Set FileOpenDialog1.Options:= [fdoPickFolders,fdoPathMustExist]

enter image description here

Jetzt haben Sie einen Dialog, dass:

  • funktioniert immer.
  • Ermöglicht Kopieren und Einfügen

*) Nicht mit dem TOpenDialog verwechselt werden, die Sie ermöglicht nicht nur auf Ordner auswählen.

Lösung für Windows XP
Beachten Sie, dass die neue TFileOpenDialog nur für Vista arbeitet und darüber.
Ihr Programm wird nicht auf XP funktionieren, wenn Sie dieses Steuerelement einschließen.
Wenn Sie den Dialog unter XP starten, wird ein EPlatformVersionException generiert.

Sie wollen stattdessen den folgenden Code verwenden, wenn Sie rückwärts sein wollen kompatibel:

uses JclSysInfo; //because you have XE use JCL. 

... 
var 
    WinMajorVer: Integer; 
    Directory: string; 
    FileDialog: TFileOpenDialog; 
begin 
    WinMajorVer:= GetWindowsMajorVersionNumber; 
    if WinMajorVer < 6 then begin //pre-vista 
    //To show the root Desktop namespace, you should be setting the Root parameter to an empty string ('') instead of 'Desktop' 
    FileCtrl.SelectDirectory('Caption', '', Directory, [sdNewUI, sdShowEdit]); 
    end else begin 
    FileDialog:= TFileOpenDialog.Create(self); 
    try 
     FileDialog.Options:= [fdoPickFolders,fdoPathMustExist]; 
     if FileDialog.Execute then Directory:= FileOpenDialog1.FileName; 
    finally 
     FileDialog.Free; 
    end; 
    end; 
    Result:= Directory; 
end; 

Empfohlene Lektüre:
detect windows version

EDIT

FileCtrl.SelectDirectory('Caption', 'Desktop', Directory, [sdNewUI, sdShowEdit]); 

Die 'Desktop' geht in die Root Parameter, die wie so gehandhabt wird:

... 
    SHGetDesktopFolder(IDesktopFolder); 
    IDesktopFolder.ParseDisplayName(Application.Handle, nil, 
     Root, Eaten, RootItemIDList, Flags); 
... 

Hier ist, was MSDN für IDesktopFolder.ParseDisplayName zu sagen hat:

pszDisplayName [in]
Typ: LPWSTR
Ein nullterminierten Unicode-String mit der Anzeigename. Da jeder Shell-Ordner seine eigene Syntax zum Parsen definiert, kann die Form, die diese Zeichenfolge annehmen kann, variieren. Der Desktop-Ordner akzeptiert beispielsweise Pfade wie "C: \ My Docs \ My File.txt". Es akzeptiert auch Verweise auf Elemente im Namespace, denen eine GUID mit der Syntax ":: {GUID}" zugeordnet ist.

Beachten Sie, dass in der Dokumentation angegeben wird, dass der Desktop-Ordner Pfade und Leitfäden akzeptiert. Es akzeptiert keine 'Desktop'. Weil das auch nicht ist.

Die Tatsache, dass 'Desktop' als root auf einem System aber nicht anderen funktioniert, ist einige nicht dokumentierte behoben in einer älteren/neueren Version der IDesktopFolder Schnittstelle gemacht.

Technische Lösung
Verwenden '' als 'root', wie oben in meinem Code gezeigt.

Offensichtlich SelectDirectory ist ein wirklich schlechtes Design von Microsoft, das nie verwendet werden sollte. Es saugt einfach auf so viele Arten. Ich empfehle es nicht verwendet werden, wann immer es möglich ist.

+0

Die * App * funktioniert immer noch unter XP, aber der * Dialog * wird nicht ausgeführt ('EPlatformVersionException' wird ausgelöst, wenn der Dialog zur Laufzeit aufgerufen wird). –

+0

@RemyLebeau, Danke für das Aufräumen. Ich habe keine XP zu testen, also war ich mir nicht sicher, was passieren würde. Da es unter XP startet, habe ich einen Workaround-Code hinzugefügt. – Johan

+0

'wenn WinVer in ...' - AUTSCH! Es wäre viel einfacher, 'if Win32MajorVersion <6 then ...' stattdessen zu verwenden. Und benutze 'try/finally' um den' TFileOpenDialog' zu befreien. –

Verwandte Themen