Olvasás angol nyelven

Megosztás a következőn keresztül:


Egyéni böngészősávok, eszköztárak és asztalszalagok létrehozása

Az Explorer-sáv a Microsoft Internet Explorer 4.0-val lett bevezetve, hogy a böngészőpanel mellett egy megjelenítési területet biztosítson. Ez alapvetően egy gyermekablak a Windows Internet Explorer ablakán belül, és az információk megjelenítésére és a felhasználóval való interakcióra is használható. A böngészősávok leggyakrabban függőleges panelként jelennek meg a böngészőablak bal oldalán. Az Explorer-sávok azonban vízszintesen is megjeleníthetők a böngészőpanel alatt.

Függőleges és vízszintes Explorer-sávokat ábrázoló képernyőkép.

Az Explorer Bar számos lehetséges felhasználási lehetőséget kínál. A felhasználók többféleképpen is kiválaszthatják, hogy melyik beállítást szeretnék látni, például a Nézet menü Kezelősáv almenüjében, vagy az eszköztár gombra kattintva. Az Internet Explorer számos szabványos Explorer-sávot kínál, köztük a kedvenceket és a keresést.

Az Internet Explorer testreszabásának egyik módja egy egyéni Explorer-sáv hozzáadása. A megvalósítás és regisztráció után a Nézet menü Felfedező eszköztár almenüjébe lesz hozzáadva. Ha a felhasználó kiválasztja, az Explorer Bar megjelenítési területe az információk megjelenítésére és a felhasználói bevitelre ugyanúgy használható, mint egy normál ablak.

kezelősávok képernyőképe

Egyéni Explorer-sáv létrehozásához implementálnia kell és regisztrálnia kell egy sávobjektumot. A sávobjektumok a Shell 4.71-es verziójával lettek bevezetve, és a normál ablakokéhoz hasonló képességeket biztosítanak. Mivel azonban a komponensobjektum-modell (COM) objektumokat az Internet Explorer vagy a Shell tartalmazza, a rendszer némileg eltérő módon implementálja őket. Az első ábrán megjelenő minta Explorer-sávok létrehozásához egyszerű sávobjektumokat használtunk. A függőleges Explorer-sáv minta implementációját egy későbbi szakaszban tárgyaljuk részletesen.

Eszközsávok

A eszközsáv egy sávobjektum, amely a Microsoft Internet Explorer 5-ben lett bevezetve a Windows-eszköztár funkció támogatásához. Az Internet Explorer eszköztár valójában egy sávvezérlő, amely több eszköztár-vezérlőt tartalmaz. Eszközsáv létrehozásával sávot adhat hozzá az adott sávvezérlőhöz. Az Explorer Barshoz hasonlóan azonban az eszközsávok is egy általános célú ablak.

eszközsávok képernyőképe

A felhasználók az eszköztárat a Nézet menü Eszköztárak almenüjében vagy a jobb gombbal az eszköztárterületre kattintva megjelenő helyi menüből jeleníthetik meg.

Asztali sávok

A sávobjektumok asztali sávoklétrehozására is használhatók. Bár alapszintű implementációjuk hasonló az Explorer-sávokhoz, az asztali sávok nem kapcsolódnak az Internet Explorerhez. Az asztali sáv alapvetően egy dokkolható ablak létrehozásának módja az asztalon. A felhasználó úgy választja ki, hogy a jobb gombbal a tálcára kattint, és kiválasztja a Eszköztárak almenüből.

képernyőkép, amelyen egy asztali mintasáv látható.

Kezdetben az asztali sávok rögzítve vannak a tálcán.

Képernyőkép, amely a tálcán rögzített eszköztárakat mutatja.

A felhasználó ezután húzhatja az asztali sávot az asztalra, és normál ablakként jelenik meg.

képernyőkép az asztali sávokról

Sávobjektumok implementálása

Az alábbi témaköröket tárgyaljuk.

Sávobjektum alapjai

Bár a normál ablakokhoz hasonlóan használhatók, a sávobjektumok olyan COM-objektumok, amelyek egy tárolóban léteznek. Az Explorer-sávokat az Internet Explorer, az asztali sávokat pedig a Shell tartalmazza. Bár különböző funkciókat szolgálnak ki, alapszintű implementációjuk nagyon hasonló. Az elsődleges különbség a sávobjektum regisztrálásakor van, ami viszont szabályozza az objektum típusát és tárolóját. Ez a szakasz az összes sávobjektumra jellemző megvalósítási szempontokat ismerteti. További megvalósítási részletekért tekintse meg Egyéni kezelősáv egyszerű példáját.

A IUnknown és IClassFactorymellett minden sávobjektumnak az alábbi interfészeket kell implementálnia.

Az osztályazonosító (CLSID) regisztrálása mellett az Explorer bar és az asztali sáv objektumait is regisztrálni kell a megfelelő összetevőkategóriához. Az összetevőkategória regisztrálása határozza meg az objektum típusát és tárolóját. Az eszközsávok eltérő regisztrációs eljárást használnak, és nem rendelkeznek kategóriaazonosítóval (CATID). Az őket igénylő három sávobjektum CATID-jei a következők:

Sáv típusa Összetevőkategória
Függőleges böngészősáv CATID_InfoBand
Vízszintes navigációs sáv CATID_CommBand
Asztali eszköztár CATID_DeskBand

 

Lásd a Sávregisztráció részt a sávobjektumok regisztrálásának további megbeszéléséhez.

Ha a sávobjektum felhasználói bemenetet szeretne fogadni, akkor IInputObjectis implementálnia kell. Ha elemeket szeretne hozzáadni az Explorer-sávok vagy az asztali sávok helyi menüjéhez, a sávobjektumnak exportálnia kell IContextMenu. Az eszközsávok nem támogatják a helyi menüket.

Mivel a sávobjektumok gyermekablakot implementálnak, a Windows-üzenetkezeléshez egy ablakeljárást is végre kell hajtaniuk.

A sávobjektumok parancsokat küldhetnek a tárolójukba a tároló IOleCommandTarget felületén keresztül. Az interfészmutató megszerzéséhez hívja meg a kontejner IInputObjectSite::QueryInterface metódusát, és kérje az IID_IOleCommandTarget-et. Ezután parancsokat küld a tárolónak IOleCommandTarget::Exec. A parancscsoport CGID_DeskBand. Amikor egy sávobjektum IDeskBand::GetBandInfo metódust hív meg, a tároló a dwBandID paraméterrel rendeli hozzá a sávobjektumhoz egy azonosítót, amely három parancshoz használatos. Négy IOleCommandTarget::Exec parancsazonosítók támogatottak.

  • DBID_BANDINFOCHANGED

    A zenekar adatai megváltoztak. Állítsa be a pvaIn paramétert a legutóbbi hívásában kapott sávazonosítóra az IDeskBand::GetBandInfofüggvény esetében. A tároló meghívja a sávobjektum IDeskBand::GetBandInfo metódust a frissített információk lekéréséhez.

  • DBID_MAXIMIZEBAND

    Maximalizálja a frekvenciasávot. Állítsa a pvaIn paramétert a sávazonosítóra, amelyet a legutóbbi IDeskBand::GetBandInfohívásban kapott.

  • DBID_SHOWONLY

    Kapcsolja be vagy ki a tároló többi sávját. Állítsa a pvaIn paramétert a VT_UNKNOWN típusra az alábbi értékek egyikével:

    Érték Leírás
    Punk Mutató a sáv objektum IUnknown felületére. Minden más asztali sáv el lesz rejtve.
    0 Rejtse el az összes asztali sávot.
    1 Az összes asztali sáv megjelenítése.

     

  • DBID_PUSHCHEVRON

    5-ös verzió. Sávos menü megjelenítése. A tároló egy RB_PUSHCHEVRON üzenetet küld, és a sávobjektum kap egy RBN_CHEVRONPUSHED értesítést, amely a sávsáv menüjének megjelenítésére kéri. Állítsa az IOleCommandTarget::Exec metódus nCmdExecOpt paraméterét az IDeskBand::GetBandInfolegutóbbi hívásában kapott sávazonosítóra. Állítsa az IOleCommandTarget::Exec metódus pvaIn paraméterét az alkalmazás által meghatározott értékkel rendelkező VT_I4 típusra. A RBN_CHEVRONPUSHED értesítés lAppValue értékeként adja vissza a sávobjektumnak.

Sávregisztráció

A sávobjektumokat OLE folyamatban lévő kiszolgálóként kell regisztrálni, amely támogatja a lakásszálazást. A kiszolgáló alapértelmezett értéke egy menüszöveg-karakterlánc. Explorer-sávok esetén az Internet Explorer View menü Explorer-sáv almenüjében jelenik meg. Eszközsávok esetén az Internet Explorer Nézet menü Eszköztárak almenüjében fog megjelenni. Az asztali sávok esetében a tálca gyorsmenüjének Eszköztárak almenüjében jelenik meg. A menüerőforrásokhoz hasonlóan az ampersand (&) betű elé helyezése aláhúzást okoz, és lehetővé teszi a billentyűparancsok használatát. Az első ábrán látható függőleges kezelősáv menüsztringje például a "Minta &Függőleges kezelősáv".

Az Internet Explorer kezdetben lekéri a regisztrált Explorer-sávobjektumok felsorolását a beállításjegyzékből az összetevőkategóriák segítségével. A teljesítmény növelése érdekében gyorsítótárazza ezt az enumerálást, ami azt eredményezi, hogy a hozzáadott Explorer-sávok figyelmen kívül hagyhatók. Ha azt szeretné, hogy a Windows Internet Explorer újraépítse a gyorsítótárat, és felismerjen egy új Explorer-sávot, törölje a következő beállításkulcsokat az új Explorer-sáv regisztrációja során:

HKEY_CURRENT_USER\Szoftver\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000046}\Enum

HKEY_CURRENT_USER\Szoftver\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Összetevő kategóriák\{00021494-0000-0000-C000-000000000046}\Enum

Megjegyzés

Mivel minden felhasználóhoz létrejön egy Explorer-gyorsítótár, előfordulhat, hogy a telepítőalkalmazásnak számba kell vennie az összes felhasználói beállításjegyzék-hiveset, vagy hozzá kell adnia egy felhasználónkénti csonkot a futtatáshoz, amikor a felhasználó először bejelentkezik.

 

A sávobjektumok alapszintű beállításjegyzék-bejegyzése általában a következőképpen jelenik meg.

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

Az eszközsávoknak az objektumuk CLSID-jét is regisztrálniuk kell az Internet Explorerben. Ehhez rendeljen hozzá egy értéket a(z) HKEY_LOCAL_MACHINE\Szoftver\Microsoft\Internet Explorer\Eszköztár alá, az eszközsáv objektum CLSID GUID-jával, ahogyan itt látható. Az adatérték figyelmen kívül lesz hagyva, ezért az érték típusa nem lényeges.

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

Több választható érték is hozzáadható a beállításjegyzékhez. Például a következő értékre van szükség, ha az Explorer-sávot szeretné használni a HTML megjelenítéséhez. A megjelenített érték nem példa, hanem a ténylegesen használandó érték.

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

A fenti értékkel együtt használva a következő opcionális értékre is szükség van, ha az Explorer sávot szeretné használni a HTML megjelenítéséhez. Ezt az értéket annak a fájlnak a helyére kell állítani, amely az Explorer-sáv HTML-tartalmát tartalmazza.

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

Egy másik választható érték határozza meg az Explorer-sáv alapértelmezett szélességét vagy magasságát attól függően, hogy függőleges vagy vízszintes.

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

A BarSize értéket a sáv szélességére vagy magasságára kell állítani. Az értékhez nyolc bájt szükséges, és bináris értékként kerül a beállításjegyzékbe. Az első négy bájt képpontban adja meg a méretet hexadecimális formátumban, a bal szélső bájttól kezdve. Az utolsó négy bájt le vannak foglalva, és nullára kell állítaniuk.

Itt látható például egy HTML-kompatibilis, alapértelmezett 291 (0x123) képpont szélességű explorersáv teljes beállításjegyzék-bejegyzése.

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

A sávobjektum CATID-jének regisztrációját programozott módon kezelheti. Hozzon létre egy összetevőkategóriák kezelőobjektumát (CLSID_StdComponentCategoriesMgr), és kérjen mutatót a ICatRegister felületére. Adja át a sávobjektum CLSID- és CATID-azonosítóját ICatRegister::RegisterClassImplCategories.

Egyszerű példa egy egyéni kezelősávra

Ez a példa végigvezeti a bevezetésben látható minta függőleges Explorer-sáv implementálásán.

Az egyéni Explorer-sávok létrehozásának alapvető eljárása a következő.

  1. A DLLáltal igényelt függvények implementálása.
  2. Implementálja a szükséges COM-interfészeket.
  3. A kívánt opcionális COM-felületek implementálása.
  4. Regisztrálja az objektum CLSID-azonosítóját és szükség esetén az összetevő kategóriáját.
  5. Hozzon létre egy gyermekablakot az Internet Explorerből, amely az Explorer-sáv megjelenítési régiójának megfelelően van méretezve.
  6. A gyermekablak használatával megjelenítheti az információkat, és kezelheti a felhasználót.

Az Explorer-sáv mintájában alkalmazott nagyon egyszerű megvalósítás valójában használható bármelyik típusú Explorer-sávhoz, vagy akár egy asztali sávhoz is, egyszerűen a megfelelő összetevőkategóriára való regisztrációval. Kifinomultabb implementációkat kell testre szabni az egyes objektumtípusok megjelenítési régióihoz és tárolóihoz. Ennek a testreszabásnak a nagy része azonban a mintakód felhasználásával és a megszokott Windows-programozási technikák alkalmazásával az alablak esetében valósítható meg. Hozzáadhat például vezérlőket a felhasználói interakcióhoz, vagy grafikus elemeket a gazdagabb megjelenítéshez.

DLL-függvények

Mindhárom objektum egyetlen DLL-fájlba van csomagolva, amely az alábbi függvényeket teszi elérhetővé.

Az első három függvény standard implementáció, és itt nem tárgyaljuk. A Class Factory implementációja is szabványos.

Szükséges interfész-implementációk

A függőleges Explorer-minta négy szükséges felületet valósít meg: IUnknown, IObjectWithSite, IPersistStream, és IDeskBand a CExplorerBar osztály részeként. A konstruktor, destruktor és IUnknown implementációk egyszerűek, és itt nem tárgyaljuk. Részletekért tekintse meg a mintakódot.

Az alábbi felületeket részletesen tárgyaljuk.

IObjectWithSite

Amikor a felhasználó kiválaszt egy Explorer-sávot, a tároló meghívja a megfelelő sávobjektum IObjectWithSite::SetSite metódust. A punkSite paramétert a helyszín IUnknown mutatójára állítjuk be.

Az SetSite implementációjának általában a következő lépéseket kell végrehajtania:

  1. Engedje fel az aktuálisan tárolt webhelymutatót.
  2. Ha az SetSite számára átadott mutató NULL van beállítva, a sáv el lesz távolítva. SetSite S_OK adhat vissza.
  3. Ha az SetSite számára átadott mutató nemNULL, új webhely lesz beállítva. SetSite a következőket kell tennie:
    1. Hívja meg QueryInterface a webhelyen az IOleWindow felületéhez.
    2. Hívja meg IOleWindow::GetWindow a szülőablak leírójának beszerzéséhez. Mentse a fogópontot későbbi használatra. Ha már nincs rá szükség, szabadítsa fel IOleWindow.
    3. Hozza létre a sávobjektum ablakát az előző lépésben beszerzett ablak gyermekeként. Ne hozza létre látható ablakként.
    4. Ha a sávobjektum implementálja az IInputObjectfelületet, hívja meg a helyszínen a IInputObjectSite interfészhez tartozó QueryInterface metódust. Tárolja a mutatót erre a felületre későbbi használatra.
    5. Ha minden lépés sikeres, adja vissza a S_OK. Ha nem, adja vissza az OLE által definiált hibakódot, amely jelzi, hogy mi nem sikerült.

Az Explorer-sáv minta a következőképpen implementálja SetSite. Az alábbi kódban m_pSite egy privát tagváltozó, amely a IInputObjectSite mutatót tartalmazza, m_hwndParent pedig a szülőablak fogópontját. Ebben a példában az ablak létrehozása is kezelve van. Ha az ablak nem létezik, ez a metódus a SetSite által beszerzett szülőablak megfelelő méretű gyermekeként hozza létre az Intézősáv ablakát. A gyermekablak fogantyúja a(z) m_hwndobjektumban van tárolva.

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

A minta GetSite implementációja egyszerűen körbefuttat egy hívást a webhely QueryInterface metódusához, a SetSiteáltal mentett webhelymutató használatával.

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

Az Internet Explorer meghívja az Explorer-sáv IPersistStream felületét, hogy lehetővé tegye az Explorer-sáv számára az állandó adatok betöltését vagy mentését. Ha nincsenek állandó adatok, a metódusnak továbbra is sikerkódot kell visszaadnia. Az IPersistStream interfész örökli a IPersistinterfész tulajdonságait, ezért öt metódust kell implementálni.

Az Explorer Bar példaprogram nem használ állandó adatokat, és csak minimális implementációval rendelkezik IPersistStream. IPersist::GetClassID az objektum CLSID azonosítóját (CLSID_SampleExplorerBar) adja vissza, a fennmaradó rész pedig S_OK, S_FALSE vagy E_NOTIMPL.

IDeskBand

Az IDeskBand felület a sávobjektumokra jellemző. Az egy módszere mellett az IDockingWindow-t is örökli, ami viszont a IOleWindow-ből származik.

Két IOleWindow metódus létezik: GetWindow és IOleWindow::ContextSensitiveHelp. A GetWindow explorer bar mintaalkalmazása az Explorer Bar gyermekablak-leíróját adja vissza, m_hwnd. A környezetfüggő súgó nincs implementálva, így a ContextSensitiveHelp a E_NOTIMPLértéket adja vissza.

Az IDockingWindow interfész három metódussal rendelkezik.

A ResizeBorderDW metódus nem használható semmilyen sávobjektumhoz, és mindig E_NOTIMPL kell visszaadnia. A ShowDW metódus a paraméter értékétől függően megjeleníti vagy elrejti az Explorer-sáv ablakát.

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

    return S_OK;
}

A CloseDW metódus megsemmisíti az Explorer-sáv ablakát.

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

    return S_OK;
}

A fennmaradó metódus, GetBandInfo, az IDeskBand-höz tartozik. Az Internet Explorer az Explorer-sáv azonosítójának és megtekintési módjának megadására használja. Az Internet Explorer a DESKBANDINFO struktúrájának harmadik paraméterként átadott dwMask tagjának kitöltésével is kérhet egy vagy több információt az Explorer sávról. GetBandInfo tárolja az azonosítót és a megtekintési módot, és töltse ki a DESKBANDINFO struktúrát a kért adatokkal. A következő kódpélda szerint az Explorer Bar példa megvalósítja a GetBandInfo.

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

Választható felületi implementációk

Két interfész nem szükséges, de ez hasznos lehet a implementáláshoz: IInputObject és IContextMenu. Az Explorer Bar minta az IInputObject -t implementálja. A IContextMenuimplementálásával kapcsolatos információkért tekintse meg a dokumentációt.

IInputObject

Az IInputObject felületet akkor kell implementálni, ha egy sávobjektum elfogadja a felhasználói bemenetet. Az Internet Explorer implementálja IInputObjectSite, és IInputObject használatával tartja fenn a megfelelő felhasználói beviteli fókuszt, ha több ablak is van benne. Az Explorer-sávnak három metódust kell implementálnia.

Az Internet Explorer meghívja UIActivateIO, hogy tájékoztassa az Explorer-sávot az aktiválásról vagy inaktiválásról. Aktiváláskor az Explorer-mintasáv meghívja SetFocus, hogy állítsa a fókuszt az ablakára.

Az Internet Explorer meghívja HasFocusIO, amikor megkísérli meghatározni, hogy melyik ablak van fókuszban. Ha az Explorer-sáv ablaka vagy valamelyik leszármazottja fókuszban van, HasFocusIO S_OK értéket kell visszaadnia. Ha nem, akkor S_FALSE kell visszaadnia.

TranslateAcceleratorIO lehetővé teszi az objektum számára a billentyűzetgyorsítók feldolgozását. Az Explorer Bar minta nem implementálja ezt a metódust, ezért az S_FALSE-t adja vissza.

Az mintasáv IInputObjectSite megvalósítása a következőképpen történik.

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

CLSID-regisztráció

Az összes COM-objektumhoz hasonlóan az Explorer Bar CLSID azonosítóját is regisztrálni kell. Ahhoz, hogy az objektum megfelelően működjön az Internet Explorerrel, regisztrálva kell lennie a megfelelő összetevőkategóriához (CATID_InfoBand). Az Explorer-sáv megfelelő kódszakasza az alábbi kódpéldában látható.

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

A sávobjektumok regisztrálása a mintában normál COM-eljárásokat használ.

A CLSID mellett a sávobjektum-kiszolgálót egy vagy több összetevőkategóriára is regisztrálni kell. Valójában ez a fő különbség a függőleges és a vízszintes Explorer Bar-minták implementációjában. Ezt a folyamatot egy összetevőkategória-kezelő objektum (CLSID_StdComponentCategoriesMgr) létrehozásával és a ICatRegister::RegisterClassImplCategories metódussal kezeli a sávobjektum-kiszolgáló regisztrálásához. Ebben a példában az összetevőkategória-regisztrációt úgy kezeli a rendszer, hogy átadja az Explorer Bar-minta CLSID-jét és CATID-jét egy privát függvénynek –RegisterComCat– az alábbi kódpéldában látható módon.

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

Az ablak eljárása

Mivel a sávobjektumok gyermekablakot használnak a megjelenítéshez, a Windows-üzenetkezeléshez egy ablakeljárást kell implementálnia. A sávminta minimális funkcionalitással rendelkezik, ezért az ablak eljárása csak öt üzenetet kezel:

Az eljárás egyszerűen bővíthető, hogy további üzeneteket fogadjon a további funkciók támogatásához.

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

A WM_COMMAND kezelő egyszerűen nullát ad vissza. A WM_PAINT kezelő a bevezetésben az Explorer-sáv példájában látható egyszerű szöveges megjelenítést hozza létre.

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

A WM_SETFOCUS és WM_KILLFOCUS kezelői a webhely IInputObjectSite::OnFocusChangeIS metódus meghívásával tájékoztatják a webhelyet a fókuszváltozásról.

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

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

A sávobjektumok rugalmas és hatékony módot biztosítanak az Internet Explorer képességeinek bővítésére egyéni Explorer-sávok létrehozásával. Az asztali sáv implementálása lehetővé teszi a normál ablakok képességeinek bővítését. Bár némi COM-programozásra van szükség, ez végső soron arra szolgál, hogy gyermekablakot biztosítson a felhasználói felület számára. Innen a megvalósítás nagy része már ismerős Windows-programozási technikákat is használhat. Bár az itt tárgyalt példa csak korlátozott funkcionalitással rendelkezik, egy sávobjektum összes szükséges funkcióját szemlélteti, és könnyen kiterjeszthető egy egyedi és hatékony felhasználói felület létrehozásához.