In diesem kleinen Tutorial zum Windows API Code Pack werden wir uns näher mit den Shell-Interfaces zu Ordnern und Dateien in der Windows API auseinandersetzen.

Der grobe Aufbau der betreffenden Klassen im Windows API Code Pack schaut folgendermaßen aus:

Aufbau der Shell-Klassen

Wichtig für das Tutorial sind eigentlich nur ShellFileSystemFolder für die Ordner und ShellFile für die Dateien. ShellLibrary haben wir bereits im vorherigen Tutorial verwendet.

 

Eigenschaften

Zugriff auf die Eigenschaften einer Datei oder eines Ordners ermöglicht die Properties-Eigenschaft des ShellObjects. Unter System finden sich alle möglichen Eigenschaften, die eine Datei besitzen kann, der Zugriff kann über zwei Varianten erfolgen:

// Entweder so:
var p = file.Properties.System.Title;

// Oder über den Namen der Eigenschaft:
var p2 = file.Properties.GetProperty<string>("System.Title");

Beide Male wird ein ShellProperty-Objekt zurückgeliefert. Den eigentlichen Inhalt der Dateieigenschaft erhalten wir schließlich über Value:

string title = file.Properties.System.Title.Value;

Darüber hinaus können wir uns natürlich auch mit LINQ bestimmte Dateien zurückliefern lassen. Um zum Beispiel um alle Dateien eines Ordners zu erhalten, die das Schlüsselwort bzw. die Markierung “Visual Studio 2010” enthalten genügt die folgende LINQ-Abfrage:

var files =
    from f in ShellFileSystemFolder.FromFolderPath(@"C:\Folder\")
    let k = f.Properties.System.Keywords.Value ?? Enumerable.Empty<string>()
    where k.Contains("Visual Studio 2010")
    select f;

foreach (var file in files)
    Console.WriteLine(file.Name);

k enthält dabei entweder den String-Array von f.Properties.System.Keywords.Value, oder, falls die Eigenschaft bei der Datei nicht gesetzt wurde und null zurückgeliefert wird, eine leere String-Auflistung IEnumerable<string>.

Vorschaubilder

Das Windows API Code Pack bietet eine komfortable Möglichkeit auf die Vorschaubilder von Ordnern und Dateien, die man unter anderem vom Windows Explorer, zu zugreifen und das sowohl als System.Drawing.Bitmap, als auch als System.Windows.Media.Imaging.BitmapSource für WPF-Anwendungen. Die Einbindung in ein WPF-Image ist dementsprechend einfach.

Die Bilder stehen unter der Eigenschaft Thumbnail in den vier Größen Small, Medium, Large, ExtraLarge zur Verfügung.

<Image Source="{Binding Path=SelectedItem.Thumbnail.MediumBitmapSource}" />

Eine Verwendung in einer Anwendung könnte z. B. folgendermaßen ausschauen:

Beispielanwendung

, ,

Windows 7 LibrariesMit dem neuen Betriebssystem Windows 7 hat Microsoft die Libraries eingeführt, die Dateien aus unterschiedlichen Ordnern zusammenfassen können.

Die Beschreibungen dieser Libraries liegen im Verzeichnis …\AppData\Roaming\Microsoft\Windows\
Libraries als XML-Dateien mit der Endung .ms-library
vor.

Für den Umgang mit den Libraries hat Microsoft der Windows Shell einige neue Interfaces spendiert. Damit .Net-Entwickler nicht leer ausgehen hat man darüberhinaus das Windows API Code Pack ins Leben gerufen, einen .Net-Wrapper, der neben den Windows 7-Neuerungen (Libraries, Jump Lists, etc.) auch DirectX 10.0/10.1/11.0, Direct2D, DirectWrite und zahlreiche andere APIs umfasst.

Arbeiten mit Libraries

Für den Einsatz der Libraries muss lediglich Microsoft.WindowsAPICodePack.Shell als Referenz zum Projekt hinzugefügt werden.

Dreh- und Angelpunkt ist die Klasse ShellLibrary, die alles nötige zum Erstellen, Laden und Bearbeiten von Libraries bereitstellt.

Libraries laden

Zum Laden steht die Load-Methode zur Verfügung, die entweder den Namen oder ein IKnownFolder-Objekt erwartet. Mehr zu Known Folders: http://msdn.microsoft.com/en-us/library/bb776911(VS.85).aspx. KnownFolders enthält eine Auflistung dieser besonderen Ordner, zu denen auch die 4 Standard-Libraries gehören. Um also die Video-Bibliothek zu laden, reicht folgende Zeile. Mit dem 2. Parameter können wir dabei festlegen, ob wir die Library verändern, z. B. neue Ordner hinzufügen oder alte entfernen, wollen.

ShellLibrary lib = ShellLibrary.Load(KnownFolders.VideosLibrary, true);

Libraries auslesen

Wir haben nun vollen Zugriff auf die Library und können z. B. alle Ordner der Library auslesen:

foreach (ShellFolder dir in lib)
    Console.WriteLine(dir.ParsingName);

Libraries bearbeiten

Neben dem bloßen Auslesen können wir der Library auch neue Ordner spendieren, oder bisherige entfernen. Dabei ist zu beachten, dass die Library zuvor auch mit der entsprechenden Einstellung geladen werden musste. Der zweite Parameter der Load-Methode musste also den Wert false besitzen.

// Ordner hinzufügen
lib.Add("D:/test/");

// Ordner entfernen
lib.Remove("D:/test/");

Last but not least, lässt sich sogar der vom Explorer bekannte Dialog ins eigene Programm einbinden:

ShellLibrary.ShowManageLibraryUI(
    lib.Name,
    IntPtr.Zero,
    "Hi there",
    "Ok, let's add some stuff",
    true
    );

win7_libs_002 Mit dem ersten Parameter geben wir den Namen der Library an, mit der der Dialog hantieren soll, es folgt der Handler des Elternfensters, als drittes der Titel des Dialogs und schließlich der Beschreibungstext. Der Dialog liefert keinerlei Informationen über die vom Benutzer getätigten Änderungen zurück.

Libraries können für eine bestimmte Anzeige optimiert werden. Vier verschiedene stehen zur Auswahl: Dokumente, Musik, Bilder und Videos. Diese Anzeigeart lässt sich über die Eigenschaft LibraryType steuern:

lib.LibraryType = LibraryFolderType.Music;

Das Icon der Library lässt sich über IconResourceId ansprechen:

// Nutze das gleiche Icon wie die Musik-Library
lib.IconResourceId = new IconReference("imageres.dll", -1004);

Libraries erstellen

Für die Erstellung neuer Libraries kann man einfach auf den Konstruktor der ShellLibrary-Klasse zurückgreifen:

ShellLibrary test = new ShellLibrary("MyLib", false);

// Soll Musik enthalten
test.LibraryType = LibraryFolderType.Music;

Dateien auslesen

Um schließlich alle Dateien einer Library aufzulisten müssen wir uns eine eigene Methode schreiben, die alle Unterordner rekursiv durchläuft. In etwa so:

List<ShellFile> files = new List<ShellFile>();

foreach (ShellFolder dir in lib)
    GetAllFiles(dir, files);

// ...

void GetAllFiles(ShellFolder parent, List<ShellFile> files)
{
    foreach (ShellObject obj in parent)
    {
        // Check if it's a file
        ShellFile file = obj as ShellFile;
        if (file != null)
        {
            files.Add(file);
        }

        // Check if it is a folder
        ShellFolder folder = obj as ShellFolder;
        if (folder != null)
        {
            GetAllFiles(folder, files);
        }
    }
}

Ende

Fragen, Erweiterungsvorschläge, Kritik etc. können in den Kommentaren geäußert werden.

, ,

Vor zwei Tagen ist Version 1.0 des Windows API Code Pack for .Net erschienen. Damit stehen hoffentlich keine Bugs mehr meinem geplanten Tutorial über Windows 7 Libraries im Weg *yuchhe*.

Wie es sich für jeden zweitklassigen Blog gehört, hier die Auflistung der Neuerungen:

  • Shell Search API Unterstützung
  • Drag & Drop für Shell Objekte
  • Direct3D und Direct2D Interoperabilität
  • Typografie und Font Enumeration DirectWrite APIs
  • Bugs fixes und Performanceverbesserungen

Link:
http://code.msdn.microsoft.com/WindowsAPICodePack

,

Auch wenn alle Welt darüber berichtet und es sich deswegen kaum lohnt einen weiteren Beitrag in die Welt zu setzen: Auch ich habe mir die neue Windows 7 Beta heruntergeladen und auf einem etwas betagten Laptop installiert.
Windows 7 Installation
Zwar muss ich dementsprechend auf alle spektakulären visuellen Effekte verzichten, nichtsdestotrotz läuft Windows 7 aber erfreulich schnell und stabil.
Windows 7

,