Entwickeln mit Windows Explorer

Windows Explorer ist eine leistungsstarke Ressourcensuch- und Verwaltungsanwendung. Auf Windows Explorer kann als Ganzes über Explorer.exe oder die IExplorerBrowser-Schnittstelle zugegriffen werden. Windows Explorer (Explorer.exe) kann als separater Prozess mit ShellExecuteEx oder einer ähnlichen Funktion erzeugt werden.

Geöffnete Explorer-Fenster können mithilfe von IShellWindows (CLSID_ShellWindows) ermittelt und programmiert werden, und neue Instanzen von Windows Explorer können mithilfe von IWebBrowser2 (CLSID_ShellBrowserWindow) erstellt werden.

Im folgenden Codebeispiel wird veranschaulicht, wie das Windows Explorer-Automatisierungsmodell verwendet werden kann, um ausgeführte Explorer-Fenster zu erstellen und zu ermitteln.

#define _WIN32_WINNT 0x0600
#define _WIN32_IE 0x0700
#define _UNICODE

#include <windows.h>
#include <shobjidl.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <propvarutil.h>
 
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "propsys.lib")
 
// Use the Shell Windows object to find all of the explorer and IExplorer 
// windows and close them.
 
void CloseExplorerWindows()
{
    IShellWindows* psw;
    
    if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, 
                                   NULL,  
                                   CLSCTX_LOCAL_SERVER, 
                                   IID_PPV_ARGS(&psw))))
    {
        VARIANT v = { VT_I4 };
        if (SUCCEEDED(psw->get_Count(&v.lVal)))
        {
            // Walk backward to make sure that the windows that close
            // do not cause the array to be reordered.
            while (--v.lVal >= 0)
            {
                IDispatch *pdisp;
                
                if (S_OK == psw->Item(v, &pdisp))
                {
                    IWebBrowser2 *pwb;
                    if (SUCCEEDED(pdisp->QueryInterface(IID_PPV_ARGS(&pwb))))
                    {
                        pwb->Quit();
                        pwb->Release();
                    }
                    pdisp->Release();
                }
            }
        }
        psw->Release();
    }
}
 
// Convert an IShellItem or IDataObject into a VARIANT that holds an IDList
// suitable for use with IWebBrowser2::Navigate2.
 
HRESULT InitVariantFromObject(IUnknown *punk, VARIANT *pvar)
{
    VariantInit(pvar);
 
    PIDLIST_ABSOLUTE pidl;
    HRESULT hr = SHGetIDListFromObject(punk, &pidl);
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromBuffer(pidl, ILGetSize(pidl), pvar);
        CoTaskMemFree(pidl);
    }
    return hr;
}
 
HRESULT ParseItemAsVariant(PCWSTR pszItem, IBindCtx *pbc, VARIANT *pvar)
{
    VariantInit(pvar);
 
    IShellItem *psi;
    HRESULT hr = SHCreateItemFromParsingName(pszItem, NULL, IID_PPV_ARGS(&psi));
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromObject(psi, pvar);
        psi->Release();
    }
    return hr;
}

HRESULT GetKnownFolderAsVariant(REFKNOWNFOLDERID kfid, VARIANT *pvar)
{
    VariantInit(pvar);
 
    PIDLIST_ABSOLUTE pidl;
    HRESULT hr = SHGetKnownFolderIDList(kfid, 0, NULL, &pidl);
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromBuffer(pidl, ILGetSize(pidl), pvar);
        CoTaskMemFree(pidl);
    }
    return hr;
}

HRESULT GetShellItemFromCommandLine(REFIID riid, void **ppv)
{
    *ppv = NULL;
    HRESULT hr = E_FAIL;

    int cArgs;
    PWSTR *ppszCmd = CommandLineToArgvW(GetCommandLineW(), &cArgs);
    if (ppszCmd && cArgs > 1)
    {
        WCHAR szSpec[MAX_PATH];
        StringCchCopyW(szSpec, ARRAYSIZE(szSpec), ppszCmd[1]);
        PathUnquoteSpacesW(szSpec);

        hr = szSpec[0] ? S_OK : E_FAIL;   // Protect against empty data
        if (SUCCEEDED(hr))
        {
            hr = SHCreateItemFromParsingName(szSpec, NULL, riid, ppv);
            if (FAILED(hr))
            {
                WCHAR szFolder[MAX_PATH];
                GetCurrentDirectoryW(ARRAYSIZE(szFolder), szFolder);

                hr = PathAppendW(szFolder, szSpec) ? S_OK : E_FAIL;
                if (SUCCEEDED(hr))
                {
                    hr = SHCreateItemFromParsingName(szFolder, NULL, riid, ppv);
                }
            }
        }
    }
    return hr;
}

HRESULT GetShellItemFromCommandLineAsVariant(VARIANT *pvar)
{
    VariantInit(pvar);

    IShellItem *psi;
    HRESULT hr = GetShellItemFromCommandLine(IID_PPV_ARGS(&psi));
    if (SUCCEEDED(hr))
    {
        hr = InitVariantFromObject(psi, pvar);
        psi->Release();
    }
    return hr;
}

void OpenWindow()
{
    IWebBrowser2 *pwb;
    HRESULT hr = CoCreateInstance(CLSID_ShellBrowserWindow, 
                                  NULL,
                                  CLSCTX_LOCAL_SERVER, 
                                  IID_PPV_ARGS(&pwb));
    if (SUCCEEDED(hr))
    {
        CoAllowSetForegroundWindow(pwb, 0);

        pwb->put_Left(100);
        pwb->put_Top(100);
        pwb->put_Height(600);
        pwb->put_Width(800);
 
        VARIANT varTarget = {0};
        hr = GetShellItemFromCommandLineAsVariant(&varTarget);
        if (FAILED(hr))
        {
            hr = GetKnownFolderAsVariant(FOLDERID_UsersFiles, &varTarget);
        }

        if (SUCCEEDED(hr))
        {
            VARIANT vEmpty = {0};
            hr = pwb->Navigate2(&varTarget, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
            if (SUCCEEDED(hr))
            {
                pwb->put_Visible(VARIANT_TRUE);
            }
            VariantClear(&varTarget);
        }
        pwb->Release();
    }
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |  COINIT_DISABLE_OLE1DDE);
    if (SUCCEEDED(hr))
    {
        CloseExplorerWindows();

        OpenWindow();

        CoUninitialize();
    }
    return 0;
}

Der Clientbereich von Windows Explorer kann mithilfe der IExplorerBrowser-Schnittstelle gehostet werden. Der Windows Explorer-Client und die Namespacestruktursteuerelemente sind Standardkomponenten von Windows Vista und höher. Entwickler können die Schnittstellen als Komponenten wiederverwenden. Eine häufige Verwendung dieser Steuerelemente besteht darin, angepasste Explorer zu erstellen, die für die Problemdomäne geeignet sind.

Die Steuerelemente in Windows Explorer sind in die folgenden Funktionskategorien eingeteilt:

Navigationssteuerelemente unterstützen Benutzer bei der Ermittlung des Kontexts und beim Navigieren im zugeordneten logischen Domänenbereich, der als Pagespace bezeichnet wird. Beispielsweise ist der Pagespace für Windows Explorer der Shell-Namespace. Seitenräume bestehen aus null oder mehr Seiten.

In der folgenden Tabelle sind die Navigationssteuerelemente aufgeführt und beschrieben, die in Windows Explorer in den Betriebssystemen Windows Vista und höher verfügbar sind.

Navigationssteuerelement BESCHREIBUNG
Adressleiste (Breadcrumb-Steuerelement) Zeigt die Adresse der aktuellen Seite im Seitenbereich an. Breadcrumb-Schaltflächen können geklickt werden, um zu einem beliebigen Vorgänger im Seitenbereich zu navigieren. Benutzer können auch URLs und Pfade eingeben, um zu navigieren.
Ordnerstruktur Stellt eine neue Version eines Struktursteuerelements bereit, die für große Seitenbereiche optimiert ist.
Reise Ermöglicht die relative Navigation über Schaltflächen im Webstil wie "Zurück " und "Vorwärts".
Titel Zeigt den aktuellen Explorernamen und -kontext an.
Pagespace Zeigt den aktuellen Branch des Seitenbereichs an. Seiten können nach verschiedenen Kriterien sortiert werden. Benutzer können auf eine Seite klicken, um zu dieser zu navigieren.

 

Command-Steuerelemente für Befehle

Befehlssteuerelemente kündigen die Features und Funktionen der Windows-Explorer benutzern an. Diese Steuerelemente führen entweder allgemeine Aktionen oder Aktionen aus, die für ein oder mehrere ausgewählte Elemente spezifisch sind.

Befehlssteuerung BESCHREIBUNG
Symbolleiste Zeigt Schaltflächen für häufig verwendete Befehle an (eine neue Version einer Befehlssymbolleiste). Zu den Anpassungsoptionen gehören Dropdownschaltflächen, geteilte Schaltflächen, optionaler beschreibender Text und ein Überlaufbereich.
Hero Wird als einzelnes, optionales, benutzerdefiniertes Steuerelement in der Mitte der Symbolleiste angezeigt. Er stellt den primären Befehl für den aktuellen Kontext dar.
Menüleiste Zeigt Befehle über Menüs an.
Kontextmenü Listet eine kontextrelevante Teilmenge der verfügbaren Befehle auf, die als Ergebnis des Rechtsklicks auf ein Element angezeigt werden.

 

Eigenschaften- und Vorschausteuerelemente

Eigenschaften- und Vorschausteuerelemente werden für die Vorschau von Elementen sowie zum Anzeigen und Bearbeiten von Elementeigenschaften verwendet.

Control BESCHREIBUNG
Vorschau Zeigt eine Vorschau des ausgewählten Elements an, z. B. eine Miniaturansicht oder ein Livesymbol.
Eigenschaften Zeigt die Eigenschaften des ausgewählten Elements an. Bei mehrfacher Auswahl wird eine Zusammenfassung der Eigenschaften für die ausgewählte Gruppe von Elementen angezeigt. Bei einer NULL-Auswahl wird eine Zusammenfassung der Eigenschaften für die aktuelle Seite (Inhalte der Listview) angezeigt.

 

Filtern und Anzeigen von Steuerelementen

Filter- und Ansichtssteuerelemente werden verwendet, um den Satz von Elementen in der Listview zu bearbeiten und die Darstellung von Elementen in der Listview zu ändern.

Control BESCHREIBUNG
Filtern Filtert Elemente in einer Listenansicht basierend auf eigenschaften, die als Spalten aufgeführt sind, oder ordnet sie an. Wenn Sie auf eine Spalte klicken, wird nach dieser Eigenschaft sortiert.
Wordwheel Die angezeigten Elemente in einer Listenansicht werden dynamisch und inkrementell anhand einer Eingabetextzeichenfolge gefiltert.
Sicht Ermöglicht es dem Benutzer, den Ansichtsmodus eines Listview-Steuerelements zu ändern. Ein Schieberegler kann verwendet werden, um die Symbolgröße zu bestimmen.

 

Listview-Steuerelement

Das Listview-Steuerelement wird verwendet, um eine Reihe von Elementen in einem von vier Ansichtsmodi anzuzeigen: Details, Kacheln, Symbole oder Panorama. Das Listview-Steuerelement ermöglicht es dem Benutzer auch, ein oder mehrere Elemente auszuwählen und zu aktivieren.

Achtung

Einige dieser Steuerelemente verfügen zwar über Namen und/oder Funktionen, die den WPF-Steuerelementen (Standard Windows Presentation Foundation) im System.Windows.Controls-Namespace ähneln, aber sie sind unterschiedliche Klassen.

 

Diese separaten Steuerelemente arbeiten größtenteils über Ereignisse zusammen, die entweder durch die Benutzerinteraktion oder durch die Steuerelemente selbst generiert werden. In der folgenden Tabelle sind die drei primären Ereigniskategorien aufgeführt.

Ereigniskategorie Beispiel
Navigation Wechseln von einer Seite zur anderen.
Auswahl Ändern der aktuellen Auswahl in der Listenansicht.
Änderung anzeigen Ändern der Präsentationsreihenfolge oder des Ansichtsmodus in der Listenansicht.