TN014: Controles personalizados.
Esta nota descreve o suporte a MFC para controles personalizados e self-desenho.Ele também descreve a subclassificação dinâmica e descreve o Relação entre CWnd objetos de e HWNDs.
O aplicativo de exemplo MFC CTRLTEST ilustra como usar vários controles personalizados.Consulte o código-fonte para o MFC geral amostra CTRLTEST e ajuda online.
Controles/menus de desenho proprietário
Windows oferece suporte para menus e controles proprietário-draw usando mensagens do Windows.A janela pai de qualquer controle ou o menu recebe essas mensagens e chamadas de funções em resposta.Você pode substituir essas funções para personalizar a aparência e comportamento do seu menu ou controle de desenho proprietário.
MFC proprietário-draw suporta diretamente com as seguintes funções:
Você pode substituir essas funções em seu CWnd classe derivada para implementar personalizado desenhar comportamento.
Essa abordagem não levar a códigos reutilizáveis.Se você tiver dois controles semelhantes em dois diferentes CWnd classes, você deve implementar o comportamento do controle personalizado em dois locais. A arquitetura suportada MFC self-desenho controle resolve esse problema.
Self-Draw menus e controles
MFC fornece uma implementação padrão (no CWnd e CMenu classes) para as mensagens padrão de desenho proprietário.Esta implementação padrão será decodificar os parâmetros de desenho proprietário e delegue as mensagens de desenho proprietário para os controles ou menu.Isso é chamado self-draw porque o código do desenho está na classe do controle ou menu, não na janela do proprietário.
Usando controles self-draw você pode criar classes de controle reutilizável que usar semântica de desenho proprietário para exibir o controle.O código para desenhar o controle é da classe de controle, não seu pai.Isso é uma abordagem orientada a objeto para a programação de controle personalizado.Adicionar a lista seguinte das funções às classes self-draw:
Para botões self-draw:
CButton:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this button
Para menus self-draw:
CMenu:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this menu CMenu:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this menu
Para caixas de listagem self-draw:
CListBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this list box CListBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this list box CListBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this list box if LBS_SORT CListBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this list box
Para caixas de combinação self-draw:
CComboBox:MeasureItem(LPMEASUREITEMSTRUCT); // insert code to measure the size of an item in this combo box CComboBox:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw an item in this combo box CComboBox:CompareItem(LPCOMPAREITEMSTRUCT); // insert code to compare two items in this combo box if CBS_SORT CComboBox:DeleteItem(LPDELETEITEMSTRUCT); // insert code to delete an item from this combo box
Para obter detalhes sobre as estruturas proprietário-draw (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT, and DELETEITEMSTRUCT) Consulte a documentação do MFC para CWnd::OnDrawItem, CWnd::OnMeasureItem, CWnd::OnCompareItem, e CWnd::OnDeleteItem respectivamente.
Usando controles self-draw e menus
Para menus self-draw, você deve substituir o OnMeasureItem e OnDrawItem métodos.
Para self-draw lista caixas e caixas de combinação, você deve substituir OnMeasureItem e OnDrawItem. Você deve especificar o LBS_OWNERDRAWVARIABLE estilo para lista caixas ou CBS_OWNERDRAWVARIABLE estilo de caixas de combinação no modelo de caixa de diálogo. The OWNERDRAWFIXED estilo não funcionará com itens self-draw porque altura fixa de item é determinada antes que controles self-draw ao lista caixa. (Você pode usar os métodos CListBox::SetItemHeight e CComboBox::SetItemHeight para superar essa limitação.)
Alternar para um OWNERDRAWVARIABLE estilo forçará o sistema para aplicar a NOINTEGRALHEIGHT estilo para o controle. Porque o controle não pode calcular uma altura integral com itens de tamanho variáveis, o estilo padrão de INTEGRALHEIGHT é ignorado e o controle é sempre NOINTEGRALHEIGHT. Se os itens forem corrigidos altura, você pode evitar que itens parcial que está sendo desenhado, especificando o dimensionar do controle como um multiplicador de inteiro do dimensionar do item.
Para self-desenho lista caixas e caixas de combinação com o LBS_SORT ou CBS_SORT estilo, você deve substituir o OnCompareItem método.
Para self-desenho lista caixas e caixas de combinação, OnDeleteItem não é geralmente substituído. Você pode substituir OnDeleteItem Se você quiser realizar qualquer processamento especial. Um caso onde isso seria aplicável é quando a memória adicional ou outros recursos são armazenados com cada lista item da caixa de combinação ou caixa.
Exemplos de Self-desenho Menus e controles
O exemplo de MFC geral CTRLTEST fornece exemplos de um menu self-draw e uma caixa de listagem self-draw.
O exemplo mais comum de um botão self-desenho é um botão de bitmap.Um botão de bitmap é um botão que mostra um, dois ou três imagens de bitmap para os diferentes estados.Um exemplo disso é fornecido no MFC classe CBitmapButton.
Subclassing dinâmico
Ocasionalmente, você deverá alterar a funcionalidade de um objeto que já existe.Os exemplos anteriores necessário personalizar os controles antes de terem sido criados.Subclassificação dinâmica permite personalizar um controle que já foi criado.
Subclassificação é o termo Windows para substituir o WndProc de uma janela com um personalizado WndProc e chamando o antigo WndProc para a funcionalidade padrão.
Não deve ser confundido com derivação de classe do C++.Para fins de esclarecimento, o C++ termos classe base and classe derivada são análogos aos superclasse and subclasse no modelo de objeto do Windows.Derivação de C++ com subclassificação MFC e do Windows são funcionalmente semelhantes, exceto C++ não dá suporte a subclassificação dinâmica.
The CWnd classe fornece a conexão entre um objeto C++ (derivado de CWnd) e um objeto de janela do Windows (conhecido sistema autônomo um HWND).
Há três maneiras comuns que eles estão relacionados:
CWnd cria o HWND. Você pode modificar o comportamento em uma classe derivada, criando uma classe derivada de CWnd. The HWND é criado quando o aplicativo chama CWnd::criar.
O aplicativo anexa um CWnd para um existente HWND. O comportamento de janela existente não é modificado.Este é um caso de delegação e é possibilitado pela chamada CWnd::anexar ao alias existente HWND para um CWnd objeto.
CWnd anexado a um existente HWND e você pode modificar o comportamento em uma classe derivada. Isso é chamado de subclassificação porque estamos alterando o comportamento e, portanto, a classe, de um objeto do Windows em time de execução dinâmico.
Você pode obter subclassificação dinâmica usando os métodos CWnd::SubclassWindow eCWnd::SubclassDlgItem.
Ambas as rotinas de anexar um CWnd objeto para um existente HWND. SubclassWindow leva a HWND diretamente. SubclassDlgItem é uma função auxiliar que leva a uma ID de controle e a janela pai. SubclassDlgItem destina-se anexar objetos C++ a controles de caixa de diálogo criados a partir de um modelo de caixa de diálogo.
Consulte o CTRLTEST exemplo vários exemplos de quando usar SubclassWindow e SubclassDlgItem.