Developing with Windows Explorer

Windows Explorer in Windows Vista® is a powerful resource-browsing and management application. Windows Explorer can be accessed as an integrated whole through Explorer.exe or the IExplorerBrowser Shell Interface.

Windows Explorer (Explorer.exe) can be spawned as a separate process using the ShellExecuteEx or similar function. The command line options are documented on the Microsoft Windows Support site in the article "Windows Explorer Command-Line Options."

Open explorer windows can be discovered and programmed using IShellWindows/ CLSID_ShellWindows, and new instances of Windows Explorer can be created using IWebBrowser2/ CLSID_ShellBrowserWindow.

The following C++ code sample demonstrates how the Explorer automation model can be used to create and discover explorer windows that are running.

#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 backwards to make sure the windows that close
            // don't cause the array to be re-ordered
            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 calling IWebBrowser2::Navigate2() with
 
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
        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;
}

// this depends on a bug fix made for Vista RTM
 
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;
}

The Windows Explorer client area can be hosted by using the IExplorerBrowser Shell interface. The Windows Explorer client and the name space tree controls are standard components of Windows Vista, and these interfaces are public. Therefore, developers can reuse the interfaces as building components. One common use of these controls is to create customized explorers appropriate to the problem domain.

The controls in Windows Explorer are classified into the following functional categories: Navigation controls, Command controls, Property and preview controls, Filtering and view controls, and Listview control.

Navigation Control

Navigation controls assist users in determining context and navigating the associated logical domain space, called the pagespace. For example, the pagespace for Windows Explorer is the Shell namespace. Pagespaces are composed of zero or more pages.

The following table lists and describes the Navigation Controls available in Windows Explorer in the Windows Vista operating system.

Navigation Control

Description

Address Bar (Breadcrumb control)

Displays the address of the current page in the pagespace. Breadcrumb buttons can be clicked to navigate up to any ancestor in pagespace. Users can still type URLs and paths to navigate.

Folder Tree

Provides a new version of a tree control, optimized for large pagespaces.

Travel

Enables relative navigation through Web-style buttons such as Back and Forward.

Title

Displays the current explorer name and context.

Pagespace

Displays the current branch of the pagespace. Pages can be ordered by different criteria. Users can click a page to navigate to it.

Command Control

Command controls advertise the features and functionality of the explorer to users and perform either general actions, or actions specific to one selected item or items.

Command Control

Description

Toolbar

Displays buttons for commonly used commands (a new version of a command toolbar). Customization options include drop-down buttons, split buttons, optional descriptive text, and an overflow area.

Hero

Appears as an optional, single-custom control in the center of the Toolbar. Represents the primary command for the current context.

Menu Bar

Presents commands through menus (legacy control in windows Explorer).

Context Menu

Lists a contextually relevant subset of available commands that are displayed as a result of clicking with the right mouse button.

Property and Preview Control

Property and preview controls are used to preview items, view and edit item properties.

Control

Description

Preview

Displays preview of the selected item, such as a thumbnail or a Live Icon.

Properties

Displays properties of the selected item. For multiple selections, displays summary of properties for the selected group of items. For null selection, displays summary of properties for the current page (contents of the listview).

Filtering and View Controls

Filtering and view controls are used to manipulate the set of items in the listview and changing the presentation of items in the Listview.

Control

Description

Filter

Filters or arranges items in listview based on properties listed as columns. Clicking on a column sorts by that property.

Wordwheel

Dynamically and incrementally filters the displayed items in Listview based on input text string.

View

Enables the user to change the view mode of the listview control. Also a slider can be used to determine icon size.

Listview Control

The Listview control is used to view a set of items in one of four view modes: Details, Tiles, Icons or Panorama. The Listview control also enables the user to interact with one or more items through selection and activation.

Caution noteCaution

Although some of these controls have similar names and/or functionality to standard WPF controls found in the System.Windows.Controls namespace, they are distinct classes.

These separate controls are wired together largely through events generated by either user interaction or generated by the controls themselves. Three primary event categories include:

Event category

Example

Navigation

Going from one page to another.

Selection

Changing the current selection in the listview.

View Change

Changing the presentation order or view mode in the listview.

With such a rich and functional set of controls to draw upon, developers can focus on describing their pagespace and implementing behavior associated with their content.

At the time of this writing, the Windows SDK does not yet contain documentation on these explorer controls; however, the ExplorerBrowserAPI example is provided in the Samples directory.

Community Additions

Show: