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.
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.
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.
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.
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.
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.
Kezdetben az asztali sávok rögzítve vannak a tálcán.
A felhasználó ezután húzhatja az asztali sávot az asztalra, és normál ablakként jelenik meg.
Az alábbi témaköröket tárgyaljuk.
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.
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.
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ő.
- A DLLáltal igényelt függvények implementálása.
- Implementálja a szükséges COM-interfészeket.
- A kívánt opcionális COM-felületek implementálása.
- Regisztrálja az objektum CLSID-azonosítóját és szükség esetén az összetevő kategóriáját.
- 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.
- 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.
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.
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.
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:
- Engedje fel az aktuálisan tárolt webhelymutatót.
- 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.
- Ha az SetSite számára átadott mutató nemNULL, új webhely lesz beállítva.
SetSite a következőket kell tennie:
- Hívja meg QueryInterface a webhelyen az IOleWindow felületéhez.
- 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.
- 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.
- 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.
- 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;
}
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.
- IPersist::GetClassID
- IPersistStream::IsDirty
- IPersistStream::Load
- IPersistStream::Save
- IPersistStream::GetSizeMax
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.
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;
}
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.
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;
};
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;
}
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.