Creazione di barre di esplorazione personalizzate, bande degli strumenti e bande da tavolo

La barra di Explorer è stata introdotta con Microsoft Internet Explorer 4.0 per fornire un'area di visualizzazione adiacente al riquadro del browser. Si tratta fondamentalmente di una finestra figlio all'interno della finestra di Windows Internet Explorer e può essere usata per visualizzare le informazioni e interagire con l'utente nello stesso modo. Le barre di Esplora risorse vengono in genere visualizzate come riquadro verticale sul lato sinistro del riquadro del browser. Tuttavia, una barra di Explorer può anche essere visualizzata orizzontalmente, sotto il riquadro del browser.

Screenshot that shows the vertical and horizontal Explorer Bars.

È disponibile un'ampia gamma di possibili usi per la barra di Explorer. Gli utenti possono selezionare l'opzione da visualizzare in diversi modi, tra cui la selezione dal sottomenu Barra di esplorazione del menu Visualizza o facendo clic su un pulsante della barra degli strumenti. Internet Explorer offre diverse barre standard di Explorer, tra cui Preferiti e Ricerca.

Uno dei modi in cui è possibile personalizzare Internet Explorer consiste nell'aggiungere una barra di Explorer personalizzata. Una volta implementata e registrata, verrà aggiunta al sottomenu Barra di Esplora risorse del menu Visualizza . Se selezionata dall'utente, l'area di visualizzazione della barra di Explorer può quindi essere usata per visualizzare le informazioni e accettare l'input dell'utente nello stesso modo di una normale finestra.

screen shot of the explorer bars

Per creare una barra di Explorer personalizzata, è necessario implementare e registrare un oggetto band. Gli oggetti band sono stati introdotti con la versione 4.71 della shell e offrono funzionalità simili a quelle delle finestre normali. Tuttavia, poiché sono oggetti COM (Component Object Model) e contenuti in Internet Explorer o shell, vengono implementati in modo leggermente diverso. Sono stati usati oggetti band semplici per creare le barre explorer di esempio visualizzate nel primo grafico. L'implementazione dell'esempio di barra di esplorazione verticale verrà illustrata in dettaglio in una sezione successiva.

Bande degli strumenti

Una banda di strumenti è un oggetto band introdotto con Microsoft Internet Explorer 5 per supportare la funzionalità della barra degli strumenti radio di Windows. La barra degli strumenti di Internet Explorer è in realtà un controllo rebar che contiene diversi controlli della barra degli strumenti. Creando una banda di strumenti, è possibile aggiungere una banda al controllo rebar. Tuttavia, come le barre di Explorer, una banda degli strumenti è una finestra per utilizzo generico.

screen shot of tool bands

Gli utenti visualizzano una barra degli strumenti selezionandola dal sottomenu Barre degli strumenti del menu Visualizza o dal menu di scelta rapida visualizzato facendo clic con il pulsante destro del mouse sull'area della barra degli strumenti.

Bande di scrivania

Gli oggetti band possono essere utilizzati anche per creare bande da tavolo. Anche se la loro implementazione di base è simile a Explorer Bars, le bande di scrivania non sono correlate a Internet Explorer. Una fascia di scrivania è fondamentalmente un modo per creare una finestra ancorabile sul desktop. L'utente lo seleziona facendo clic con il pulsante destro del mouse sulla barra delle applicazioni e selezionandolo dal sottomenu Barre degli strumenti .

Screenshot that shows a sample desk band.

Inizialmente, le bande della scrivania sono ancorate sulla barra delle applicazioni.

Screenshot that shows desk bands docked on the task bar.

L'utente può quindi trascinare la banda della scrivania sul desktop e apparirà come una finestra normale.

screen shot of desk bands

Implementazione di oggetti band

Vengono illustrati gli argomenti seguenti.

Nozioni di base sugli oggetti Band

Anche se possono essere usati in modo molto simile alle normali finestre, gli oggetti band sono oggetti COM presenti all'interno di un contenitore. Le barre di Explorer sono contenute in Internet Explorer e le bande della scrivania sono contenute in Shell. Anche se servono funzioni diverse, la loro implementazione di base è molto simile. La differenza principale consiste nel modo in cui viene registrato l'oggetto band, che a sua volta controlla il tipo di oggetto e il relativo contenitore. In questa sezione vengono illustrati gli aspetti dell'implementazione comuni a tutti gli oggetti band. Per altri dettagli sull'implementazione, vedere Un semplice esempio di barra di Esplora risorse personalizzate.

Oltre a IUnknown e IClassFactory, tutti gli oggetti band devono implementare le interfacce seguenti.

Oltre a registrare il relativo identificatore di classe (CLSID), è necessario registrare anche gli oggetti barra e barra della scrivania per la categoria di componenti appropriata. La registrazione della categoria di componenti determina il tipo di oggetto e il relativo contenitore. Le bande degli strumenti usano una procedura di registrazione diversa e non hanno un identificatore di categoria (CATID). I CATID per i tre oggetti band che li richiedono sono:

Tipo banda Categoria del componente
Barra di esplorazione verticale CATID_InfoBand
Barra di Esplora orizzontale CATID_CommBand
Fascia scrivania CATID_DeskBand

 

Per altre informazioni su come registrare gli oggetti band, vedere Registrazione band.

Se l'oggetto band deve accettare l'input dell'utente, deve implementare anche IInputObject. Per aggiungere elementi al menu di scelta rapida per le bande di Explorer Bar o desk, l'oggetto band deve esportare IContextMenu. Le bande degli strumenti non supportano i menu di scelta rapida.

Poiché gli oggetti banda implementano una finestra figlio, devono implementare anche una routine finestra per gestire la messaggistica di Windows.

Gli oggetti Band possono inviare comandi al contenitore tramite l'interfaccia IOleCommandTarget del contenitore. Per ottenere il puntatore all'interfaccia, chiamare il metodo IInputObjectSite::QueryInterface del contenitore e richiedere IID_IOleCommandTarget. I comandi vengono quindi inviati al contenitore con IOleCommandTarget::Exec. Il gruppo di comandi è CGID_DeskBand. Quando viene chiamato il metodo IDeskBand::GetBandInfo di un oggetto band, il contenitore usa il parametro dwBandID per assegnare all'oggetto band un identificatore utilizzato per tre dei comandi. Sono supportati quattro ID comando IOleCommandTarget::Exec .

  • DBID_BANDINFOCHANGED

    Le informazioni della band sono cambiate. Impostare il parametro pvaIn sull'identificatore di banda ricevuto nella chiamata più recente a IDeskBand::GetBandInfo. Il contenitore chiamerà il metodo IDeskBand::GetBandInfo dell'oggetto band per richiedere le informazioni aggiornate.

  • DBID_MAXIMIZEBAND

    Ingrandire la banda. Impostare il parametro pvaIn sull'identificatore di banda ricevuto nella chiamata più recente a IDeskBand::GetBandInfo.

  • DBID_SHOWONLY

    Attivare o disattivare altre bande nel contenitore. Impostare il parametro pvaIn sul tipo VT_UNKNOWN con uno dei valori seguenti:

    Valore Descrizione
    Punk Puntatore all'interfaccia IUnknown dell'oggetto band. Tutte le altre bande di scrivania saranno nascoste.
    0 Nascondi tutte le bande della scrivania.
    1 Mostra tutte le bande della scrivania.

     

  • DBID_PUSHCHEVRON

    Versione 5. Visualizzare un menu freccia di espansione. Il contenitore invia un messaggio di RB_PUSHCHEVRON e l'oggetto band riceve una notifica RBN_CHEVRONPUSHED che richiede di visualizzare il menu freccia di espansione. Impostare il parametro nCmdExec del metodo IOleCommandTarget::Exec sull'identificatore di banda ricevuto nella chiamata più recente a IDeskBand::GetBandInfo. Impostare il parametro pvaIn del metodo IOleCommandTarget::Exec sul tipo VT_I4 con un valore definito dall'applicazione. Torna all'oggetto band come valore lAppValue della notifica di RBN_CHEVRONPUSHED.

Registrazione banda

Un oggetto band deve essere registrato come server ole in-process che supporta il threading apartment. Il valore predefinito per il server è una stringa di testo del menu. Per le barre di Explorer, verrà visualizzato nel sottomenu Barra di Explorer del menu Visualizza di Internet Explorer. Per le bande degli strumenti, verrà visualizzato nel sottomenu Barre degli strumenti del menu Visualizza di Internet Explorer. Per le fasce di scrivania, verrà visualizzato nel sottomenu Barre degli strumenti del menu di scelta rapida della barra delle applicazioni. Come per le risorse di menu, posizionare una e commerciale (&) davanti a una lettera causerà la sottolineatura e l'abilitazione dei tasti di scelta rapida. Ad esempio, la stringa di menu per la barra verticale explorer visualizzata nel primo grafico è "Sample &Vertical Explorer Bar".

Inizialmente, Internet Explorer recupera un'enumerazione degli oggetti barra di Explorer registrati dal Registro di sistema usando le categorie di componenti. Per migliorare le prestazioni, memorizza nella cache questa enumerazione, causando l'aggiunta successivamente di barre di Esplora risorse da ignorare. Per forzare Windows Internet Explorer a ricompilare la cache e riconoscere una nuova barra di Explorer, eliminare le chiavi del Registro di sistema seguenti durante la registrazione della nuova barra di Explorer:

HKEY_CURRENT_Uedizione Standard R\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000000046}\Enum

HKEY_CURRENT_Uedizione Standard R\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021494-0000-0000-C000-000000000000046}\Enum

Nota

Poiché viene creata una cache della barra di Explorer per ogni utente, l'applicazione di installazione potrebbe dover enumerare tutti gli hive del Registro di sistema utente o aggiungere uno stub per utente da eseguire al primo accesso dell'utente.

 

In generale, la voce del Registro di sistema di base per un oggetto band verrà visualizzata come segue.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         (Default) = Menu Text String
         InProcServer32
            (Default) = DLL Path Name
            ThreadingModel = Apartment

Le bande degli strumenti devono inoltre avere il CLSID dell'oggetto registrato con Internet Explorer. A tale scopo, assegnare un valore in HKEY_LOCAL_MACHINE\Barra degli strumenti di\Microsoft\Internet Explorer\denominata con il GUID CLSID dell'oggetto banda degli strumenti, come illustrato di seguito. Il valore dei dati viene ignorato, quindi il tipo di valore non è importante.

HKEY_LOCAL_MACHINE
   Software
      Microsoft
         Internet Explorer
            Toolbar
               {Your Band Object's CLSID GUID}

Sono disponibili diversi valori facoltativi che possono essere aggiunti anche al Registro di sistema. Ad esempio, il valore seguente è necessario se si desidera utilizzare la barra di Explorer per visualizzare HTML Il valore visualizzato non è un esempio, ma il valore effettivo che deve essere usato.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         Instance
            CLSID
               (Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}

Usato insieme al valore illustrato in precedenza, è necessario anche il valore facoltativo seguente se si desidera utilizzare la barra di Explorer per visualizzare HTML. Questo valore deve essere impostato sul percorso del file che contiene il contenuto HTML per la barra di Explorer.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         Instance
            InitPropertyBag
               Url

Un altro valore facoltativo definisce la larghezza o l'altezza predefinita della barra di Explorer, a seconda che sia verticale o orizzontale.

HKEY_CURRENT_USER
   Software
      Microsoft
         Internet Explorer
            Explorer Bars
               {Your Band Object's CLSID GUID}
                  BarSize

Il valore BarSize deve essere impostato sulla larghezza o sull'altezza della barra. Il valore richiede otto byte e viene inserito nel Registro di sistema come valore binario. I primi quattro byte specificano le dimensioni in pixel, in formato esadecimale, a partire dal byte più a sinistra. Gli ultimi quattro byte sono riservati e devono essere impostati su zero.

Ad esempio, le voci complete del Registro di sistema per una barra di Esplora risorse con supporto HTML con una larghezza predefinita di 291 (0x123) pixel sono mostrate qui.

HKEY_CLASSES_ROOT
   CLSID
      {Your Band Object's CLSID GUID}
         (Default) = Menu Text String
         InProcServer32
            (Default) = DLL Path Name
            ThreadingModel = Apartment
         Instance
            CLSID
               (Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}
            InitPropertyBag
               Url = Your HTML File
HKEY_CURRENT_USER
   Software
      Microsoft
         Internet Explorer
            Explorer Bars
               {Your Band Object's CLSID GUID}
                  BarSize = 23 01 00 00 00 00 00 00

È possibile gestire la registrazione del CATID di un oggetto band a livello di codice. Creare un oggetto manager delle categorie di componenti (CLSID_StdComponentCategoriesMgr) e richiedere un puntatore alla relativa interfaccia ICatRegister. Passare il CLSID e CATID dell'oggetto band a ICatRegister::RegisterClassImplCategories.

Esempio semplice di una barra di Esplora risorse personalizzata

In questo esempio viene illustrata l'implementazione della barra di esplorazione verticale di esempio illustrata nell'introduzione.

La procedura di base per la creazione di una barra di Explorer personalizzata è la seguente.

  1. Implementare le funzioni necessarie per la DLL.
  2. Implementare le interfacce COM necessarie.
  3. Implementare le interfacce COM facoltative desiderate.
  4. Registrare il CLSID dell'oggetto e, se necessario, categoria di componenti.
  5. Creare una finestra figlio di Internet Explorer, ridimensionata in base all'area di visualizzazione della barra di Explorer.
  6. Usare la finestra figlio per visualizzare le informazioni e interagire con l'utente.

L'implementazione molto semplice usata nell'esempio Explorer Bar può effettivamente essere usata per un tipo di barra explorer o una barra da tavolo, semplicemente registrandola per la categoria di componenti appropriata. Le implementazioni più sofisticate dovranno essere personalizzate per l'area di visualizzazione e il contenitore di ogni tipo di oggetto. Tuttavia, gran parte di questa personalizzazione può essere eseguita prendendo il codice di esempio ed estendendolo applicando tecniche di programmazione Windows familiari alla finestra figlio. Ad esempio, è possibile aggiungere controlli per l'interazione dell'utente o grafica per una visualizzazione più completa.

Funzioni DLL

Tutti e tre gli oggetti vengono inseriti in un pacchetto in una singola DLL, che espone le funzioni seguenti.

Le prime tre funzioni sono implementazioni standard e non verranno discusse qui. Anche l'implementazione di Class Factory è standard.

Implementazioni dell'interfaccia necessarie

L'esempio verticale Explorer Bar implementa le quattro interfacce necessarie: IUnknown, IObjectWithSite, IPersistStream e IDeskBand come parte della classe CExplorerBar. Le implementazioni del costruttore, del distruttore e IUnknown sono semplici e non verranno descritte qui. Vedere il codice di esempio per i dettagli.

Le interfacce seguenti sono descritte in dettaglio.

IObjectWithSite

Quando l'utente seleziona una barra di Explorer, il contenitore chiama il metodo IObjectWithSite::SetSite dell'oggetto band corrispondente. Il parametro punkSite verrà impostato sul puntatore IUnknown del sito.

In generale, un'implementazione di SetSite deve eseguire i passaggi seguenti:

  1. Rilasciare qualsiasi puntatore del sito attualmente in corso.
  2. Se il puntatore passato a SetSite è impostato su NULL, la banda verrà rimossa. SetSite può restituire S_OK.
  3. Se il puntatore passato a SetSite non è NULL, verrà impostato un nuovo sito. SetSite deve eseguire le operazioni seguenti:
    1. Chiamare QueryInterface nel sito per l'interfaccia IOleWindow.
    2. Chiama IOleWindow::GetWindow per ottenere l'handle della finestra padre. Salvare l'handle per usarlo in un secondo momento. Rilasciare IOleWindow se non è più necessario.
    3. Creare la finestra dell'oggetto band come elemento figlio della finestra ottenuta nel passaggio precedente. Non crearlo come finestra visibile.
    4. Se l'oggetto band implementa IInputObject, chiamare QueryInterface nel sito per l'interfaccia IInputObjectSite. Archiviare il puntatore a questa interfaccia per usarlo in un secondo momento.
    5. Se tutti i passaggi hanno esito positivo, restituire S_OK. In caso contrario, restituire il codice di errore definito da OLE che indica cosa non è riuscito.

L'esempio di barra di Explorer implementa SetSite nel modo seguente. Nel codice seguente m_pSite è una variabile membro privato che contiene il puntatore IInputObjectSite e m_hwndParent contiene l'handle della finestra padre. In questo esempio viene gestita anche la creazione della finestra. Se la finestra non esiste, questo metodo crea la finestra della barra di Explorer come elemento figlio di dimensioni appropriate della finestra padre ottenuta da SetSite. L'handle della finestra figlio viene archiviato in m_hwnd.

STDMETHODIMP CDeskBand::SetSite(IUnknown *pUnkSite)
{
    HRESULT hr = S_OK;

    m_hwndParent = NULL;

    if (m_pSite)
    {
        m_pSite->Release();
    }

    if (pUnkSite)
    {
        IOleWindow *pow;
        hr = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&pow));
        if (SUCCEEDED(hr))
        {
            hr = pow->GetWindow(&m_hwndParent);
            if (SUCCEEDED(hr))
            {
                WNDCLASSW wc = { 0 };
                wc.style         = CS_HREDRAW | CS_VREDRAW;
                wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
                wc.hInstance     = g_hInst;
                wc.lpfnWndProc   = WndProc;
                wc.lpszClassName = g_szDeskBandSampleClass;
                wc.hbrBackground = CreateSolidBrush(RGB(255, 255, 0));

                RegisterClassW(&wc);

                CreateWindowExW(0,
                                g_szDeskBandSampleClass,
                                NULL,
                                WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
                                0,
                                0,
                                0,
                                0,
                                m_hwndParent,
                                NULL,
                                g_hInst,
                                this);

                if (!m_hwnd)
                {
                    hr = E_FAIL;
                }
            }

            pow->Release();
        }

        hr = pUnkSite->QueryInterface(IID_IInputObjectSite, reinterpret_cast<void **>(&m_pSite));
    }

    return hr;
}

L'implementazione GetSite dell'esempio esegue semplicemente il wrapping di una chiamata al metodo QueryInterface del sito, usando il puntatore del sito salvato da SetSite.

STDMETHODIMP CDeskBand::GetSite(REFIID riid, void **ppv)
{
    HRESULT hr = E_FAIL;

    if (m_pSite)
    {
        hr =  m_pSite->QueryInterface(riid, ppv);
    }
    else
    {
        *ppv = NULL;
    }

    return hr;
}

Ipersiststream

Internet Explorer chiamerà l'interfaccia IPersistStream della barra di Explorer per consentire alla barra di Explorer di caricare o salvare dati persistenti. Se non sono presenti dati persistenti, i metodi devono comunque restituire un codice di operazione riuscita. L'interfaccia IPersistStream eredita da IPersist, quindi è necessario implementare cinque metodi.

L'esempio di barra di Explorer non usa dati persistenti e ha solo un'implementazione minima di IPersistStream. IPersist::GetClassID restituisce il CLSID (CLSID_SampleExplorerBar) dell'oggetto e il resto restituisce S_OK, S_FALedizione Standard o E_NOTIMPL.

IDeskBand

L'interfaccia IDeskBand è specifica per gli oggetti band. Oltre a un metodo, eredita da IDockingWindow, che a sua volta eredita da IOleWindow.

Esistono due metodi IOleWindow: GetWindow e IOleWindow::ContextSensitiveHelp. L'implementazione dell'esempio della barra di Explorer di GetWindow restituisce l'handle della finestra figlio della barra di Explorer, m_hwnd. La Guida sensibile al contesto non viene implementata, quindi ContextSensitiveHelp restituisce E_NOTIMPL.

L'interfaccia IDockingWindow ha tre metodi.

Il metodo ResizeBorderDW non viene utilizzato con alcun tipo di oggetto band e deve restituire sempre E_NOTIMPL. Il metodo ShowDW mostra o nasconde la finestra della barra di Explorer, a seconda del valore del relativo parametro.

STDMETHODIMP CDeskBand::ShowDW(BOOL fShow)
{
    if (m_hwnd)
    {
        ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
    }

    return S_OK;
}

Il metodo CloseDW elimina definitivamente la finestra della barra di Explorer.

STDMETHODIMP CDeskBand::CloseDW(DWORD)
{
    if (m_hwnd)
    {
        ShowWindow(m_hwnd, SW_HIDE);
        DestroyWindow(m_hwnd);
        m_hwnd = NULL;
    }

    return S_OK;
}

Il metodo rimanente, GetBandInfo, è specifico di IDeskBand. Internet Explorer lo usa per specificare l'identificatore e la modalità di visualizzazione della barra di Explorer. Internet Explorer può anche richiedere una o più informazioni dalla barra di Explorer compilando il membro dwMask della struttura DESKBANDINFO passata come terzo parametro. GetBandInfo deve archiviare l'identificatore e la modalità di visualizzazione e riempire la struttura DESKBANDINFO con i dati richiesti. L'esempio di barra di Explorer implementa GetBandInfo come illustrato nell'esempio di codice seguente.

STDMETHODIMP CDeskBand::GetBandInfo(DWORD dwBandID, DWORD, DESKBANDINFO *pdbi)
{
    HRESULT hr = E_INVALIDARG;

    if (pdbi)
    {
        m_dwBandID = dwBandID;

        if (pdbi->dwMask & DBIM_MINSIZE)
        {
            pdbi->ptMinSize.x = 200;
            pdbi->ptMinSize.y = 30;
        }

        if (pdbi->dwMask & DBIM_MAXSIZE)
        {
            pdbi->ptMaxSize.y = -1;
        }

        if (pdbi->dwMask & DBIM_INTEGRAL)
        {
            pdbi->ptIntegral.y = 1;
        }

        if (pdbi->dwMask & DBIM_ACTUAL)
        {
            pdbi->ptActual.x = 200;
            pdbi->ptActual.y = 30;
        }

        if (pdbi->dwMask & DBIM_TITLE)
        {
            // Don't show title by removing this flag.
            pdbi->dwMask &= ~DBIM_TITLE;
        }

        if (pdbi->dwMask & DBIM_MODEFLAGS)
        {
            pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT;
        }

        if (pdbi->dwMask & DBIM_BKCOLOR)
        {
            // Use the default background color by removing this flag.
            pdbi->dwMask &= ~DBIM_BKCOLOR;
        }

        hr = S_OK;
    }

    return hr;
}

Implementazioni dell'interfaccia facoltative

Esistono due interfacce che non sono necessarie, ma che possono essere utili per implementare: IInputObject e IContextMenu. L'esempio di barra di Explorer implementa IInputObject. Per informazioni su come implementare IContextMenu, vedere la documentazione.

IInputObject

L'interfaccia IInputObject deve essere implementata se un oggetto band accetta l'input dell'utente. Internet Explorer implementa IInputObjectSite e usa IInputObject per mantenere lo stato attivo dell'input utente appropriato quando ha più di una finestra contenuta. Esistono tre metodi che devono essere implementati da una barra di Explorer.

Internet Explorer chiama UIActivateIO per informare la barra di Explorer che è in corso di attivazione o disattivazione. Quando attivato, l'esempio di barra di Explorer chiama SetFocus per impostare lo stato attivo sulla finestra.

Internet Explorer chiama HasFocusIO quando tenta di determinare quale finestra ha lo stato attivo. Se la finestra della barra di Explorer o uno dei relativi discendenti ha lo stato attivo, HasFocusIO dovrebbe restituire S_OK. In caso contrario, deve restituire S_FALedizione Standard.

TranslateAcceleratorIO consente all'oggetto di elaborare gli acceleratori da tastiera. L'esempio di barra di Explorer non implementa questo metodo, pertanto restituisce S_FALedizione Standard.

L'implementazione della barra di esempio di IInputObjectSite è la seguente.

STDMETHODIMP CDeskBand::UIActivateIO(BOOL fActivate, MSG *)
{
    if (fActivate)
    {
        SetFocus(m_hwnd);
    }

    return S_OK;
}

STDMETHODIMP CDeskBand::HasFocusIO()
{
    return m_fHasFocus ? S_OK : S_FALSE;
}

STDMETHODIMP CDeskBand::TranslateAcceleratorIO(MSG *)
{
    return S_FALSE;
};

Registrazione CLSID

Come per tutti gli oggetti COM, il CLSID della barra di Explorer deve essere registrato. Affinché l'oggetto funzioni correttamente con Internet Explorer, deve anche essere registrato per la categoria di componenti appropriata (CATID_InfoBand). La sezione relativa al codice per la barra di Explorer è illustrata nell'esempio di codice seguente.

HRESULT RegisterServer()
{
    WCHAR szCLSID[MAX_PATH];
    StringFromGUID2(CLSID_DeskBandSample, szCLSID, ARRAYSIZE(szCLSID));

    WCHAR szSubkey[MAX_PATH];
    HKEY hKey;

    HRESULT hr = StringCchPrintfW(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
    if (SUCCEEDED(hr))
    {
        hr = E_FAIL;
        if (ERROR_SUCCESS == RegCreateKeyExW(HKEY_CLASSES_ROOT,
                                             szSubkey,
                                             0,
                                             NULL,
                                             REG_OPTION_NON_VOLATILE,
                                             KEY_WRITE,
                                             NULL,
                                             &hKey,
                                             NULL))
        {
            WCHAR const szName[] = L"DeskBand Sample";
            if (ERROR_SUCCESS == RegSetValueExW(hKey,
                                                NULL,
                                                0,
                                                REG_SZ,
                                                (LPBYTE) szName,
                                                sizeof(szName)))
            {
                hr = S_OK;
            }

            RegCloseKey(hKey);
        }
    }

    if (SUCCEEDED(hr))
    {
        hr = StringCchPrintfW(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s\\InprocServer32", szCLSID);
        if (SUCCEEDED(hr))
        {
            hr = HRESULT_FROM_WIN32(RegCreateKeyExW(HKEY_CLASSES_ROOT, szSubkey,
                 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
            if (SUCCEEDED(hr))
            {
                WCHAR szModule[MAX_PATH];
                if (GetModuleFileNameW(g_hInst, szModule, ARRAYSIZE(szModule)))
                {
                    DWORD cch = lstrlen(szModule);
                    hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, NULL, 0, REG_SZ, (LPBYTE) szModule, cch * sizeof(szModule[0])));
                }

                if (SUCCEEDED(hr))
                {
                    WCHAR const szModel[] = L"Apartment";
                    hr = HRESULT_FROM_WIN32(RegSetValueExW(hKey, L"ThreadingModel", 0,  REG_SZ, (LPBYTE) szModel, sizeof(szModel)));
                }

                RegCloseKey(hKey);
            }
        }
    }

    return hr;
}

La registrazione di oggetti band nell'esempio usa le normali procedure COM.

Oltre a CLSID, è necessario registrare anche il server oggetti banda per una o più categorie di componenti. Questa è in realtà la differenza principale nell'implementazione tra gli esempi di barre di Explorer verticale e orizzontale. Questo processo viene gestito creando un oggetto manager delle categorie di componenti (CLSID_StdComponentCategoriesMgr) e usando il metodo ICatRegister::RegisterClassImplCategories per registrare il server oggetti band. In questo esempio, la registrazione delle categorie di componenti viene gestita passando il CLSID e CATID dell'esempio Explorer Bar a una funzione privata, RegisterComCat, come illustrato nell'esempio di codice seguente.

HRESULT RegisterComCat()
{
    ICatRegister *pcr;
    HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pcr));
    if (SUCCEEDED(hr))
    {
        CATID catid = CATID_DeskBand;
        hr = pcr->RegisterClassImplCategories(CLSID_DeskBandSample, 1, &catid);
        pcr->Release();
    }
    return hr;
}

Procedura finestra

Poiché un oggetto band usa una finestra figlio per la relativa visualizzazione, deve implementare una routine finestra per gestire la messaggistica di Windows. L'esempio di banda ha funzionalità minime, quindi la relativa routine finestra gestisce solo cinque messaggi:

La procedura può essere facilmente espansa per contenere messaggi aggiuntivi per supportare altre funzionalità.

LRESULT CALLBACK CDeskBand::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = 0;

    CDeskBand *pDeskBand = reinterpret_cast<CDeskBand *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));

    switch (uMsg)
    {
    case WM_CREATE:
        pDeskBand = reinterpret_cast<CDeskBand *>(reinterpret_cast<CREATESTRUCT *>(lParam)->lpCreateParams);
        pDeskBand->m_hwnd = hwnd;
        SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pDeskBand));
        break;

    case WM_SETFOCUS:
        pDeskBand->OnFocus(TRUE);
        break;

    case WM_KILLFOCUS:
        pDeskBand->OnFocus(FALSE);
        break;

    case WM_PAINT:
        pDeskBand->OnPaint(NULL);
        break;

    case WM_PRINTCLIENT:
        pDeskBand->OnPaint(reinterpret_cast<HDC>(wParam));
        break;

    case WM_ERASEBKGND:
        if (pDeskBand->m_fCompositionEnabled)
        {
            lResult = 1;
        }
        break;
    }

    if (uMsg != WM_ERASEBKGND)
    {
        lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    return lResult;
}

Il gestore WM_COMMAND restituisce semplicemente zero. Il gestore WM_PAINT crea la visualizzazione testo semplice illustrata nell'esempio della barra di Explorer nell'introduzione.

void CDeskBand::OnPaint(const HDC hdcIn)
{
    HDC hdc = hdcIn;
    PAINTSTRUCT ps;
    static WCHAR szContent[] = L"DeskBand Sample";
    static WCHAR szContentGlass[] = L"DeskBand Sample (Glass)";

    if (!hdc)
    {
        hdc = BeginPaint(m_hwnd, &ps);
    }

    if (hdc)
    {
        RECT rc;
        GetClientRect(m_hwnd, &rc);

        SIZE size;

        if (m_fCompositionEnabled)
        {
            HTHEME hTheme = OpenThemeData(NULL, L"BUTTON");
            if (hTheme)
            {
                HDC hdcPaint = NULL;
                HPAINTBUFFER hBufferedPaint = BeginBufferedPaint(hdc, &rc, BPBF_TOPDOWNDIB, NULL, &hdcPaint);

                DrawThemeParentBackground(m_hwnd, hdcPaint, &rc);

                GetTextExtentPointW(hdc, szContentGlass, ARRAYSIZE(szContentGlass), &size);
                RECT rcText;
                rcText.left   = (RECTWIDTH(rc) - size.cx) / 2;
                rcText.top    = (RECTHEIGHT(rc) - size.cy) / 2;
                rcText.right  = rcText.left + size.cx;
                rcText.bottom = rcText.top + size.cy;

                DTTOPTS dttOpts = {sizeof(dttOpts)};
                dttOpts.dwFlags = DTT_COMPOSITED | DTT_TEXTCOLOR | DTT_GLOWSIZE;
                dttOpts.crText = RGB(255, 255, 0);
                dttOpts.iGlowSize = 10;
                DrawThemeTextEx(hTheme, hdcPaint, 0, 0, szContentGlass, -1, 0, &rcText, &dttOpts);

                EndBufferedPaint(hBufferedPaint, TRUE);

                CloseThemeData(hTheme);
            }
        }
        else
        {
            SetBkColor(hdc, RGB(255, 255, 0));
            GetTextExtentPointW(hdc, szContent, ARRAYSIZE(szContent), &size);
            TextOutW(hdc,
                     (RECTWIDTH(rc) - size.cx) / 2,
                     (RECTHEIGHT(rc) - size.cy) / 2,
                     szContent,
                     ARRAYSIZE(szContent));
        }
    }

    if (!hdcIn)
    {
        EndPaint(m_hwnd, &ps);
    }
}

I gestori WM_edizione Standard TFOCUS e WM_KILLFOCUS informano il sito di una modifica dello stato attivo chiamando il metodo IInputObjectSite::OnFocusChangeIS del sito.

void CDeskBand::OnFocus(const BOOL fFocus)
{
    m_fHasFocus = fFocus;

    if (m_pSite)
    {
        m_pSite->OnFocusChangeIS(static_cast<IOleWindow*>(this), m_fHasFocus);
    }
}

Gli oggetti band offrono un modo flessibile e potente per estendere le funzionalità di Internet Explorer creando barre di Explorer personalizzate. L'implementazione di una fascia di scrivania consente di estendere le funzionalità delle normali finestre. Anche se è necessaria una programmazione COM, in definitiva serve a fornire una finestra figlio per l'interfaccia utente. Da qui, la maggior parte dell'implementazione può usare tecniche di programmazione Windows familiari. Mentre l'esempio descritto qui ha solo funzionalità limitate, illustra tutte le caratteristiche necessarie di un oggetto band e può essere facilmente esteso per creare un'interfaccia utente unica e potente.