TN014: Controles de personalizados
Esta anotação descreve o suporte do MFC para controles personalizados e self-drawing.Ele também descreve dinâmica subclassificação e descreve a relação entre CWnd objetos e HWNDs.
O aplicativo de exemplo do MFC CTRLTEST ilustra como usar vários controles personalizados.Consulte o código fonte de exemplo MFC geral CTRLTEST e ajuda on-line.
Controles/Menus de desenho proprietário
Windows fornece suporte para menus e controles de desenho proprietário usando mensagens do Windows.A janela pai de qualquer controle ou menu recebe essas funções de chamadas e mensagens de resposta.Você pode substituir essas funções para personalizar a aparência e o comportamento de controle owner-draw ou no menu.
MFC diretamente suporta desenho proprietário com as seguintes funções:
Você pode substituir essas funções em seu CWnd classe para implementar comportamento personalizado desenhar derivada.
Essa abordagem não resultar em código reutilizável.Se você tiver dois controles semelhantes em duas diferentes CWnd classes, você deve implementar o comportamento do controle personalizado em dois locais.A arquitetura de controle self-drawing suporte para MFC resolve esse problema.
Menus e controles self-Draw
MFC fornece uma implementação padrão (na CWnd e CMenu classes) para as mensagens padrão de desenho proprietário.Esta implementação padrão irá decodificar os parâmetros de desenho proprietário e delegar as mensagens controles ou menu de desenho proprietário.Isso é chamado self-draw porque o código do desenho está na classe de controle ou menu, não na janela do proprietário.
Usando controles de self-draw você pode criar classes de controle reutilizável usam semântica de desenho proprietário para exibir o controle.O código para desenhar o controle está na classe de controle, não seu pai.Esta é uma abordagem orientada a objeto de programação de controle personalizado.Adicione a seguinte lista de funções para as classes self-draw:
Para botões de self-draw:
CButton:DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this button
Para menus de 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 de desenho proprietário (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT, e DELETEITEMSTRUCT) consulte a documentação do MFC para CWnd::OnDrawItem, CWnd::OnMeasureItem, CWnd::OnCompareItem, e CWnd::OnDeleteItem respectivamente.
Usando menus e controles self-draw
Para menus de self-draw, você deve substituir o OnMeasureItem e OnDrawItem métodos.
Para caixas de combinação e caixas de listagem self-draw, você deve substituir OnMeasureItem e OnDrawItem.Você deve especificar o LBS_OWNERDRAWVARIABLE o estilo das caixas de listagem ou CBS_OWNERDRAWVARIABLE estilo para combinação caixas no modelo de caixa de diálogo.O OWNERDRAWFIXED estilo não funcionará com itens self-draw porque a altura do item fixo é determinada antes de self-draw controles à caixa de listagem.(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 o NOINTEGRALHEIGHT estilo de controle.Porque o controle não pode calcular uma altura integral com tamanho variável de itens, o estilo padrão de INTEGRALHEIGHT será ignorado e o controle é sempre NOINTEGRALHEIGHT.Se os itens são fixos altura, você pode impedir itens parciais sendo desenhada, especificando o tamanho do controle como um multiplicador de inteiro do tamanho do item.
Para self-drawing caixas de listagem e caixas de combinação com o LBS_SORT ou CBS_SORT estilo, você deve substituir o OnCompareItem método.
Para self-drawing caixas de listagem e caixas de combinação, OnDeleteItem não é geralmente substituído.Você pode substituir OnDeleteItem se você quiser executar qualquer processamento especial.Um caso onde isso seria aplicável é quando memória adicional ou outros recursos são armazenados com cada item de caixa de combinação ou de caixa de lista.
Exemplos de Self-Drawing Menus e controles
O exemplo MFC geral CTRLTEST fornece exemplos de um menu de self-draw e uma caixa de listagem self-draw.
O exemplo mais comum de um botão de self-drawing é um botão de bitmap.Um botão de bitmap é um botão que mostra imagens de bitmap de um, dois ou três estados diferentes.Um exemplo é fornecido na classe MFC CBitmapButton.
Dinâmica subclassificação
Ocasionalmente, você poderá alterar a funcionalidade de um objeto que já existe.Os exemplos anteriores necessárias personalizar os controles antes que eles foram criados.Dinâmica subclassificação 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, os termos de C++ classe base e classe derivada são análogos aos superclasse e subclasse no modelo de objeto do Windows.Derivação de C++ com subclassificação MFC e Windows são funcionalmente semelhantes, exceto C++ não dá suporte dinâmica subclassificação.
O CWnd classe fornece a conexão entre um objeto C++ (derivado de CWnd) e um objeto de janela do Windows (conhecido como um HWND).
Há três maneiras comuns que eles estão relacionados:
CWndcria o HWND.Você pode modificar o comportamento em uma classe derivada, criando uma classe derivada de CWnd.O HWND é criado quando o aplicativo chama CWnd::Create.
A aplicativo anexa um CWnd a um HWND.O comportamento da janela existente não é modificado.Este é um caso de delegação e é possibilitado chamando CWnd::Attach a alias um HWND para um CWnd objeto.
CWndanexado a um HWND e você pode modificar o comportamento em uma classe derivada.Isso é chamado dinâmico subclassificação porque estamos alterando o comportamento e, portanto, a classe de um objeto do Windows em tempo de execução.
Você pode obter dinâmica subclassificação usando os métodos CWnd::SubclassWindow eCWnd::SubclassDlgItem.
Ambas as rotinas de anexar um CWnd objeto existente HWND.SubclassWindowleva a HWND diretamente.SubclassDlgItemé uma função auxiliar que leva a uma identificação de controle e a janela pai.SubclassDlgItemfoi projetado para anexar objetos C++ a controles de caixa de diálogo criadas de um modelo de diálogo.
Consulte o CTRLTEST exemplo para vários exemplos de quando usar SubclassWindow e SubclassDlgItem.