Alternativas à anotação dinâmica
Há outras maneiras de fornecer suporte personalizado ao IAccessible para elementos de interface do usuário e, em alguns casos, eles são a solução correta. Antes da Anotação Dinâmica, essas técnicas alternativas eram as únicas opções disponíveis para os desenvolvedores. Eles incluem a implementação de toda a interface IAccessible e técnicas programáticas.
Implementando toda a interface IAccessible
Uma técnica alternativa é implementar toda a interface IAccessible . Essa abordagem geralmente é necessária para controles personalizados ou elementos de interface do usuário radicalmente diferentes; no entanto, os custos de desenvolvimento e teste são significativos o suficiente para serem evitados, a menos que seja realmente necessário. Se o objetivo for modificar uma única propriedade, o custo será difícil de justificar.
Técnicas programáticas
Outra opção é usar técnicas de subclasse e encapsulamento para modificar as informações que estão sendo expostas para uma propriedade específica. Essa é a técnica que a Anotação Dinâmica se destina a substituir. Para substituir uma única propriedade usando subclasse e encapsulamento, o desenvolvedor deve executar as seguintes etapas:
- Subclasse o HWND do objeto IAccessible .
- Intercepte a mensagem WM_GETOBJECT para o valor correto de IParam/OBJID.
- Encaminhe a mensagem WM_GETOBJECT para a classe base usando a função de retorno de chamada CallWndProc . Se zero for retornado, chame CreateStdAccessibleObject; caso contrário, chame LresultFromObject no valor retornado para obter o ponteiro de interface IAccessible nativo do controle.
- Crie uma classe wrapper, que implementa IAccessible e encapsula o ponteiro de interface IAccessible retornado da etapa anterior. Essa classe wrapper envia todos os métodos e propriedades para o ponteiro de interface IAccessible original, exceto aqueles que devem ser substituídos. Isso envolve escrever código de encaminhamento para todas as 21 propriedades e métodos da interface IAccessible , independentemente de quantos são realmente substituídos.
Além disso, os desenvolvedores devem verificar as seguintes condições:
- O método ou a propriedade substituído só deve manipular as IDs filho necessárias e encaminhar todas as outras para o ponteiro de interface IAccessible original.
- O encapsulamento também deve encaminhar interfaces IEnumVARIANT e IOleWindow somente se o objeto original der suporte a elas.
- A contagem de referências deve ser tratada corretamente, especialmente se houver suporte para outras interfaces.
- Os valores retornados de IDispatch devem ser tratados corretamente, especialmente com o método ITypeInfo::Invoke, que deve ser chamado com um ponteiro de interface para a interface wrapper, não um ponteiro para a interface IAccessible original.
Essas técnicas exigem uma quantidade considerável de trabalho, mesmo que apenas uma ou duas propriedades precisem ser substituídas. A maioria do código resultante está preocupada com subclasse e encapsulamento, e apenas uma pequena fração está realmente fornecendo as informações substituídas.
No entanto, há cenários em que essas técnicas são necessárias. Por exemplo, se você estiver fazendo alterações estruturais para criar um elemento de interface do usuário de espaço reservado, deverá usar essas técnicas em vez de Anotação Dinâmica.
Corrigindo nomes derivados de rótulos
Alguns controles comuns do Microsoft Win32, como o controle de caixa de edição, são quase sempre usados com um rótulo (uma entrada LTEXT no arquivo de recurso) ou uma caixa de grupo (GROUPBOX no arquivo de recursos). A Acessibilidade Ativa da Microsoft deriva automaticamente a propriedade name do controle de seu rótulo. Para esses controles, o texto da janela (mostrado no Microsoft Visual Studio como a propriedade Name ou ID) é ignorado, pois geralmente é gerado automaticamente e raramente é muito descritivo; por exemplo, "IDC_EDIT1".
Se a interface do usuário do aplicativo não for projetada corretamente, a Acessibilidade Ativa da Microsoft poderá não ser capaz de definir o nome corretamente. Para ser associado a um controle, a caixa de rótulo ou grupo deve ser colocada imediatamente antes do controle dinâmico na ordem de tabulação.
A ordem de tabulação pode ser alterada usando a ferramenta no Visual Studio (no menu Formatar quando o editor de recursos está aberto) ou editando diretamente o arquivo de recurso.
O exemplo a seguir mostra a descrição de um arquivo de recurso de uma caixa de diálogo que contém duas caixas de edição rotuladas.
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
LTEXT "First Name:",IDC_STATIC,8,16,43,8
LTEXT "Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
END
Neste exemplo, os rótulos e controles não estão listados na ordem de tabulação correta. Como resultado, a Acessibilidade Ativa da Microsoft atribui o nome "Sobrenome" à caixa de edição de nome e nenhum nome à caixa de edição de sobrenome.
O exemplo a seguir mostra a listagem de recursos correta. Observe também que as teclas de atalho foram designadas nos rótulos.
IDD_INPUTNAME DIALOGEX 22, 17, 312, 118
STYLE DS_SETFONT | DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
CAPTION "Enter your name"
FONT 8, "System", 0, 0, 0x0
BEGIN
LTEXT "&First Name:",IDC_STATIC,8,16,43,8
EDITTEXT IDC_EDITFIRSTNAME,53,15,120,12,ES_AUTOHSCROLL
LTEXT "&Last Name:",IDC_STATIC,8,33,43,8
EDITTEXT IDC_EDITLASTNAME,53,34,120,12,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,179,35,30,11,WS_GROUP
END
Quando os controles têm rótulos suplementares, como para valores mínimos e máximos em uma barra de controle, esses rótulos devem ser colocados após o controle na ordem de tabulação. O rótulo main do controle deve aparecer imediatamente antes do próprio controle.
Controles de nomenclatura sem rótulos
Nem sempre é possível ou desejável ter um rótulo visível para cada controle. No entanto, você ainda pode fornecer um nome para o controle adicionando um rótulo invisível. Como sempre, o rótulo invisível deve preceder imediatamente o controle na ordem de tabulação.
Se você estiver usando o Editor de Recursos no Microsoft Visual Studio .NET, poderá definir a propriedade Visible como False. Para tornar o rótulo invisível ao editar o arquivo de recurso (.rc), adicione NOT WS_VISIBLE ou à parte de estilo do controle de rótulo, conforme mostrado no exemplo a seguir.
LTEXT "&FullName:",IDC_STATIC,111,23,44,8,NOT WS_VISIBLE
Observe que qualquer tecla de atalho designada funciona mesmo que o rótulo seja invisível.