Partager via


Création de barres de Explorer personnalisées, de bandes d’outils et de bandes de bureau

La barre Explorer a été introduite avec Microsoft Internet Explorer 4.0 pour fournir une zone d’affichage adjacente au volet du navigateur. Il s’agit essentiellement d’une fenêtre enfant dans la fenêtre d’Explorer Windows Internet, qui peut être utilisée pour afficher des informations et interagir avec l’utilisateur de la même façon. Explorer Barres sont généralement affichées sous la forme d’un volet vertical sur le côté gauche du volet du navigateur. Toutefois, une barre Explorer peut également s’afficher horizontalement, sous le volet du navigateur.

Capture d’écran montrant les barres verticales et horizontales Explorer.

Il existe un large éventail d’utilisations possibles pour la barre Explorer. Les utilisateurs peuvent sélectionner l’option qu’ils souhaitent afficher de différentes façons, notamment en la sélectionnant dans le sous-menu Barre d’Explorer du menu Affichage ou en cliquant sur un bouton de barre d’outils. Internet Explorer fournit plusieurs barres de Explorer standard, y compris les favoris et la recherche.

L’une des façons de personnaliser les Explorer Internet consiste à ajouter une barre de Explorer personnalisée. Une fois implémenté et inscrit, il est ajouté au sous-menu Barre Explorer du menu Affichage. Lorsqu’elle est sélectionnée par l’utilisateur, la zone d’affichage de la barre d’Explorer peut ensuite être utilisée pour afficher des informations et prendre les entrées utilisateur de la même façon qu’une fenêtre normale.

capture d’écran des barres de l’explorateur

Pour créer un Explorer Bar personnalisé, vous devez implémenter et inscrire un objet de bande. Les objets de bande ont été introduits avec la version 4.71 de l’interpréteur de commandes et offrent des fonctionnalités similaires à celles des fenêtres normales. Toutefois, étant donné qu’il s’agit d’objets COM (Component Object Model) et contenus par internet Explorer ou l’interpréteur de commandes, ils sont implémentés quelque peu différemment. Des objets de bande simples ont été utilisés pour créer l’exemple Explorer barres affichées dans le premier graphique. L’implémentation de l’exemple de barre de Explorer verticale sera traitée en détail dans une section ultérieure.

Bandes d’outils

Une bande d’outils est un objet de bande introduit avec Microsoft Internet Explorer 5 pour prendre en charge la fonctionnalité de barre d’outils radio Windows. La barre d’outils Internet Explorer est en fait un contrôle de barre d’outils qui contient plusieurs contrôles de barre d’outils. En créant une bande d’outils, vous pouvez ajouter une bande à ce contrôle de barre d’barres. Toutefois, comme Explorer Barres, une bande d’outils est une fenêtre à usage général.

capture d’écran des bandes d’outils

Les utilisateurs affichent une barre d’outils en la sélectionnant dans le sous-menu Barres d’outils du menu Affichage ou dans le menu contextuel qui s’affiche en cliquant avec le bouton droit sur la zone de barre d’outils.

Bandes de bureau

Les objets band peuvent également être utilisés pour créer des bandes de bureau. Bien que leur implémentation de base soit similaire à Explorer Barres, les bandes de bureau ne sont pas liées aux Explorer Internet. Une bande de bureau est essentiellement un moyen de créer une fenêtre ancrée sur le bureau. L’utilisateur la sélectionne en cliquant avec le bouton droit sur la barre des tâches et en la sélectionnant dans le sous-menu Barres d’outils .

Capture d’écran montrant un exemple de bande de bureau.

Initialement, les bandes de bureau sont ancrées sur la barre des tâches.

Capture d’écran montrant les bandes de bureau ancrées dans la barre des tâches.

L’utilisateur peut ensuite faire glisser la bande de bureau vers le bureau, qui s’affiche comme une fenêtre normale.

capture d’écran des bandes de bureau

Implémentation d’objets de bande

Les sujets suivants sont abordés.

Concepts de base de l’objet band

Bien qu’ils puissent être utilisés comme des fenêtres normales, les objets de bande sont des objets COM qui existent dans un conteneur. Explorer barres sont contenues dans les Explorer Internet, et les bandes de bureau sont contenues dans l’interpréteur de commandes. Bien qu’ils remplissent des fonctions différentes, leur implémentation de base est très similaire. La principale différence réside dans la façon dont l’objet de bande est inscrit, qui à son tour contrôle le type de l’objet et son conteneur. Cette section décrit les aspects de l’implémentation qui sont communs à tous les objets de bande. Pour plus d’informations sur l’implémentation, consultez Exemple simple de barre d’Explorer personnalisée.

Outre IUnknown et IClassFactory, tous les objets de bande doivent implémenter les interfaces suivantes.

En plus d’inscrire leur identificateur de classe (CLSID), les objets barre Explorer et bande de bureau doivent également être inscrits pour la catégorie de composant appropriée. L’inscription de la catégorie de composant détermine le type d’objet et son conteneur. Les bandes d’outils utilisent une procédure d’inscription différente et n’ont pas d’identificateur de catégorie (CATID). Les CATID pour les trois objets de bande qui en ont besoin sont les suivants :

Type de bande Catégorie de composant
Barre de Explorer verticale CATID_InfoBand
Barre de Explorer horizontale CATID_CommBand
Desk Band CATID_DeskBand

 

Pour plus d’informations sur l’inscription d’objets de bande, consultez Inscription de bande.

Si l’objet band doit accepter l’entrée utilisateur, il doit également implémenter IInputObject. Pour ajouter des éléments au menu contextuel de Explorer barres ou de bandes de bureau, l’objet band doit exporter IContextMenu. Les bandes d’outils ne prennent pas en charge les menus contextuels.

Étant donné que les objets de bande implémentent une fenêtre enfant, ils doivent également implémenter une procédure de fenêtre pour gérer la messagerie Windows.

Les objets band peuvent envoyer des commandes à leur conteneur via l’interface IOleCommandTarget du conteneur. Pour obtenir le pointeur d’interface, appelez la méthode IInputObjectSite::QueryInterface du conteneur et demandez IID_IOleCommandTarget. Vous envoyez ensuite des commandes au conteneur avec IOleCommandTarget::Exec. Le groupe de commandes est CGID_DeskBand. Quand la méthode IDeskBand::GetBandInfo d’un objet de bande est appelée, le conteneur utilise le paramètre dwBandID pour affecter à l’objet de bande un identificateur qui est utilisé pour trois commandes. Quatre ID de commande IOleCommandTarget::Exec sont pris en charge.

  • DBID_BANDINFOCHANGED

    Les informations du groupe ont changé. Définissez le paramètre pvaIn sur l’identificateur de bande qui a été reçu lors de l’appel le plus récent à IDeskBand::GetBandInfo. Le conteneur appelle la méthode IDeskBand::GetBandInfo de l’objet band pour demander les informations mises à jour.

  • DBID_MAXIMIZEBAND

    Agrandissez le groupe. Définissez le paramètre pvaIn sur l’identificateur de bande qui a été reçu lors de l’appel le plus récent à IDeskBand::GetBandInfo.

  • DBID_SHOWONLY

    Activez ou désactivez les autres bandes dans le conteneur. Définissez le paramètre pvaIn sur le type VT_UNKNOWN avec l’une des valeurs suivantes :

    Valeur Description
    Punk Pointeur vers l’interface IUnknown de l’objet band. Tous les autres groupes de bureau seront masqués.
    0 Masquez tous les groupes de bureau.
    1 Afficher tous les groupes de bureau.

     

  • DBID_PUSHCHEVRON

    Version 5. Afficher un menu chevron. Le conteneur envoie un message RB_PUSHCHEVRON et l’objet band reçoit une notification RBN_CHEVRONPUSHED qui l’invite à afficher le menu chevron. Définissez le paramètre nCmdExecOpt de la méthode IOleCommandTarget::Exec sur l’identificateur de bande reçu lors de l’appel le plus récent à IDeskBand::GetBandInfo. Définissez le paramètre pvaIn de la méthode IOleCommandTarget::Exec sur le type VT_I4 avec une valeur définie par l’application. Elle revient à l’objet band en tant que valeur lAppValue de la notification RBN_CHEVRONPUSHED.

Enregistrement de bande

Un objet de bande doit être inscrit en tant que serveur ole in-process qui prend en charge le thread d’appartement. La valeur par défaut du serveur est une chaîne de texte de menu. Pour Explorer barres, elle s’affiche dans le sous-menu Barre Explorer du menu Affichage Explorer Internet. Pour les bandes d’outils, elle s’affiche dans le sous-menu Barres d’outils du menu Affichage Explorer Internet. Pour les bandes de bureau, elle s’affiche dans le sous-menu Barres d’outils du menu contextuel de la barre des tâches. Comme avec les ressources de menu, placer une esperluette (&) devant une lettre entraîne son soulignement et active les raccourcis clavier. Par exemple, la chaîne de menu de la barre de Explorer verticale affichée dans le premier graphique est « Sample &Vertical Explorer Bar ».

Initialement, Internet Explorer récupère une énumération des objets Bar Explorer inscrits à partir du Registre à l’aide des catégories de composants. Pour améliorer les performances, il met ensuite en cache cette énumération, ce qui entraîne l’ajout de barres Explorer par la suite à l’oubli. Pour forcer windows Internet Explorer à reconstruire le cache et à reconnaître une nouvelle barre Explorer, supprimez les clés de Registre suivantes lors de l’inscription de la nouvelle barre Explorer :

HKEY_CURRENT_USER\Logiciel\Microsoft\Windows\Currentversion\\ Explorer Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-00000000046}\Enum

HKEY_CURRENT_USER\Logiciel\Microsoft\Windows\Currentversion\\ Explorer Discardable\PostSetup\Component Categories\{00021494-0000-0000-C000-000000000046}\Enum

Notes

Étant donné qu’un cache de barre d’Explorer est créé pour chaque utilisateur, votre application d’installation peut avoir besoin d’énumérer toutes les ruches du registre utilisateur ou d’ajouter un stub par utilisateur à exécuter lorsque l’utilisateur se connecte pour la première fois.

 

En général, l’entrée de registre de base pour un objet band s’affiche comme suit.

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

Les bandes d’outils doivent également avoir le CLSID de leur objet inscrit auprès d’Internet Explorer. Pour ce faire, affectez une valeur sous HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Toolbar nommée avec le GUID CLSID de l’objet de bande d’outils, comme indiqué ici. Sa valeur de données est ignorée, de sorte que le type de valeur n’est pas important.

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

Plusieurs valeurs facultatives peuvent également être ajoutées au Registre. Pour instance, la valeur suivante est nécessaire si vous souhaitez utiliser la barre d’Explorer pour afficher du code HTML La valeur affichée n’est pas un exemple, mais la valeur réelle qui doit être utilisée.

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

Utilisée conjointement avec la valeur indiquée ci-dessus, la valeur facultative suivante est également nécessaire si vous souhaitez utiliser la barre d’Explorer pour afficher du code HTML. Cette valeur doit être définie sur l’emplacement du fichier qui contient le contenu HTML de la barre Explorer.

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

Une autre valeur facultative définit la largeur ou la hauteur par défaut de la barre Explorer, selon qu’elle est verticale ou horizontale, respectivement.

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

La valeur BarSize doit être définie sur la largeur ou la hauteur de la barre. La valeur nécessite huit octets et est placée dans le Registre en tant que valeur binaire. Les quatre premiers octets spécifient la taille en pixels, au format hexadécimal, en commençant par l’octet le plus à gauche. Les quatre derniers octets sont réservés et doivent être définis sur zéro.

Par exemple, les entrées de Registre complètes d’une barre Explorer html avec une largeur par défaut de 291 pixels (0x123) sont affichées ici.

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

Vous pouvez gérer l’inscription du CATID d’un objet de bande par programmation. Créez un objet de gestionnaire de catégories de composants (CLSID_StdComponentCategoriesMgr) et demandez un pointeur vers son interface ICatRegister . Passez le CLSID et le CATID de l’objet de bande à ICatRegister::RegisterClassImplCategories.

Exemple simple de barre de Explorer personnalisée

Cet exemple montre comment implémenter l’exemple de barre de Explorer verticale indiquée dans l’introduction.

La procédure de base pour créer une barre d’Explorer personnalisée est la suivante.

  1. Implémentez les fonctions nécessaires à la DLL.
  2. Implémentez les interfaces COM requises.
  3. Implémentez toutes les interfaces COM facultatives souhaitées.
  4. Inscrivez le CLSID de l’objet et, si nécessaire, la catégorie de composant.
  5. Créez une fenêtre enfant de Explorer Internet, dimensionnée pour s’adapter à la zone d’affichage de la barre de Explorer.
  6. Utilisez la fenêtre enfant pour afficher des informations et interagir avec l’utilisateur.

L’implémentation très simple utilisée dans l’exemple Explorer Bar peut en fait être utilisée pour un type de barre d’Explorer ou une bande de bureau, en l’inscrivant simplement pour la catégorie de composant appropriée. Des implémentations plus sophistiquées devront être personnalisées pour la région d’affichage et le conteneur de chaque type d’objet. Toutefois, une grande partie de cette personnalisation peut être effectuée en prenant l’exemple de code et en l’étendant en appliquant des techniques de programmation Windows familières à la fenêtre enfant. Par exemple, vous pouvez ajouter des contrôles pour l’interaction utilisateur ou des graphiques pour un affichage plus riche.

Fonctions DLL

Les trois objets sont empaquetés dans une seule DLL, qui expose les fonctions suivantes.

Les trois premières fonctions sont des implémentations standard et ne seront pas abordées ici. L’implémentation de La fabrique de classes est également standard.

Implémentations d’interface requises

L’exemple de barre d’Explorer verticale implémente les quatre interfaces requises : IUnknown, IObjectWithSite, IPersistStream et IDeskBand dans le cadre de la classe CExplorerBar. Les implémentations du constructeur, du destructeur et de IUnknown sont simples et ne seront pas abordées ici. Consultez l'exemple de code pour plus d'informations.

Les interfaces suivantes sont décrites en détail.

IObjectWithSite

Lorsque l’utilisateur sélectionne un Explorer Bar, le conteneur appelle la méthode IObjectWithSite::SetSite de l’objet de bande correspondant. Le paramètre punkSite est défini sur le pointeur IUnknown du site.

En général, une implémentation SetSite doit effectuer les étapes suivantes :

  1. Libérez tout pointeur de site en cours de détention.
  2. Si le pointeur transmis à SetSite est défini sur NULL, la bande est supprimée. SetSite peut retourner S_OK.
  3. Si le pointeur transmis à SetSite n’est pas NULL, un nouveau site est défini. SetSite doit effectuer les opérations suivantes :
    1. Appelez QueryInterface sur le site pour son interface IOleWindow .
    2. Appelez IOleWindow::GetWindow pour obtenir le handle de la fenêtre parente. Enregistrez le handle pour une utilisation ultérieure. Relâchez IOleWindow s’il n’est plus nécessaire.
    3. Créez la fenêtre de l’objet bande en tant qu’enfant de la fenêtre obtenue à l’étape précédente. Ne la créez pas en tant que fenêtre visible.
    4. Si l’objet band implémente IInputObject, appelez QueryInterface sur le site pour son interface IInputObjectSite . Stockez le pointeur vers cette interface pour une utilisation ultérieure.
    5. Si toutes les étapes réussissent, retournez S_OK. Si ce n’est pas le cas, retournez le code d’erreur défini par OLE indiquant ce qui a échoué.

L’exemple Explorer Bar implémente SetSite de la manière suivante. Dans le code suivant , m_pSite est une variable membre privée qui contient le pointeur IInputObjectSite et m_hwndParent contient le handle de la fenêtre parente. Dans cet exemple, la création de fenêtres est également gérée. Si la fenêtre n’existe pas, cette méthode crée la fenêtre de la barre d’Explorer en tant qu’enfant de taille appropriée de la fenêtre parente obtenue par SetSite. Le handle de la fenêtre enfant est stocké dans 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’implémentation GetSite de l’exemple encapsule simplement un appel à la méthode QueryInterface du site, à l’aide du pointeur de site enregistré par 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

Les Explorer Internet appellent l’interface IPersistStream de la barre d’Explorer pour permettre à la barre d’Explorer de charger ou d’enregistrer des données persistantes. S’il n’y a pas de données persistantes, les méthodes doivent toujours retourner un code de réussite. L’interface IPersistStream hérite d’IPersist. Cinq méthodes doivent donc être implémentées.

L’exemple Explorer Bar n’utilise pas de données persistantes et n’a qu’une implémentation minimale d’IPersistStream. IPersist::GetClassID renvoie le CLSID (CLSID_SampleExplorerBar) de l’objet, et le reste retourne S_OK, S_FALSE ou E_NOTIMPL.

IDeskBand

L’interface IDeskBand est spécifique aux objets de bande. En plus de sa méthode unique, il hérite d’IDockingWindow, qui à son tour hérite de IOleWindow.

Il existe deux méthodes IOleWindow : GetWindow et IOleWindow::ContextSensitiveHelp. L’implémentation de l’exemple de barre de Explorer de GetWindow retourne la poignée de fenêtre enfant de la barre d’Explorer, m_hwnd. L’aide contextuelle n’étant pas implémentée, ContextSensitiveHelp retourne E_NOTIMPL.

L’interface IDockingWindow a trois méthodes.

La méthode ResizeBorderDW n’est utilisée avec aucun type d’objet de bande et doit toujours retourner E_NOTIMPL. La méthode ShowDW affiche ou masque la fenêtre de la barre d’Explorer, en fonction de la valeur de son paramètre.

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

    return S_OK;
}

La méthode CloseDW détruit la fenêtre de la barre d’Explorer.

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

    return S_OK;
}

La méthode restante, GetBandInfo, est spécifique à IDeskBand. Internet Explorer l’utilise pour spécifier l’identificateur et le mode d’affichage de la barre d’Explorer. Les Explorer Internet peuvent également demander une ou plusieurs informations à partir de la barre de Explorer en remplissant le membre dwMask de la structure DESKBANDINFO qui est passé comme troisième paramètre. GetBandInfo doit stocker l’identificateur et le mode d’affichage et remplir la structure DESKBANDINFO avec les données demandées. L’exemple Explorer Bar implémente GetBandInfo comme indiqué dans l’exemple de code suivant.

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

Implémentations d’interface facultatives

Il existe deux interfaces qui ne sont pas obligatoires, mais qui peuvent être utiles à implémenter : IInputObject et IContextMenu. L’exemple Explorer Bar implémente IInputObject. Reportez-vous à la documentation pour plus d’informations sur l’implémentation d’IContextMenu.

IInputObject

L’interface IInputObject doit être implémentée si un objet de bande accepte une entrée utilisateur. Internet Explorer implémente IInputObjectSite et utilise IInputObject pour maintenir le focus d’entrée utilisateur approprié lorsqu’il a plusieurs fenêtres contenues. Trois méthodes doivent être implémentées par un Explorer Bar.

Internet Explorer appelle UIActivateIO pour informer la barre d’Explorer qu’elle est activée ou désactivée. Lorsqu’il est activé, l’exemple de barre de Explorer appelle SetFocus pour définir le focus sur sa fenêtre.

Internet Explorer appelle HasFocusIO lorsqu’il tente de déterminer quelle fenêtre a le focus. Si la fenêtre de la barre d’Explorer ou l’un de ses descendants a le focus, HasFocusIO doit retourner S_OK. Si ce n’est pas le cas, elle doit retourner S_FALSE.

TranslateAcceleratorIO permet à l’objet de traiter les raccourcis clavier. L’exemple Explorer Bar n’implémente pas cette méthode, il retourne donc S_FALSE.

L’implémentation d’IInputObjectSite dans la barre d’exemples est la suivante.

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

Inscription CLSID

Comme pour tous les objets COM, le CLSID de la barre d’Explorer doit être inscrit. Pour que l’objet fonctionne correctement avec Internet Explorer, il doit également être inscrit pour la catégorie de composant appropriée (CATID_InfoBand). La section de code appropriée pour la barre d’Explorer est illustrée dans l’exemple de code suivant.

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

L’inscription d’objets de bande dans l’exemple utilise des procédures COM normales.

En plus du CLSID, le serveur d’objets de bande doit également être inscrit pour une ou plusieurs catégories de composants. Il s’agit en fait de la main différence d’implémentation entre les exemples de barres Explorer verticales et horizontales. Ce processus est géré en créant un objet de gestionnaire de catégories de composants (CLSID_StdComponentCategoriesMgr) et en utilisant la méthode ICatRegister::RegisterClassImplCategories pour inscrire le serveur d’objets de bande. Dans cet exemple, l’inscription de catégorie de composant est gérée en passant le CLSID et le CATID de l’exemple de barre d’Explorer à une fonction privée, RegisterComCat, comme indiqué dans l’exemple de code suivant.

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

Procédure de la fenêtre

Étant donné qu’un objet de bande utilise une fenêtre enfant pour son affichage, il doit implémenter une procédure de fenêtre pour gérer la messagerie Windows. L’exemple de bande ayant des fonctionnalités minimales, sa procédure de fenêtre ne gère que cinq messages :

La procédure peut facilement être développée pour prendre en charge d’autres messages afin de prendre en charge davantage de fonctionnalités.

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

Le gestionnaire WM_COMMAND retourne simplement zéro. Le gestionnaire de WM_PAINT crée l’affichage de texte simple affiché dans l’exemple Explorer Bar de l’introduction.

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

Les gestionnaires WM_SETFOCUS et WM_KILLFOCUS informent le site d’un changement de focus en appelant la méthode IInputObjectSite::OnFocusChangeIS du site.

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

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

Les objets de bande offrent un moyen flexible et puissant d’étendre les fonctionnalités des Explorer Internet en créant des barres de Explorer personnalisées. L’implémentation d’une bande de bureau vous permet d’étendre les fonctionnalités des fenêtres normales. Bien qu’une certaine programmation COM soit requise, elle sert finalement à fournir une fenêtre enfant pour votre interface utilisateur. À partir de là, la majeure partie de l’implémentation peut utiliser des techniques de programmation Windows familières. Bien que l’exemple présenté ici n’ait que des fonctionnalités limitées, il illustre toutes les fonctionnalités nécessaires d’un objet de bande et il peut être facilement étendu pour créer une interface utilisateur unique et puissante.