Implementando o objeto COM da página de propriedades
Uma extensão de folha de propriedades é um objeto COM implementado como um servidor in-proc. A extensão da folha de propriedades deve implementar as interfaces IShellExtInit e IShellPropSheetExt. Uma extensão de folha de propriedades é instanciada quando o usuário exibe a folha de propriedades de um objeto de uma classe para o qual a extensão de folha de propriedades foi registrada no especificador de exibição da classe.
- Implementando IShellExtInit
- Implementando IShellPropSheetExt
- Passando o objeto de extensão para a página de propriedades
- Trabalhando com o objeto de notificação
- Diversos
- Folhas de propriedades de seleção múltipla
- Novo com o Windows Server 2003
- Tópicos relacionados
Implementando IShellExtInit
Depois que o objeto COM de extensão de folha de propriedades é instanciado, o método IShellExtInit::Initialize é chamado. IShellExtInit::Initialize fornece a extensão da folha de propriedades com um objeto IDataObject que contém dados que pertencem ao objeto de diretório que a folha de propriedades aplica.
O IDataObject contém dados no formato CFSTR_DSOBJECTNAMES. O formato de dados CFSTR_DSOBJECTNAMES é um HGLOBAL que contém uma estrutura DSOBJECTNAMES . A estrutura DSOBJECTNAMES contém dados de objeto de diretório que a extensão de folha de propriedades aplica.
O IDataObject também contém dados no formato CFSTR_DS_DISPLAY_SPEC_OPTIONS. O formato de dados CFSTR_DS_DISPLAY_SPEC_OPTIONS é um HGLOBAL que contém uma estrutura DSDISPLAYSPECOPTIONS . O DSDISPLAYSPECOPTIONS contém dados de configuração para uso pela extensão.
Se qualquer valor diferente de S_OK for retornado de IShellExtInit::Initialize, a folha de propriedades não será exibida.
Os parâmetros pidlFolder e hkeyProgID do método IShellExtInit::Initialize não são usados.
O ponteiro IDataObject pode ser salvo pela extensão incrementando a contagem de referência do IDataObject. Essa interface deve ser liberada quando não for mais necessária.
Implementando IShellPropSheetExt
Após IShellExtInit::Initialize retorna, o IShellPropSheetExt::AddPages método é chamado. A extensão da folha de propriedades deve adicionar a página ou páginas durante esse método. Uma página de propriedades é criada preenchendo uma estrutura PROPSHEETPAGE e, em seguida, passando essa estrutura para a função CreatePropertySheetPage. A página de propriedades é adicionada à folha de propriedades chamando a função de retorno de chamada passada para IShellPropSheetExt::AddPages no parâmetro lpfnAddPage.
Se qualquer valor diferente de S_OK for retornado de IShellPropSheetExt::AddPages, a folha de propriedades não será exibida.
Se a extensão da folha de propriedades não for necessária para adicionar páginas à folha de propriedades, ela não deverá chamar a função de retorno de chamada passada para IShellPropSheetExt::AddPages no parâmetro lpfnAddPage.
O método IShellPropSheetExt::ReplacePage não é usado.
Passando o objeto de extensão para a página de propriedades
O objeto de extensão da folha de propriedades é independente da página de propriedades. Em muitos casos, é desejável poder usar o objeto de extensão, ou algum outro objeto, a partir da página de propriedades. Para fazer isso, defina o membro lParam da estrutura PROPSHEETPAGE para o ponteiro do objeto. A página de propriedades pode recuperar esse valor quando processa a mensagem WM_INITDIALOG. Para uma página de propriedades, o parâmetro lParam da mensagem WM_INITDIALOG é um ponteiro para a estrutura PROPSHEETPAGE. Recupere o ponteiro do objeto convertendo o lParam da mensagem WM_INITDIALOG em um ponteiro PROPSHEETPAGE e, em seguida, recuperando o membro lParam da estrutura PROPSHEETPAGE.
O exemplo de código C++ a seguir mostra como passar um objeto para uma página de propriedades.
case WM_INITDIALOG:
{
LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;
if(NULL != pPage)
{
CPropSheetExt *pPropSheetExt;
pPropSheetExt = (CPropSheetExt*)pPage->lParam;
if(pPropSheetExt)
{
return pPropSheetExt>OnInitDialog(wParam, lParam);
}
}
}
break;
Lembre-se de que, depois que IShellPropSheetExt::AddPages for chamado, a folha de propriedades liberará o objeto de extensão da folha de propriedades e nunca mais o usará. Isso significa que o objeto de extensão seria excluído antes que a página de propriedades fosse exibida. Quando a página tenta acessar o ponteiro do objeto, a memória terá sido liberada e o ponteiro não será válido. Para corrigir isso, incremente a contagem de referência para o objeto de extensão quando a página for adicionada e, em seguida, libere o objeto quando a caixa de diálogo da página de propriedades for destruída. Isso cria outro problema porque a caixa de diálogo da página de propriedades não é criada até a primeira vez que a página é exibida. Se o usuário nunca selecionar a página de extensão, a página nunca será criada e destruída. Isso faz com que o objeto de extensão nunca seja liberado, portanto, ocorre um vazamento de memória. Para evitar isso, implemente uma função de retorno de chamada de página de propriedades. Para fazer isso, adicione o sinalizador PSP_USECALLBACK ao membro dwFlags da estrutura PROPSHEETPAGE e defina o membro pfnCallback da estrutura PROPSHEETPAGE para o endereço da função PropSheetPageProc implementada. Quando a função PropSheetPageProc recebe a notificação PSPCB_RELEASE, o parâmetro ppsp do PropSheetPageProc contém um ponteiro para a estrutura PROPSHEETPAGE. O membro lParam da estrutura PROPSHEETPAGE contém o ponteiro de extensão que pode ser usado para liberar o objeto.
O exemplo de código C++ a seguir mostra como liberar um objeto de extensão.
UINT CALLBACK CPropSheetExt::PageCallbackProc( HWND hWnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
switch(uMsg)
{
case PSPCB_CREATE:
// Must return TRUE to enable the page to be created.
return TRUE;
case PSPCB_RELEASE:
{
/*
Release the object. This is called even if the page dialog box was
never actually created.
*/
CPropSheetExt *pPropSheetExt = (CPropSheetExt*)ppsp->lParam;
if(pPropSheetExt)
{
pPropSheetExt->Release();
}
}
break;
}
return FALSE;
}
Trabalhando com o objeto de notificação
Como as páginas de extensão da folha de propriedades são exibidas dentro de uma folha de propriedades criada por um componente desconhecido para a extensão, é necessário usar um "gerente" para manipular a transferência de dados entre as páginas de extensão e a folha de propriedades. Esse "gerente" é chamado de objeto de notificação. O objeto de notificação opera como um moderador entre as páginas individuais e a folha de propriedades.
Quando o objeto de extensão da folha de propriedades é inicializado, a extensão deve criar um objeto de notificação chamando ADsPropCreateNotifyObj, passando o IDataObject obtido de IShellExtInit::Initialize e o nome do objeto de diretório. Não é necessário incrementar a contagem de referência da interface IDataObject, porque o objeto de notificação criado pela função ADsPropCreateNotifyObj fará isso. O identificador de objeto de notificação fornecido por ADsPropCreateNotifyObj deve ser salvo para uso posterior. ADsPropCreateNotifyObj pode ser chamado durante IShellExtInit::Initialize ou IShellPropSheetExt::AddPages. Quando a extensão da folha de propriedades é desligada, ela deve enviar uma mensagem de WM_ADSPROP_NOTIFY_EXIT para o objeto de notificação. Isso faz com que o objeto de notificação se destrua. Isso é melhor feito quando a função PropSheetPageProc recebe a notificação PSPCB_RELEASE.
A extensão da folha de propriedades pode obter dados além daqueles fornecidos pelo formato da área de transferência CFSTR_DSOBJECTNAMES chamando ADsPropGetInitInfo. Uma das vantagens de usar ADsPropGetInitInfo é que ele fornece um objeto IDirectoryObject usado para trabalhar programaticamente com o objeto de diretório.
Observação
Ao contrário da maioria dos métodos e funções COM, ADsPropGetInitInfo não incrementa a contagem de referência para o objeto IDirectoryObject. O IDirectoryObject não deve ser liberado a menos que a contagem de referência seja incrementada manualmente primeiro.
Quando a página de propriedades é criada pela primeira vez, a extensão deve registrar a página com o objeto de notificação chamando ADsPropSetHwnd com o identificador de janela da página.
ADsPropCheckIfWritable é uma função de utilitário que a extensão da folha de propriedades pode usar para determinar se uma propriedade pode ser gravada.
Diversos
O identificador da página de propriedades é passado para o procedimento da caixa de diálogo da página. A folha de propriedades é o pai direto da página de propriedades, portanto, o identificador da folha de propriedades pode ser obtido chamando a função GetParent com o identificador da página de propriedades.
Quando o conteúdo da página de extensão é alterado, a extensão deve usar a macro PropSheet_Changed para notificar a folha de propriedades sobre alterações. A folha de propriedades habilitará o botão Aplicar.
Folhas de propriedades de seleção múltipla
Com o Windows Server 2003 e sistemas operacionais posteriores, os snap-ins do MMC administrativo do Active Directory oferecem suporte a extensões de folha de propriedades para vários objetos de diretório. Essas folhas de propriedades são exibidas quando as propriedades são exibidas para mais de um item por vez. A principal diferença entre uma extensão de folha de propriedades de seleção única e uma extensão de folha de propriedades de seleção múltipla é que a estrutura DSOBJECTNAMES fornecida pelo formato de área de transferência CFSTR_DSOBJECTNAMES em IShellExtInit::Initialize conterá mais de uma estrutura DSOBJECT.
Quando o objeto de notificação é criado, uma extensão de folha de propriedades de seleção múltipla deve passar um nome exclusivo fornecido pelo snap-in em vez de um nome criado pela extensão. Para obter o nome exclusivo, solicite o formato da área de transferência CFSTR_DS_MULTISELECTPROPPAGE do IDataObject obtido de IShellExtInit::Initialize. Esses dados são um HGLOBAL que contém uma cadeia de caracteres Unicode terminada em nulo que é o nome exclusivo. Esse nome exclusivo é então passado para a função ADsPropCreateNotifyObj para criar o objeto de notificação. A função de exemplo CreateADsNotificationObject em Código de exemplo para implementação do objeto COM da folha de propriedades demonstra como fazer isso corretamente, além de ser compatível com versões anteriores do snap-in que não oferecem suporte a folhas de propriedades de seleção múltipla.
Para folhas de propriedades de seleção múltipla, o sistema só se vincula ao primeiro objeto na matriz DSOBJECT . Devido a isso, ADsPropGetInitInfo fornece apenas os atributos IDirectoryObject e gravável para o primeiro objeto na matriz. Os outros objetos na matriz não estão vinculados.
Uma extensão de folha de propriedades de seleção múltipla é registrada sob o atributo adminMultiselectPropertyPages.
Novo com o Windows Server 2003
Os recursos a seguir são novos no Windows Server 2003.
Se a página de propriedades encontrar um erro, ADsPropSendErrorMessage pode ser chamado com os dados de erro apropriados. ADsPropSendErrorMessage armazenará todas as mensagens de erro em uma fila. Essas mensagens serão exibidas na próxima vez que ADsPropShowErrorDialog for chamado. Quando ADsPropShowErrorDialog retorna, as mensagens enfileiradas são excluídas.
O Windows Server 2003 apresenta a função ADsPropSetHwndWithTitle. Esta função é semelhante a ADsPropSetHwnd, mas inclui o título da página. Isso permite que a caixa de diálogo de erro exibida por ADsPropShowErrorDialog forneça dados mais úteis ao usuário. Se a extensão da folha de propriedades usar a função ADsPropShowErrorDialog, a extensão deverá usar ADsPropSetHwndWithTitle em vez de ADsPropSetHwnd.
Tópicos relacionados