Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Esta nota descreve o suporte do MFC para controles personalizados e auto-desenho. Ele também descreve a subclasse dinâmica e descreve a relação entre objetos CWnd e HWNDs.
O aplicativo de exemplo MFC CTRLTEST ilustra como usar muitos controles personalizados. Consulte o código-fonte para o exemplo geral do MFC CTRLTEST e ajuda online.
Controles/Menus de Owner-Draw
O Windows fornece suporte para menus e controles de desenho de proprietário usando mensagens do Windows. A janela pai de qualquer controle ou menu recebe essas mensagens e chama funções em resposta. Você pode substituir essas funções para personalizar a aparência visual e o comportamento do seu controle ou menu de desenho do proprietário.
O MFC dá suporte diretamente ao desenho do proprietário com as seguintes funções:
Você pode substituir essas funções em sua CWnd classe derivada para implementar o comportamento de desenho personalizado.
Essa abordagem não leva a código reutilizável. Se você tiver dois controles semelhantes em duas classes diferentes CWnd , deverá implementar o comportamento de controle personalizado em dois locais. A arquitetura de controle de auto-desenho com suporte do MFC resolve esse problema.
Controles e menus do Self-Draw
O MFC fornece uma implementação padrão (nas classes CWnd e CMenu) para as mensagens padrão de desenho personalizado. Essa implementação padrão decodificará os parâmetros de desenho do proprietário e delegará as mensagens de desenho do proprietário para os controles ou menu. Isso é chamado de auto-desenho porque o código de desenho está na classe do controle ou menu, não na janela do proprietário.
Usando controles de autodesenho, você pode criar classes de controle reutilizáveis que utilizam semântica de desenho proprietário para exibir o controle. O código para desenhar o controle está na classe do controle, não em sua classe pai. Essa é uma abordagem orientada a objetos para programação de controle personalizada. Adicione a seguinte lista de funções às classes de auto-desenho:
Para botões de auto-desenho:
CButton::DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this buttonPara menus de auto-desenho:
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 menuPara caixas de listagem auto-desenhadas:
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 boxPara caixas de combinação auto-desenhadas:
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 do proprietário (DRAWITEMSTRUCT, MEASUREITEMSTRUCT, COMPAREITEMSTRUCT e DELETEITEMSTRUCT), consulte a documentação do MFC para CWnd::OnDrawItem, CWnd::OnMeasureIteme CWnd::OnCompareItemCWnd::OnDeleteItem respectivamente.
Usando controles e menus de auto-desenho
Para menus autodesenhados, você deve substituir os métodos OnMeasureItem e OnDrawItem.
Para caixas de listagem auto-desenhadas e caixas de combinação, você deve substituir OnMeasureItem e OnDrawItem. Você deve especificar o estilo LBS_OWNERDRAWVARIABLE para listas ou o estilo CBS_OWNERDRAWVARIABLE para caixas de combinação no modelo de diálogo. O estilo OWNERDRAWFIXED não funcionará com itens de auto-desenho porque a altura do item fixo é determinada antes que os controles de auto-desenho sejam anexados à caixa de listagem. (Você pode usar os métodos CListBox::SetItemHeight e CComboBox::SetItemHeight para superar essa limitação.)
Alternar para o estilo OWNERDRAWVARIABLE forçará o sistema a aplicar o estilo NOINTEGRALHEIGHT ao controle. Como o controle não pode calcular uma altura integral com itens de tamanho variável, o estilo padrão de INTEGRALHEIGHT é ignorado e o controle é sempre NOINTEGRALHEIGHT. Se os itens forem de altura fixa, você poderá impedir que itens parciais sejam desenhados especificando o tamanho do controle como um multiplicador inteiro do tamanho do item.
Para caixas de listagem autodesenho e caixas de combinação com o estilo LBS_SORT ou CBS_SORT, você deve substituir o método OnCompareItem.
Geralmente, para caixas de listagem e caixas de combinação auto desenhadas, OnDeleteItem não é substituído. Você pode substituir OnDeleteItem se quiser executar qualquer processamento especial. Um caso em que isso seria aplicável é quando memória adicional ou outros recursos são armazenados com cada caixa de listagem ou item de caixa de combinação.
Exemplos de controles e menus de Self-Drawing
O exemplo geral do MFC CTRLTEST fornece exemplos de um menu de desenho automático e uma lista de desenho automático.
O exemplo mais típico de um botão de auto-desenho é um botão bitmap. Um botão bitmap é um botão que mostra uma, duas ou três imagens bitmap para os estados diferentes. Um exemplo disso é fornecido na classe MFC CBitmapButton.
Subclasse dinâmica
Ocasionalmente, você desejará alterar a funcionalidade de um objeto que já existe. Os exemplos anteriores exigiam que você personalizasse os controles antes de serem criados. A subclasse dinâmica permite personalizar um controle que já foi criado.
Subclasseamento é o termo do Windows para substituir a WndProc de uma janela por um WndProc personalizado e chamar o WndProc antigo para a funcionalidade padrão.
Isso não deve ser confundido com derivação de classe C++. Para esclarecimento, a classe base de termos C++ e a classe derivada são análogas à superclasse e à subclasse no modelo de objeto do Windows. A derivação em C++ com subclassificação do MFC e do Windows é funcionalmente semelhante, exceto que C++ não suporta subclassificação dinâmica.
A CWnd classe fornece a conexão entre um objeto C++ (derivado de CWnd) e um objeto de janela do Windows (conhecido como ).HWND
Há três maneiras comuns relacionadas a elas:
CWndcria oHWND. Você pode modificar o comportamento em uma classe derivada criando uma classe derivada deCWnd.HWNDé criado quando seu aplicativo chama CWnd::Create.O aplicativo anexa um
CWnda umHWNDexistente. O comportamento da janela existente não é modificado. Esse é um caso de delegação e é possível fazendo isso ao chamar CWnd::Attach para definir um alias para um objeto existente deHWNDpara um objetoCWnd.CWndé anexado a um existenteHWNDe você pode modificar o comportamento em uma classe derivada. Isso é chamado de subclasse dinâmica porque estamos alterando o comportamento e, portanto, a classe, de um objeto windows em tempo de execução.
Você pode obter subclasse dinâmica usando os métodos CWnd::SubclassWindow e CWnd::SubclassDlgItem.
Ambas as rotinas anexam um CWnd objeto a um existente HWND.
SubclassWindow assume diretamente HWND .
SubclassDlgItem é uma função auxiliar que usa uma ID de controle e a janela pai.
SubclassDlgItem foi projetado para anexar objetos C++ a controles de diálogo criados a partir de um modelo de caixa de diálogo.
Consulte o exemplo CTRLTEST para obter vários exemplos de quando usar SubclassWindow e SubclassDlgItem.