Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Explorer-fältet introducerades med Microsoft Internet Explorer 4.0 för att tillhandahålla ett visningsområde intill webbläsarfönstret. Det är i princip ett underordnat fönster i Windows Internet Explorer-fönstret, och det kan användas för att visa information och interagera med användaren på ungefär samma sätt. Explorer-rader visas oftast som en lodrät panel till vänster i webbläsaren. Ett Explorer-fält kan dock också visas vågrätt under webbläsarfönstret.
Det finns ett brett utbud av möjliga användningsområden för Explorer-fältet. Användare kan välja vilket alternativ de vill se på flera olika sätt, bland annat genom att välja det från Explorer-fältet undermenyn i menyn Visa eller klicka på en verktygsfältsknapp. Internet Explorer innehåller flera vanliga Explorer-fält, inklusive Favoriter och Sökning.
Ett av sätten du kan anpassa Internet Explorer på är genom att lägga till ett anpassat Explorer-fält. När den implementeras och registreras läggs den till i Explorer-fältet undermenyn i menyn Visa. När det väljs av användaren kan visningsområdet i Explorer-fältet sedan användas för att visa information och ta användarindata på ungefär samma sätt som ett normalt fönster.
Om du vill skapa ett anpassat Explorer-fält måste du implementera och registrera ett bandobjekt. Bandobjekt introducerades med version 4.71 av Shell och tillhandahåller funktioner som liknar dem i vanliga fönster. Men eftersom de är COM-objekt (Component Object Model) och finns i Antingen Internet Explorer eller Shell, implementeras de något annorlunda. Enkla bandobjekt användes för att skapa exempel på Explorer Bars som visas i den första bilden. Implementeringen av det lodräta Explorer Bar-exemplet beskrivs i detalj i ett senare avsnitt.
Verktygsband
Ett verktygsband är ett bandobjekt som introducerades med Microsoft Internet Explorer 5 för att stödja Windows radioverktygsfältfunktion. Verktygsfältet i Internet Explorer är faktiskt en rebar-kontroll som innehåller flera verktygsfältkontroller. Genom att skapa ett verktygsband kan du lägga till ett band till den armeringsjärnskontrollen. Men precis som Explorer Bars är ett verktygsband ett fönster för generell användning.
Användarna visar ett verktygsfält genom att välja det från verktygsfält undermenyn i menyn Visa eller från snabbmenyn som visas genom att högerklicka på verktygsfältsområdet.
Skrivbordsband
Bandobjekt kan också användas för att skapa skrivbordsband. Även om deras grundläggande implementering liknar Explorer Bars, är skrivbordsband inte relaterade till Internet Explorer. Ett skrivbordsband är i princip ett sätt att skapa ett dockbart fönster på skrivbordet. Användaren väljer det genom att högerklicka på aktivitetsfältet och välja det från Verktygsfält undermeny.
Ursprungligen dockas skrivbordsband i aktivitetsfältet.
Användaren kan sedan dra skrivbordsbandet till skrivbordet och det visas som ett normalt fönster.
Implementering av Band-objekt
Följande ämnen diskuteras.
Grunderna för bandobjekt
Även om de kan användas ungefär som vanliga fönster är bandobjekt COM-objekt som finns i en container. Explorer-fält finns i Internet Explorer och skrivbordsband finns i skalet. Även om de fungerar med olika funktioner är deras grundläggande implementering mycket lik. Den primära skillnaden är hur bandobjektet registreras, vilket i sin tur styr typen av objekt och dess container. I det här avsnittet beskrivs de aspekter av implementeringen som är gemensamma för alla bandobjekt. Mer implementeringsinformation finns i Ett enkelt exempel på ett anpassat explorerfält.
Förutom IUnknown och IClassFactorymåste alla bandobjekt implementera följande gränssnitt.
Förutom att registrera deras klassidentifierare (CLSID) måste Explorer Bar- och desk band-objekt också registreras för lämplig komponentkategori. Om du registrerar komponentkategorin avgörs objekttypen och dess container. Verktygsband använder en annan registreringsprocedur och har ingen kategoriidentifierare (CATID). CATID:erna för de tre bandobjekt som kräver dem är:
Bandtyp | Komponentkategori |
---|---|
Lodrätt utforskarfält | CATID_InfoBand |
Vågrätt utforskarfält | CATID_CommBand |
Skrivbordspanel | CATID_DeskBand |
Mer information om hur du registrerar bandobjekt finns i Band Registration.
Om bandobjektet ska acceptera användarindata måste det även implementera IInputObject-. Om du vill lägga till objekt i snabbmenyn för Explorer Bar- eller skrivbordsband måste bandobjektet exportera IContextMenu-. Verktygsband stöder inte snabbmenyer.
Eftersom bandobjekt implementerar ett underordnat fönster måste de också implementera en fönsterprocedur för att hantera Windows-meddelanden.
Bandobjekt kan skicka kommandon till containern via containerns IOleCommandTarget--gränssnitt. Hämta gränssnittspekaren genom att anropa containerns IInputObjectSite::QueryInterface-metod och be om IID_IOleCommandTarget. Sedan skickar du kommandon till containern med IOleCommandTarget::Exec. Kommandogruppen är CGID_DeskBand. När ett bandobjekts metod IDeskBand::GetBandInfo anropas använder containern parametern dwBandID för att tilldela bandobjektet en identifierare som används för tre av kommandona. Fyra IOleCommandTarget::Exec kommando-ID:er stöds.
DBID_BANDINFOCHANGED
Bandets information har ändrats. Ange parametern pvaIn till den bandidentifierare som togs emot i det senaste anropet till IDeskBand::GetBandInfo. Containern anropar bandobjektets IDeskBand::GetBandInfo- metod för att begära den uppdaterade informationen.
DBID_MAXIMIZEBAND
Maximera musikgruppen. Ange parametern pvaIn till den bandidentifierare som togs emot i det senaste anropet till IDeskBand::GetBandInfo.
DBID_SHOWONLY
Aktivera eller inaktivera andra band i containern. Ange parametern pvaIn till den VT_UNKNOWN typen med något av följande värden:
Värde Beskrivning Punk En pekare till bandobjektets IUnknown-gränssnitt. Alla andra skrivbordsband kommer att döljas. 0 Dölj alla skrivbordsband. 1 Visa alla skrivbordsband. DBID_PUSHCHEVRON
version 5. Visa en rullgardinsmeny. Containern skickar ett RB_PUSHCHEVRON meddelande och bandobjektet får ett RBN_CHEVRONPUSHED meddelande som uppmanar det att visa chevronmenyn. Ställ in metodens IOleCommandTarget::Exec parameter nCmdExecOpt till bandidentifieraren som mottogs i det senaste anropet till IDeskBand::GetBandInfo. Ange parametern IOleCommandTarget::Exec-metodens parameter pvaIn till den VT_I4 typen med ett programdefinierat värde. Det skickas tillbaka till bandobjektet som lAppValue värdet för RBN_CHEVRONPUSHED-meddelandet.
Bandregistrering
Ett bandobjekt måste registreras som en ole-in-process-server som stöder lägenhetstrådning. Standardvärdet för servern är en menytextsträng. För Explorer-staplar visas den i Explorer-fältet undermenyn i Internet Explorer Visa-menyn. För verktygsband visas det i verktygsfält undermenyn i Internet Explorer Visa-menyn. För skrivbordsgrupper visas det i Verktygsfält undermenyn för aktivitetsfältets snabbmeny. Precis som med menyresurser gör placering av ett et-tecken (&) framför en bokstav att det blir understruket och aktiverar kortkommandon. Till exempel är menysträngen för det lodräta Explorer-fältet som visas i den första bilden "Exempel &lodrät explorerfält".
Till en början hämtar Internet Explorer en uppräkning av de registrerade Explorer Bar-objekten från registret med hjälp av komponentkategorierna. För att öka prestandan cachelagrar den sedan den här uppräkningen, vilket gör att utforskarfält som läggs till senare förbises. Om du vill tvinga Windows Internet Explorer att återskapa cacheminnet och identifiera ett nytt Explorer-fält tar du bort följande registernycklar under registreringen av det nya Explorer-fältet:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021493-0000-0000-C000-000000000046}\Enum
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Discardable\PostSetup\Component Categories\{00021494-0000-0000-C000-000000000046}\Enum
Not
Eftersom en Explorer Bar-cache skapas för varje användare kan ditt installationsprogram behöva räkna upp alla användarregisterdatafiler eller lägga till en stub per användare som ska köras när användaren loggar in.
I allmänhet visas den grundläggande registerposten för ett bandobjekt på följande sätt.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
(Default) = Menu Text String
InProcServer32
(Default) = DLL Path Name
ThreadingModel = Apartment
Verktygsband måste också ha objektets CLSID registrerat med Internet Explorer. Det gör du genom att tilldela ett värde under HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Toolbar med namnet med verktygsbandsobjektets CLSID GUID enligt nedan. Dess datavärde ignoreras, så värdetypen är oviktig.
HKEY_LOCAL_MACHINE
Software
Microsoft
Internet Explorer
Toolbar
{Your Band Object's CLSID GUID}
Det finns flera valfria värden som också kan läggas till i registret. Till exempel är följande värde nödvändigt om du vill använda Explorer-fältet för att visa HTML Värdet som visas är inte ett exempel, utan det faktiska värde som ska användas.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
Instance
CLSID
(Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}
Används tillsammans med det värde som visas ovan, är följande valfria värde också nödvändigt om du vill använda Explorer-fältet för att visa HTML. Det här värdet ska anges till platsen för filen som innehåller HTML-innehållet för Explorer-fältet.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
Instance
InitPropertyBag
Url
Ett annat valfritt värde definierar standardbredden eller höjden för Explorer-fältet, beroende på om det är lodrätt eller vågrätt.
HKEY_CURRENT_USER
Software
Microsoft
Internet Explorer
Explorer Bars
{Your Band Object's CLSID GUID}
BarSize
Värdet BarSize ska justeras till stapelns bredd eller höjd. Värdet kräver åtta byte och placeras i registret som ett binärt värde. De första fyra byteen anger storleken i bildpunkter, i hexadecimalt format, med början från den vänstra byte. De sista fyra byteen är reserverade och ska vara inställda på noll.
Till exempel visas de fullständiga registerposterna för ett HTML-kompatibelt Explorer-fält med standardbredden 291 (0x123) bildpunkter här.
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
Du kan hantera registrering av ett bandobjekts CATID programmatiskt. Skapa ett hanteringsobjekt för komponentkategorier (CLSID_StdComponentCategoriesMgr) och begär en pekare till dess ICatRegister--gränssnitt. Skicka bandobjektets CLSID och CATID till ICatRegister::RegisterClassImplCategories.
Ett enkelt exempel på ett anpassat explorerfält
Det här exemplet går igenom implementeringen av det vertikala Explorer-fält som visas i introduktionen.
Den grundläggande proceduren för att skapa ett anpassat Explorer-fält är följande.
- Implementera de funktioner som krävs av DLL-.
- Implementera nödvändiga COM-gränssnitt.
- Implementera önskade valfria COM-gränssnitt.
- Registrera objektets CLSID och, om det behövs, komponentkategori.
- Skapa ett underfönster i Internet Explorer, som passar Explorer-fältets visningsområde.
- Använd det underordnade fönstret för att visa information och interagera med användaren.
Den mycket enkla implementeringen som används i Explorer Bar-exemplet kan faktiskt användas för antingen typ av Explorer Bar eller ett skrivbordsband genom att helt enkelt registrera den för lämplig komponentkategori. Mer avancerade implementeringar måste anpassas för varje objekttyps visningsregion och container. En stor del av den här anpassningen kan dock utföras genom att ta exempelkoden och utöka den genom att använda välbekanta Windows-programmeringstekniker i det underordnade fönstret. Du kan till exempel lägga till kontroller för användarinteraktion eller grafik för en mer omfattande visning.
DLL-funktioner
Alla tre objekten är paketerade i en enda DLL, vilket exponerar följande funktioner.
De första tre funktionerna är standardimplementeringar och kommer inte att diskuteras här. Class Factory-implementeringen är också standard.
Nödvändiga gränssnittsimplementeringar
Det lodräta Explorer Bar-exemplet implementerar de fyra nödvändiga gränssnitten: IUnknown, IObjectWithSite, IPersistStreamoch IDeskBand som en del av klassen CExplorerBar. Konstruktorn, destruktorn och IUnknown-implementeringarna är okomplicerade och kommer inte att behandlas här. Mer information finns i exempelkoden.
Följande gränssnitt beskrivs i detalj.
IObjectWithSite
När användaren väljer ett Explorer-fält anropar containern motsvarande bandobjekts IObjectWithSite::SetSite-metod. Parametern punkSite ställs in på webbplatsens IUnknown pekare.
I allmänhet bör en SetSite- implementering utföra följande steg:
- Släpp alla webbplatspekare som hålls fast.
- Om pekaren som skickas till SetSite är inställd på NULL-tas bandet bort. SetSite kan returnera S_OK.
- Om pekaren som skickas till SetSite inte ärNULL, anges en ny plats.
SetSite bör göra följande:
- Anropa QueryInterface- på webbplatsen för dess IOleWindow--gränssnitt.
- Anropa IOleWindow::GetWindow för att hämta det överordnade fönstrets handtag. Spara handtaget för senare användning. Släpp IOleWindow om det inte längre behövs.
- Skapa bandobjektets fönster som ett underordnat fönster till fönstret som hämtades i föregående steg. Skapa den inte som ett synligt fönster.
- Om bandobjektet implementerar IInputObjectanropar du QueryInterface- på webbplatsen för dess IInputObjectSite--gränssnitt. Lagra pekaren i det här gränssnittet för senare användning.
- Om alla steg lyckas returnerar du S_OK. Annars returnerar du den OLE-definierade felkoden som anger vad som misslyckades.
Explorer Bar-exemplet implementerar SetSite- på följande sätt. I följande kod är m_pSite en privat medlemsvariabel som innehåller en IInputObjectSite pekare och m_hwndParent innehåller det överordnade fönstrets referens. I det här exemplet hanteras även skapandet av fönster. Om fönstret inte finns skapar den här metoden Explorer Barens fönster som ett underordnat fönster till det överordnade fönstret som hämtas av SetSite. Handtaget för barnfönstret lagras i 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;
}
Exemplets GetSite- implementering omsluter helt enkelt ett anrop till webbplatsens QueryInterface-metod med hjälp av platspekaren som sparats av 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 anropar Explorer-fältets IPersistStream--gränssnitt så att Explorer-fältet kan läsa in eller spara beständiga data. Om det inte finns några beständiga data måste metoderna fortfarande returnera en lyckad kod. Gränssnittet IPersistStream ärver från IPersist, så fem metoder måste implementeras.
- IPersist::GetClassID
- IPersistStream::IsDirty
- IPersistStream::Load
- IPersistStream::Spara
- IPersistStream::GetSizeMax
Explorer Bar-exemplet använder inte några beständiga data och har bara en minimal implementering av IPersistStream. IPersist::GetClassID returnerar objektets CLSID (CLSID_SampleExplorerBar) och resten returnerar antingen S_OK, S_FALSE eller E_NOTIMPL.
IDeskBand
Gränssnittet IDeskBand är specifikt för bandobjekt. Förutom sin enda metod ärver den från IDockingWindow, som i sin tur ärver från IOleWindow.
Det finns två IOleWindow- metoder: GetWindow och IOleWindow::ContextSensitiveHelp. Explorer Bar-exemplets implementering av GetWindow returnerar Explorer-fältets underordnade fönsterhandtag m_hwnd. Kontextkänslig hjälp implementeras inte, så ContextSensitiveHelp returnerar E_NOTIMPL.
Gränssnittet IDockingWindow har tre metoder.
Metoden ResizeBorderDW används inte med någon typ av bandobjekt och bör alltid returnera E_NOTIMPL. Metoden ShowDW visar eller döljer utforskarfältets fönster, beroende på värdet för parametern.
STDMETHODIMP CDeskBand::ShowDW(BOOL fShow)
{
if (m_hwnd)
{
ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
}
return S_OK;
}
Metoden CloseDW förstör utforskarfältets fönster.
STDMETHODIMP CDeskBand::CloseDW(DWORD)
{
if (m_hwnd)
{
ShowWindow(m_hwnd, SW_HIDE);
DestroyWindow(m_hwnd);
m_hwnd = NULL;
}
return S_OK;
}
Den återstående metoden, GetBandInfo, är specifik för IDeskBand. Internet Explorer använder det för att ange explorerfältets identifierare och visningsläge. Internet Explorer kan också begära en eller flera uppgifter från Explorer-fältet genom att fylla i dwMask medlem i DESKBANDINFO struktur som skickas som den tredje parametern. GetBandInfo ska lagra identifieraren och visningsläget och fylla DESKBANDINFO struktur med begärda data. Explorer Bar-exemplet implementerar GetBandInfo- enligt följande kodexempel.
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;
}
Valfria gränssnittsimplementeringar
Det finns två gränssnitt som inte krävs, men det kan vara användbart att implementera: IInputObject och IContextMenu. Explorer Bar-exemplet implementerar IInputObject. I dokumentationen finns information om hur du implementerar IContextMenu.
IInputObject
Gränssnittet IInputObject måste implementeras om ett bandobjekt accepterar användarindata. Internet Explorer implementerar IInputObjectSite- och använder IInputObject- för att behålla rätt fokus på användarindata när det finns fler än ett inneslutet fönster. Det finns tre metoder som måste implementeras av ett Explorer-fält.
Internet Explorer anropar UIActivateIO- för att informera Explorer-fältet om att det aktiveras eller inaktiveras. När det aktiveras anropar Explorer Bar-provprogrammet SetFocus- för att sätta fokus på sitt fönster.
Internet Explorer anropar HasFocusIO när det försöker avgöra vilket fönster som har fokus. Om utforskarfältets fönster eller någon av dess underordnade objekt har fokus bör HasFocusIO- returnera S_OK. Annars bör den returnera S_FALSE.
TranslateAcceleratorIO tillåter objektet att bearbeta tangentbordsacceleratorer. Explorer Bar-exemplet implementerar inte den här metoden, så den returnerar S_FALSE.
Exempelfältets implementering av IInputObjectSite är följande.
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-registrering
Precis som med alla COM-objekt måste Explorer-fältets CLSID registreras. För att objektet ska fungera korrekt med Internet Explorer måste det också vara registrerat för lämplig komponentkategori (CATID_InfoBand). Det relevanta kodavsnittet för Explorer-fältet visas i följande kodexempel.
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;
}
Registrering av bandobjekt i exemplet använder normala COM-procedurer.
Förutom CLSID måste bandobjektservern också registreras för en eller flera komponentkategorier. Det här är faktiskt den största skillnaden i implementering mellan de lodräta och vågräta Explorer Bar-exemplen. Den här processen hanteras genom att skapa ett komponentkategoriers hanteringsobjekt (CLSID_StdComponentCategoriesMgr) och använda ICatRegister::RegisterClassImplCategories metod för att registrera bandobjektservern. I det här exemplet hanteras registrering av komponentkategori genom att skicka exempelexemplet CLSID och CATID i Explorer till en privat funktion,RegisterComCat, som du ser i följande kodexempel.
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;
}
Fönsterproceduren
Eftersom ett bandobjekt använder ett underordnat fönster för sin visning måste det implementera en fönsterprocedur för att hantera Windows-meddelanden. Bandexemplet har minimal funktionalitet, så fönsterproceduren hanterar bara fem meddelanden:
Proceduren kan enkelt utökas för att hantera ytterligare meddelanden för att stödja fler funktioner.
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;
}
Hanteraren WM_COMMAND returnerar helt enkelt noll. WM_PAINT-hanteraren skapar den enkla textvisning som visas i Explorer Bar-exemplet i introduktionen.
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);
}
}
Hanterare för WM_SETFOCUS och WM_KILLFOCUS informerar siten om en fokusändring genom att anropa sitens IInputObjectSite::OnFocusChangeIS-metod.
void CDeskBand::OnFocus(const BOOL fFocus)
{
m_fHasFocus = fFocus;
if (m_pSite)
{
m_pSite->OnFocusChangeIS(static_cast<IOleWindow*>(this), m_fHasFocus);
}
}
Bandobjekt ger ett flexibelt och kraftfullt sätt att utöka Internet Explorers funktioner genom att skapa anpassade utforskarfält. Genom att implementera ett skrivbordsband kan du utöka funktionerna i normala fönster. Även om viss COM-programmering krävs, fungerar det i slutändan att tillhandahålla ett underordnat fönster för ditt användargränssnitt. Därifrån kan huvuddelen av implementeringen använda välbekanta Windows-programmeringstekniker. Även om exemplet som beskrivs här bara har begränsade funktioner, illustrerar det alla nödvändiga funktioner i ett bandobjekt och det kan enkelt utökas för att skapa ett unikt och kraftfullt användargränssnitt.