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.
Este artigo aborda tópicos avançados relacionados ao desenvolvimento de controles ActiveX. Estes são, entre outros:
Importante
ActiveX é uma tecnologia herdada que não deve ser usada para novos desenvolvimentos. Para obter mais informações sobre tecnologias modernas que substituem o ActiveX, consulte Controles ActiveX.
Usando classes de banco de dados em controles ActiveX
Como as classes de controle ActiveX fazem parte da biblioteca de classes, você pode aplicar os mesmos procedimentos e regras para usar classes de banco de dados em um aplicativo MFC padrão para desenvolver controles ActiveX que usam as classes de banco de dados MFC.
Para obter uma visão geral das classes de banco de dados MFC, consulte Classes de banco de dados MFC (DAO e ODBC). O artigo apresenta as classes ODBC do MFC e as classes do MFC DAO e direciona você para mais detalhes sobre qualquer uma delas.
Observação
DAO é suportado através do Office 2013. DAO 3.6 é a versão final, e é considerado obsoleto. O ambiente e os assistentes do Visual C++ não oferecem suporte a DAO (embora as classes DAO estejam incluídas e você ainda possa usá-las). A Microsoft recomenda que você use modelos OLE DB ou ODBC e MFC para novos projetos. Você só deve usar o DAO na manutenção de aplicativos existentes.
Implementando uma propriedade parametrizada
Uma propriedade parametrizada (às vezes chamada de matriz de propriedades) é um método para expor uma coleção homogênea de valores como uma única propriedade do controle. Por exemplo, você pode usar uma propriedade parametrizada para expor uma matriz ou um dicionário como uma propriedade. No Visual Basic, essa propriedade é acessada usando notação de matriz:
x = o.Array(2, 3) ' gets element of 2D array
o.Array(2, 3) = 7 ' sets element of 2D array
Use o Assistente de Adição de Propriedades para implementar uma propriedade parametrizada. O Assistente para Adicionar Propriedade implementa a propriedade adicionando um par de funções Get/set que permitem que o usuário de controle acesse a propriedade usando a notação acima ou da maneira padrão.
Semelhante aos métodos e propriedades, as propriedades parametrizadas também têm um limite para o número de parâmetros permitidos. No caso de propriedades parametrizadas, o limite é de 15 parâmetros (com um parâmetro reservado para armazenar o valor da propriedade).
O procedimento a seguir adiciona uma propriedade parametrizada, chamada Array, que pode ser acessada como uma matriz bidimensional de inteiros.
Para adicionar uma propriedade parametrizada usando o Assistente para Adicionar Propriedade
Carregue o projeto do seu controlador.
Na Vista de Classe, expanda o nó da biblioteca do seu controle.
Clique com o botão direito do mouse no nó da interface do seu controle (o segundo nó do nó da biblioteca) para abrir o menu de atalho.
No menu de atalho, clique em Adicionar e, em seguida, clique em Adicionar propriedade.
Na caixa Nome da propriedade , digite
Array.Na caixa Tipo de propriedade , selecione
short.Para Tipo de implementação, clique em Obter/definir métodos.
Nas caixas Obter Função e Definir Função , digite nomes exclusivos para Obter e Definir Funções ou aceite os nomes padrão.
Adicione um parâmetro, chamado row (type short), usando os controles Parameter Name e Parameter Type .
Adicione um segundo parâmetro chamado coluna (digite short).
Clique em Concluir.
Alterações feitas pelo Assistente de Adição de Propriedades
Quando adiciona uma propriedade personalizada, o Assistente para Adicionar Propriedade faz alterações nos ficheiros de cabeçalho da classe de controlo (.H) e nos ficheiros de implementação (.CPP).
As seguintes linhas são adicionadas ao ficheiro da classe de controlo .H:
SHORT GetArray(SHORT row, SHORT column);
void SetArray(SHORT row, SHORT column, SHORT newVal);
Este código declara duas funções chamadas GetArray e SetArray que permitem ao usuário solicitar uma linha e coluna específicas ao acessar a propriedade.
Além disso, o Assistente para Adicionar Propriedade adiciona as seguintes linhas ao mapa de distribuição de controle, localizado na implementação da classe de controle (.CPP):
DISP_PROPERTY_PARAM_ID(CMyAxUICtrl, "Array", dispidArray, GetArray, SetArray, VT_I2, VTS_I2 VTS_I2)
Finalmente, as implementações das funções GetArray e SetArray são adicionadas ao final do arquivo CPP. Na maioria dos casos, você modificará a função Get para retornar o valor da propriedade. A função set geralmente conterá código que deve ser executado, antes ou depois das alterações de propriedade.
Para que essa propriedade seja útil, você pode declarar uma variável de membro de matriz bidimensional na classe de controle, do tipo short, para armazenar valores para a propriedade parametrizada. Em seguida, você pode modificar a função Get para retornar o valor armazenado na linha e coluna apropriadas, conforme indicado pelos parâmetros, e modificar a função set para atualizar o valor referenciado pelos parâmetros de linha e coluna.
Tratando erros no seu controle ActiveX
Se ocorrerem condições de erro no controle, talvez seja necessário relatar o erro para o contêiner de controle. Existem dois métodos para relatar erros, dependendo da situação em que o erro ocorre. Se o erro ocorrer dentro da função Get ou set de uma propriedade, ou dentro da implementação de um método de automação OLE, o controle deve chamar COleControl::ThrowError, que sinaliza ao usuário de controle que ocorreu um erro. Se o erro ocorrer em qualquer outro momento, o controle deve chamar COleControl::FireError, que aciona um evento de erro padrão.
Para indicar o tipo de erro que ocorreu, o controle deve passar um código de erro para ThrowError ou FireError. Um código de erro é um código de status OLE, que tem um valor de 32 bits. Sempre que possível, escolha um código de erro do conjunto padrão de códigos definido no ficheiro de cabeçalho OLECTL.H. A tabela a seguir resume esses códigos.
Códigos de erro do controle ActiveX
| Erro | Descrição |
|---|---|
| CTL_E_ILLEGALFUNCTIONCALL | Chamada de função ilegal |
| CTL_E_OVERFLOW | Transbordo |
| CTL_E_OUTOFMEMORY | Memória esgotada |
| CTL_E_DIVISÃOPORZERO | Divisão por zero |
| CTL_E_OUTOFSTRINGSPACE | Sem espaço para strings |
| Erro: CTL_E_OUTOFSTACKSPACE (sem espaço na pilha) | Sem espaço na pilha |
| CTL_E_BADFILENAMEORNUMBER | Nome ou número de arquivo incorreto |
| CTL_E_FILENOTFOUND | Arquivo não encontrado |
| CTL_E_BADFILEMODE | Modo de arquivo incorreto |
| CTL_E_FICHEIROJÁABERTO | Ficheiro já aberto |
| CTL_E_DEVICEIOERROR | Erro de E/S do dispositivo |
| CTL_E_FILEALREADYEXISTS | O arquivo já existe |
| CTL_E_BADRECORDLENGTH | Comprimento de registo incorreto |
| CTL_E_DISKFULL | Disco cheio |
| Número de Registo Inválido (CTL_E_BADRECORDNUMBER) | Número de registo incorreto |
| Erro de nome de ficheiro inválido (CTL_E_BADFILENAME) | Nome de arquivo incorreto |
| CTL_E_TOOMANYFILES (Erro: Arquivos em excesso) | Demasiados ficheiros |
| CTL_E_DISPOSITIVOINDISPONÍVEL | Dispositivo indisponível |
| CTL_E_GRANTEDENEGADA | Permissão negada |
| CTL_E_DISKNOTREADY (O disco não está pronto) | Disco não pronto |
| CTL_E_PATHFILEACCESSERROR | Erro de acesso ao caminho/arquivo |
| CTL_E_PATHNOTFOUND | Caminho não encontrado |
| CTL_E_STRINGDEPADRÃOINVÁLIDA | Cadeia de caracteres de padrão inválida |
| CTL_ERRO_USOINVÁLIDO_NULL | Uso inválido de NULL |
| CTL_E_INVALIDFILEFORMAT | Formato de ficheiro inválido |
| CTL_E_VALORDAPROPRIEDADEINVÁLIDO | Valor de propriedade inválido |
| CTL_E_INVALIDPROPERTYARRAYINDEX | Índice de matriz de propriedades inválido |
| A configuração não é suportada durante a execução. | Conjunto não suportado em tempo de execução |
| CTL_E_SETNOTSUPPORTED | Definição não suportada (propriedade somente leitura) |
| CTL_E_NEEDPROPERTYARRAYINDEX | Precisa de índice de matriz de propriedades |
| CTL_E_DEFINIÇÃONÃOÉPERMITIDA | Conjunto não permitido |
| CTL_E_ObtencaoNaoSuportadaEmTempoDeExecucao | Não é suportado em tempo de execução |
| CTL_E_GETNÃOÉSUPORTADO | Obtenção não suportada (propriedade de escrita apenas) |
| CTL_E_PROPRIEDADE_NÃO_ENCONTRADA | Propriedade não encontrada |
| CTL_E_INVALIDCLIPBOARDFORMAT | Formato da área de transferência inválido |
| imagem inválida | Imagem inválida |
| CTL_E_PRINTERERROR - Erro na impressora | Erro de impressora |
| CTL_E_CANTSAVEFILETOTEMP | Não é possível salvar o arquivo em TEMP |
| Texto de pesquisa não encontrado (CTL_E_SEARCHTEXTNOTFOUND) | Texto de pesquisa não encontrado |
| CTL_E_REPLACEMENTSTOOLONG | Substituições demasiado longas |
Se necessário, use a macro CUSTOM_CTL_SCODE para definir um código de erro personalizado para uma condição que não é coberta por um dos códigos padrão. O parâmetro para esta macro deve ser um inteiro entre 1000 e 32767, inclusive. Por exemplo:
#define MYCTL_E_SPECIALERROR CUSTOM_CTL_SCODE(1000)
Se você estiver criando um controle ActiveX para substituir um controle VBX existente, defina seus códigos de erro de controle ActiveX com os mesmos valores numéricos que o controle VBX usa para garantir que os códigos de erro sejam compatíveis.
Manuseamento de teclas especiais no comando
Em alguns casos, você pode querer lidar com certas combinações de pressionamento de tecla de uma maneira especial; por exemplo, insira uma nova linha quando a tecla ENTER for pressionada em um controle de caixa de texto de várias linhas ou mova-se entre um grupo de controles de edição quando um ID de tecla direcional for pressionado.
Se a classe base do seu controlo ActiveX for COleControl, poderá sobrepor CWnd::PreTranslateMessage para manipular mensagens antes que o contentor as processe. Ao usar essa técnica, sempre retorne TRUE se você manipular a mensagem em sua substituição de PreTranslateMessage.
O exemplo de código a seguir demonstra uma maneira possível de manipular quaisquer mensagens relacionadas às chaves direcionais.
BOOL CMyAxUICtrl::PreTranslateMessage(MSG* pMsg)
{
BOOL bHandleNow = FALSE;
switch (pMsg->message)
{
case WM_KEYDOWN:
switch (pMsg->wParam)
{
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
bHandleNow = TRUE;
break;
}
if (bHandleNow)
{
OnKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
}
break;
}
return bHandleNow;
}
Para obter mais informações sobre como manipular interfaces de teclado para um controle ActiveX, consulte a documentação do SDK do ActiveX.
Acessando controles de caixa de diálogo que são invisíveis em tempo de execução
Você pode criar controles de diálogo que não têm interface de usuário e são invisíveis em tempo de execução. Se você adicionar um controle ActiveX invisível em tempo de execução a uma caixa de diálogo e usar CWnd::GetDlgItem para acessar o controle, o controle não funcionará corretamente. Em vez disso, você deve usar uma das seguintes técnicas para obter um objeto que representa o controle:
Usando o Assistente para Adicionar Variável de Membro, selecione Variável de Controle e, em seguida, selecione a ID do controle. Insira um nome de variável de membro e selecione a classe wrapper do controle como o Tipo de Controle.
-ou-
Declare uma variável local e uma subclasse como o item de diálogo. Insira um código semelhante ao seguinte (
CMyCtrlé a classe wrapper IDC_MYCTRL1 é a ID do controle):CCirc myCirc; myCirc.SubclassDlgItem(IDC_CIRCCTRL2, this); // ... use myCirc ... myCirc.UnsubclassWindow();