Desarrollo con el Explorador de Windows

Explorador de Windows es una aplicación eficaz de administración y exploración de recursos. Se puede acceder al Explorador de Windows como un todo integrado a través de Explorer.exe o la interfaz IExplorerBrowser . El Explorador de Windows (Explorer.exe) se puede generar como un proceso independiente mediante ShellExecuteEx o una función similar.

Las ventanas abiertas del explorador se pueden detectar y programar mediante IShellWindows (CLSID_ShellWindows) y se pueden crear nuevas instancias del Explorador de Windows mediante IWebBrowser2 (CLSID_ShellBrowserWindow).

En el ejemplo de código siguiente se muestra cómo se puede usar el modelo de automatización del Explorador de Windows para crear y detectar ventanas del explorador que se ejecutan.

#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;
}

El área cliente del Explorador de Windows se puede hospedar mediante la interfaz IExplorerBrowser . El cliente del Explorador de Windows y los controles de árbol de espacios de nombres son componentes estándar de Windows Vista y versiones posteriores. Los desarrolladores pueden reutilizar las interfaces como componentes de compilación. Un uso común de estos controles es crear exploradores personalizados adecuados para el dominio del problema.

Los controles del Explorador de Windows se clasifican en las siguientes categorías funcionales:

Los controles de navegación ayudan a los usuarios a determinar el contexto y navegar por el espacio de dominio lógico asociado, denominado espacio de páginas. Por ejemplo, el espacio de páginas para el Explorador de Windows es el espacio de nombres shell. Los espacios de páginas se componen de cero o más páginas.

En la tabla siguiente se enumeran y describen los controles de navegación disponibles en el Explorador de Windows en los sistemas operativos Windows Vista y versiones posteriores.

Control de navegación Descripción
Barra de direcciones (control de ruta de navegación) Muestra la dirección de la página actual en el espacio de páginas. Se puede hacer clic en los botones de ruta de navegación para navegar a cualquier antecesor del espacio de páginas. Los usuarios también pueden escribir direcciones URL y rutas de acceso para navegar.
Árbol de carpetas Proporciona una nueva versión de un control de árbol, optimizado para espacios de páginas grandes.
Viajes Habilita la navegación relativa a través de botones de estilo web, como Atrás y Adelante.
Título Muestra el nombre y el contexto actuales del explorador.
Espacio de páginas Muestra la rama actual del espacio de páginas. Las páginas se pueden ordenar por criterios diferentes. Los usuarios pueden hacer clic en una página para navegar a ella.

 

Controles de comando

Los controles de comandos anuncian las características y la funcionalidad del Explorador de Windows para los usuarios. Estos controles realizan acciones generales o acciones específicas de un elemento o elemento seleccionado.

Control de comandos Descripción
Barra de herramientas Muestra botones para comandos usados habitualmente (una nueva versión de una barra de herramientas de comandos). Las opciones de personalización incluyen botones desplegables, botones de división, texto descriptivo opcional y un área de desbordamiento.
Imagen prominente Aparece como un único control personalizado opcional en el centro de la barra de herramientas. Representa el comando principal para el contexto actual.
Barra de menús Presenta comandos a través de menús.
Menú contextual Enumera un subconjunto contextualmente relevante de comandos disponibles que se muestran como resultado de hacer clic con el botón derecho en un elemento.

 

Controles de propiedad y vista previa

Los controles de propiedad y vista previa se usan para obtener una vista previa de los elementos y para ver y editar las propiedades del elemento.

Control Descripción
Versión preliminar Muestra una vista previa del elemento seleccionado, como una miniatura o un icono dinámico.
Propiedades Muestra las propiedades del elemento seleccionado. Para varias selecciones, muestra un resumen de las propiedades del grupo de elementos seleccionado. Para una selección nula, muestra un resumen de las propiedades de la página actual (contenido de la vista de lista).

 

Filtrado y controles de vista

Los controles de filtrado y vista se usan para manipular el conjunto de elementos de la vista de lista y para cambiar la presentación de elementos en la vista de lista.

Control Descripción
Filter Filtra o organiza elementos en una vista de lista en función de las propiedades enumeradas como columnas. Al hacer clic en una columna se ordena por esa propiedad.
Rueda de word Filtra dinámica e incrementalmente los elementos mostrados en una vista de lista en función de una cadena de texto de entrada.
Ver Permite al usuario cambiar el modo de vista de un control listview. Se puede usar un control deslizante para determinar el tamaño del icono.

 

Listview Control

El control listview se usa para ver un conjunto de elementos en uno de los cuatro modos de vista: detalles, iconos, iconos o panorama. El control listview también permite al usuario seleccionar y activar uno o varios elementos.

Precaución

Aunque algunos de estos controles tienen nombres o funcionalidades similares a los controles estándar de Windows Presentation Foundation (WPF) que se encuentran en el espacio de nombres System.Windows.Controls, son clases distintas.

 

Estos controles independientes funcionan conjuntamente a través de eventos generados por la interacción del usuario o por los propios controles. En la tabla siguiente se muestran las tres categorías de eventos principales.

Categoría de eventos Ejemplo
Navegación Ir de una página a otra.
Número de selección Cambiar la selección actual en la vista de lista.
Ver cambio Cambiar el orden de presentación o el modo de vista en la vista de lista.