Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
A Barra do Explorer foi introduzida com o Microsoft Internet Explorer 4.0 para fornecer uma área de exibição adjacente ao painel do navegador. É basicamente uma janela filha dentro da janela do Windows Internet Explorer, e pode ser usada para exibir informações e interagir com o usuário da mesma maneira. As Barras do Explorer são mais comumente exibidas como um painel vertical no lado esquerdo do painel do navegador. No entanto, uma Barra do Explorer também pode ser exibida horizontalmente, abaixo do painel do navegador.
Há uma ampla gama de usos possíveis para a Barra do Explorer. Os utilizadores podem selecionar qual opção desejam ver de várias maneiras diferentes, incluindo selecioná-la no sub-menu Barra do Explorer do menu Exibir ou clicar num botão da barra de ferramentas. O Internet Explorer fornece várias Barras do Explorer padrão, incluindo Favoritos e Pesquisa.
Uma das maneiras de personalizar o Internet Explorer é adicionando uma Barra do Explorer personalizada. Quando implementado e registado, será adicionado ao submenu Explorer Bar do menu View. Quando selecionada pelo usuário, a área de exibição da Barra do Explorer pode ser usada para exibir informações e receber a entrada do usuário da mesma forma que uma janela normal.
Para criar uma barra do Explorer personalizada, você deve implementar e registrar um objeto de banda . Os objetos de banda foram introduzidos com a versão 4.71 do Shell e fornecem recursos semelhantes aos das janelas normais. No entanto, como eles são objetos COM (Component Object Model) e contidos pelo Internet Explorer ou pelo Shell, eles são implementados de forma um pouco diferente. Objetos de banda simples foram usados para criar as barras do Explorer de amostra exibidas no primeiro gráfico. A implementação do exemplo de barra vertical do Explorer será discutida em detalhes em uma seção posterior.
Bandas de ferramentas
Um de banda de ferramentas é um objeto de banda que foi introduzido com o Microsoft Internet Explorer 5 para oferecer suporte ao recurso de barra de ferramentas de rádio do Windows. A barra de ferramentas do Internet Explorer é, na verdade, um de controle de vergalhão que contém vários controles de barra de ferramentas . Ao criar uma barra de ferramentas, pode adicionar uma banda a esse controlador de vergalhão. No entanto, como as barras do Explorer, uma faixa de ferramentas é uma janela de uso geral.
Os utilizadores podem exibir uma barra de ferramentas ao selecioná-la no submenu Barras de Ferramentas do menu Ver, ou no menu de atalho que aparece ao clicar com o botão direito do rato na área da barra de ferramentas.
Faixas de mesa
Objetos de banda também podem ser usados para criar bandas de mesa. Embora sua implementação básica seja semelhante às barras do Explorer, as bandas de mesa não estão relacionadas ao Internet Explorer. Uma banda de mesa é basicamente uma maneira de criar uma janela encaixável na área de trabalho. O usuário seleciona-o clicando com o botão direito do mouse na barra de tarefas e selecionando-o no submenu Barras de Ferramentas.
Inicialmente, as bandas de mesa são encaixadas na barra de tarefas.
O usuário pode então arrastar a faixa de mesa para a área de trabalho, e ela aparecerá como uma janela normal.
Implementando objetos de banda
São discutidos os seguintes tópicos.
- Noções Básicas sobre Objetos de Banda
- Inscrição na Banda
- Um exemplo simples de uma barra do Explorer personalizada
Noções básicas sobre objetos de banda
Embora possam ser usados como janelas normais, os objetos de banda são objetos COM que existem dentro de um contêiner. As barras do Explorer são contidas pelo Internet Explorer e as bandas de mesa são contidas pelo Shell. Embora sirvam funções diferentes, a sua implementação básica é muito semelhante. A principal diferença está em como o objeto de banda é registrado, que por sua vez controla o tipo de objeto e seu contêiner. Esta seção discute os aspetos da implementação que são comuns a todos os objetos de banda. Consulte Um exemplo simples de uma barra de explorador personalizada para obter detalhes adicionais de implementação.
Além de IUnknown e IClassFactory, todos os objetos de banda devem implementar as seguintes interfaces.
Além de registrar seu identificador de classe (CLSID), os objetos da barra do Explorer e da banda de mesa também devem ser registrados para a categoria de componente apropriada. O registro da categoria de componente determina o tipo de objeto e seu contêiner. As bandas de ferramentas utilizam um procedimento de registo diferente e não têm um identificador de categoria (CATID). Os CATIDs dos três objetos de banda que os requerem são:
| Tipo de banda | Categoria do componente |
|---|---|
| Barra Exploradora Vertical | CATID_InfoBand |
| Barra do explorador horizontal | CATID_CommBand |
| Banda de secretária | CATID_DeskBand |
Consulte Band Registration para mais discussões sobre como registrar objetos de banda.
Se o objeto de banda tiver de aceitar a entrada do utilizador, deverá também implementar IInputObject. Para adicionar itens ao menu de atalho para a barra do Explorer ou bandas de mesa, o objeto de banda deve exportar IContextMenu. As bandas de ferramentas não suportam menus de atalho.
Como os objetos de banda implementam uma janela filha, eles também devem implementar um procedimento de janela para gerir mensagens do Windows.
Os objetos Band podem enviar comandos para o seu contêiner por meio da interface IOleCommandTarget do contêiner. Para obter o ponteiro da interface, chame o método IInputObjectSite::QueryInterface do contentor e peça por IID_IOleCommandTarget. Em seguida, você envia comandos para o contêiner com IOleCommandTarget::Exec. O grupo de comando é CGID_DeskBand. Quando o método IDeskBand::GetBandInfo de um objeto de banda é chamado, o contêiner usa o parâmetro dwBandID para atribuir ao objeto de banda um identificador que é usado para três dos comandos. São suportados quatro IDs de comando IOleCommandTarget::Exec.
DBID_BANDINFOCHANGED
As informações da banda mudaram. Estabeleça o parâmetro pvaIn como o identificador de banda recebido durante a chamada mais recente de IDeskBand::GetBandInfo. O contêiner chamará o método IDeskBand::GetBandInfo do objeto de banda para solicitar as informações atualizadas.
DBID_MAXIMIZEBAND
Maximize a banda. Configure o parâmetro pvaIn para o identificador de banda recebido na chamada mais recente para IDeskBand::GetBandInfo.
DBID_SHOWONLY
Ative ou desative outras bandas no contentor. Defina o parâmetro pvaIn para o tipo de VT_UNKNOWN com um dos seguintes valores:
Valor Descrição pUnk Um ponteiro para a interface IUnknown do objeto de banda . Todas as outras bandas de mesa estarão escondidas. 0 Oculte todas as barras. 1 Mostrar todas as barras de ferramentas. DBID_PUSHCHEVRON
Versão 5. Exiba um menu de seta. O contêiner envia uma mensagem RB_PUSHCHEVRON e o objeto de banda recebe uma notificação RBN_CHEVRONPUSHED que solicita que ele exiba o menu de chevron. Defina o parâmetro do método IOleCommandTarget::Exec para o identificador de banda recebido na chamada mais recente para IDeskBand::GetBandInfo. Defina o parâmetro pvaIn do método IOleCommandTarget::Exec para o tipo VT_I4 com um valor definido pelo aplicativo. Passa de volta para o objeto de banda como o valor lAppValue da notificação RBN_CHEVRONPUSHED.
Registo de Banda
Um objeto de banda deve ser registado como um servidor OLE em processo que suporta encadeamento por apartamento. O valor padrão para o servidor é uma cadeia de texto de menu. Para Barras do Explorador, aparecerá no submenu Barra do Explorador do menu Exibir Ver do Internet Explorer. Para bandas de ferramentas, ele aparecerá no submenu Barras de Ferramentas do menu Ver do Internet Explorer. Para bandas de mesa, ele aparecerá no submenu Barras de Ferramentas do menu de atalho da barra de tarefas. Tal como acontece com os recursos do menu, colocar um e comercial (&) antes de uma letra provocará que esta seja sublinhada e ativará atalhos de teclado. Por exemplo, a cadeia de caracteres de menu para a barra vertical do Explorer mostrada no primeiro gráfico é "Sample &Vertical Explorer Bar".
Inicialmente, o Internet Explorer recupera uma enumeração dos objetos registrados da barra do Explorer do registro usando as categorias de componentes. Para aumentar o desempenho, ele armazena em cache essa enumeração, fazendo com que as barras do Explorer adicionadas subsequentemente sejam ignoradas. Para forçar o Windows Internet Explorer a reconstruir o cache e reconhecer uma nova Barra do Explorer, exclua as seguintes chaves do Registro durante o registro da nova Barra do Explorer:
Software HKEY_CURRENT_USER\\Microsoft\Windows\CurrentVersion\Explorer\Descartável\PostSetup\Categorias de Componentes\{00021493-0000-0000-C000-000000000046}\Enum
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\\descartáveis PostSetup\categorias de componentes\{00021494-0000-0000-C000-00000000046}\Enum
Observação
Como um cache da Barra do Explorer é criado para cada usuário, seu aplicativo de instalação pode precisar enumerar todas as seções de registro do usuário ou adicionar um stub por usuário para ser executado quando o usuário fizer logon pela primeira vez.
Em geral, a entrada básica do registo para um objeto da barra aparecerá da seguinte maneira.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
(Default) = Menu Text String
InProcServer32
(Default) = DLL Path Name
ThreadingModel = Apartment
As bandas de ferramentas também devem ter o CLSID do objeto registado no Internet Explorer. Para fazer isso, atribua um valor em HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Toolbar nomeado com o GUID CLSID do objeto de banda de ferramentas, conforme mostrado aqui. Seu valor de dados é ignorado, portanto, o tipo de valor não é importante.
HKEY_LOCAL_MACHINE
Software
Microsoft
Internet Explorer
Toolbar
{Your Band Object's CLSID GUID}
Há vários valores opcionais que também podem ser adicionados ao registro. Por exemplo, o seguinte valor é necessário se você quiser usar a barra do Explorer para exibir HTML O valor mostrado não é um exemplo, mas o valor real que deve ser usado.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
Instance
CLSID
(Default) = {4D5C8C2A-D075-11D0-B416-00C04FB90376}
Usado em conjunto com o valor mostrado acima, o seguinte valor opcional também é necessário se você quiser usar a Barra do Explorer para exibir HTML. Esse valor deve ser definido como o local do arquivo que contém o conteúdo HTML para a Barra do Explorer.
HKEY_CLASSES_ROOT
CLSID
{Your Band Object's CLSID GUID}
Instance
InitPropertyBag
Url
Outro valor opcional define a largura ou altura padrão da Barra do Explorer, dependendo se ela é vertical ou horizontal, respectivamente.
HKEY_CURRENT_USER
Software
Microsoft
Internet Explorer
Explorer Bars
{Your Band Object's CLSID GUID}
BarSize
O valor BarSize deve ser definido como a largura ou altura da barra. O valor requer oito bytes e é colocado no registro como um valor binário. Os primeiros quatro bytes especificam o tamanho em pixels, em formato hexadecimal, a partir do byte mais à esquerda. Os últimos quatro bytes são reservados e devem ser definidos como zero.
Como exemplo, as entradas completas do Registro para uma barra do Explorer compatível com HTML com uma largura padrão de 291 (0x123) pixels são mostradas aqui.
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
Você pode manipular o registro do CATID de um objeto de banda programaticamente. Crie um objeto gestor de categorias de componentes (CLSID_StdComponentCategoriesMgr) e solicite um ponteiro para a sua interface ICatRegister. Passe o CLSID e o CATID do objeto de banda para ICatRegister::RegisterClassImplCategories.
Um exemplo simples de uma barra do Explorer personalizada
Este exemplo passa pela implementação da barra vertical do Explorer de exemplo mostrada na introdução.
O procedimento básico para criar uma barra do Explorer personalizada é o seguinte.
- Implementar as funções necessárias para a DLL.
- Implementar as interfaces COM necessárias.
- Implemente quaisquer interfaces COM opcionais desejadas.
- Registre o CLSID do objeto e, se necessário, a categoria do componente.
- Crie uma janela secundária do Internet Explorer, dimensionada para caber na região de exibição da Barra do Explorer.
- Use a subjanela para exibir informações e interagir com o utilizador.
A implementação muito simples usada no exemplo de Barra do Explorer poderia realmente ser usada para qualquer tipo de Barra do Explorer ou uma faixa de mesa, simplesmente registrando-a para a categoria de componente apropriada. Implementações mais sofisticadas precisarão ser personalizadas para a região de exibição e o contêiner de cada tipo de objeto. No entanto, grande parte dessa personalização pode ser realizada pegando o código de exemplo e estendendo-o aplicando técnicas familiares de programação do Windows à janela filho. Por exemplo, você pode adicionar controles para interação do usuário ou gráficos para uma exibição mais avançada.
Funções DLL
Todos os três objetos são empacotados em uma única DLL, que expõe as seguintes funções.
As três primeiras funções são implementações padrão e não serão discutidas aqui. A implementação do Class Factory também é padrão.
Implementações de interface necessárias
O exemplo de barra vertical do Explorer implementa as quatro interfaces necessárias: IUnknown, IObjectWithSite, IPersistStreame IDeskBand como parte da classe CExplorerBar. O construtor, o destruidor e implementações IUnknown são simples e não serão discutidos aqui. Consulte o código de exemplo para obter detalhes.
As interfaces a seguir são discutidas em detalhes.
IObjectWithSite
Quando o utilizador seleciona uma barra do Explorer, o contêiner chama o método IObjectWithSite::SetSite do objeto de banda correspondente. O parâmetro punkSite será definido como o ponteiro IUnknown do site.
Em geral, uma implementação SetSite deve executar as seguintes etapas:
- Liberte qualquer apontador de site que esteja a ser mantido no momento.
- Se o ponteiro passado para SetSite estiver definido como NULL, a banda será removida. SetSite pode retornar S_OK.
- Se o ponteiro passado para SetSite não for NULL, um novo site está a ser definido.
SetSite deve fazer o seguinte:
- Chame QueryInterface no site para sua interfaceIOleWindow.
- Chame IOleWindow::GetWindow para obter o identificador da janela pai. Salve a alça para uso posterior. Libere IOleWindow caso já não seja necessário.
- Crie a janela do objeto de banda como um filho da janela obtida na etapa anterior. Não o crie como uma janela visível.
- Se o objeto de banda implementar IInputObject, chame QueryInterface no site para sua interface IInputObjectSite . Armazene o ponteiro para esta interface para utilização futura.
- Se todas as etapas forem bem-sucedidas, retorne S_OK. Caso contrário, retorne o código de erro definido pelo OLE indicando o que falhou.
O exemplo de barra do Explorer implementa SetSite da seguinte maneira. No código a seguir, m_pSite é uma variável de membro privado que contém o ponteiroIInputObjectSite e m_hwndParent mantém o identificador da janela pai. Neste exemplo, a criação de janelas também é tratada. Se a janela não existir, esse método criará a janela da Barra do Explorer como um filho de tamanho apropriado da janela pai obtida por SetSite. O handle da janela filho é armazenado em 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;
}
A implementação do exemplo GetSite simplesmente envolve uma chamada para o método QueryInterface do site, usando o ponteiro do site guardado por 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
O Internet Explorer chamará a interface IPersistStream da Barra do Explorer para permitir que a Barra do Explorer carregue ou salve dados persistentes. Se não houver dados persistentes, os métodos ainda devem retornar um código de êxito. O interface IPersistStream herda de IPersist, portanto, cinco métodos devem ser implementados.
- IPersist::GetClassID
- IPersistStream::IsDirty
- IPersistStream::Carregar
- IPersistStream::Salvar
- IPersistStream::GetSizeMax
O exemplo de barra do Explorer não usa dados persistentes e tem apenas uma implementação mínima de IPersistStream. IPersist::GetClassID retorna o CLSID (CLSID_SampleExplorerBar) do objeto e o restante retorna S_OK, S_FALSE ou E_NOTIMPL.
IDeskBand
A interface IDeskBand é específica para objetos de banda. Além de seu único método, ele herda de IDockingWindow, que por sua vez herda de IOleWindow.
Há dois métodos IOleWindow: GetWindow e IOleWindow::ContextSensitiveHelp. A implementação de exemplo da Barra de Exploração GetWindow retorna o identificador da janela secundária da Barra de Exploração, m_hwnd. A Ajuda sensível ao contexto não é implementada, portanto, ContextSensitiveHelp retorna E_NOTIMPL.
O IDockingWindow interface tem três métodos.
O método ResizeBorderDW não é usado com nenhum tipo de objeto de banda e deve sempre retornar E_NOTIMPL. O método ShowDW mostra ou oculta a janela da Barra do Explorer, dependendo do valor de seu parâmetro.
STDMETHODIMP CDeskBand::ShowDW(BOOL fShow)
{
if (m_hwnd)
{
ShowWindow(m_hwnd, fShow ? SW_SHOW : SW_HIDE);
}
return S_OK;
}
O métodoCloseDW destrói a janela da Barra do Explorer.
STDMETHODIMP CDeskBand::CloseDW(DWORD)
{
if (m_hwnd)
{
ShowWindow(m_hwnd, SW_HIDE);
DestroyWindow(m_hwnd);
m_hwnd = NULL;
}
return S_OK;
}
O método restante, GetBandInfo, é específico para IDeskBand. O Internet Explorer usa-o para especificar o identificador e o modo de visualização da Barra do Explorer. O Internet Explorer também pode solicitar uma ou mais informações da Barra do Explorador preenchendo o membro dwMask da estrutura DESKBANDINFO que é passada como o terceiro parâmetro. GetBandInfo deve armazenar o identificador e o modo de visualização e preencher a estrutura de dados DESKBANDINFO com os dados solicitados. O exemplo de barra do Explorer implementa GetBandInfo, conforme mostrado no exemplo de código a seguir.
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;
}
Implementações de interface opcionais
Há duas interfaces que não são necessárias, mas que podem ser úteis para implementar: IInputObject e IContextMenu. O exemplo de Explorer Bar implementa IInputObject. Consulte a documentação para obter informações sobre como implementar IContextMenu.
IInputObject
A interface IInputObject deve ser implementada se um objeto de barra aceitar a entrada do usuário. O Internet Explorer implementa IInputObjectSite e usa IInputObject para manter o foco de entrada do utilizador adequado quando tem mais de uma janela incluída. Há três métodos que precisam ser implementados por uma barra do Explorer.
O Internet Explorer chama UIActivateIO para informar a Barra do Explorer de que ele está sendo ativado ou desativado. Quando ativado, o exemplo de Barra do Explorer chama SetFocus para definir o foco para sua janela.
O Internet Explorer chama HasFocusIO quando está tentando determinar qual janela tem foco. Se a janela da Barra do Explorer ou de um dos seus descendentes tiver foco, HasFocusIO deverá retornar S_OK. Caso contrário, deve retornar S_FALSE.
TranslateAcceleratorIO permite que o objeto processe aceleradores de teclado. O exemplo de barra do Explorer não implementa esse método, portanto, ele retorna S_FALSE.
A implementação da barra de exemplo de IInputObjectSite é a seguinte.
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;
};
Registo CLSID
Como em todos os objetos COM, o CLSID da Barra do Explorer deve ser registrado. Para que o objeto funcione corretamente com o Internet Explorer, ele também deve ser registrado para a categoria de componente apropriada (CATID_InfoBand). A seção de código relevante para a barra do Explorer é mostrada no exemplo de código a seguir.
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;
}
O registro de objetos de banda na amostra usa procedimentos COM normais.
Além do CLSID, o servidor de objeto de banda também deve ser registrado para uma ou mais categorias de componentes. Esta é, na verdade, a principal diferença na implementação entre os exemplos verticais e horizontais da Barra do Explorer. Esse processo é manipulado criando um objeto gerenciador de categorias de componentes (CLSID_StdComponentCategoriesMgr) e usando o ICatRegister::RegisterClassImplCategories método para registrar o servidor de objeto de banda. Neste exemplo, o registro de categoria de componente é tratado passando o CLSID e o CATID do exemplo da Barra do Explorer para uma função privada —RegisterComCat— conforme mostrado no exemplo de código a seguir.
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;
}
O procedimento da janela
Como um objeto de banda usa uma janela filha para sua exibição, ele deve implementar um procedimento de janela para lidar com mensagens do Windows. O exemplo de banda tem funcionalidade mínima, portanto, seu procedimento de janela lida apenas com cinco mensagens:
O procedimento pode ser facilmente expandido para acomodar mensagens adicionais para suportar mais recursos.
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;
}
O manipulador de WM_COMMAND simplesmente retorna zero. O manipulador de WM_PAINT cria a exibição de texto simples mostrada no exemplo da Barra do Explorer na introdução.
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);
}
}
Os manipuladores de WM_SETFOCUS e WM_KILLFOCUS informam o site de uma alteração de foco chamando o do site IInputObjectSite::OnFocusChangeIS método.
void CDeskBand::OnFocus(const BOOL fFocus)
{
m_fHasFocus = fFocus;
if (m_pSite)
{
m_pSite->OnFocusChangeIS(static_cast<IOleWindow*>(this), m_fHasFocus);
}
}
Os objetos Band fornecem uma maneira flexível e poderosa de estender os recursos do Internet Explorer criando barras do Explorer personalizadas. Implementar uma barra de ferramentas permite-lhe expandir as capacidades das janelas normais. Embora alguma programação COM seja necessária, ela serve para fornecer uma janela filha para a sua interface de utilizador. A partir daí, a maior parte da implementação pode usar técnicas de programação familiares do Windows. Embora o exemplo discutido aqui tenha apenas funcionalidade limitada, ele ilustra todos os recursos necessários de um objeto de banda e pode ser prontamente estendido para criar uma interface de usuário única e poderosa.