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.
Esta nota descreve o suporte MFC para controles personalizados e de desenho automático. Ele também descreve a subclassificação 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 do exemplo geral MFC CTRLTEST e ajuda online.
Owner-Draw Controlos/Menus
O Windows fornece suporte para controlos de desenho próprio e menus através de 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.
MFC suporta diretamente o 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.
Esta abordagem não conduz 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 autodesenho suportada pelo MFC resolve esse problema.
Self-Draw Controles e Menus
MFC fornece uma implementação padrão (nas classes CWnd e CMenu) para as mensagens owner-draw padrões. Essa implementação padrão decodificará os parâmetros owner-draw e delegará as mensagens owner-draw aos controles ou menu. Isso é chamado de desenho automático porque o código de desenho está na classe do controlo ou menu, não na janela do proprietário.
Utilizando controles de desenho próprio, é possível criar classes de controle reutilizáveis que usam semântica de desenho personalizada para exibir o controle. O código para desenhar o controle está na classe de controle, não em seu pai. Esta é uma abordagem orientada a objetos para programação de controle personalizada. Adicione a seguinte lista de funções às suas classes de desenho automático:
Para botões de desenho automático:
CButton::DrawItem(LPDRAWITEMSTRUCT); // insert code to draw this buttonPara menus de desenho próprio:
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 de desenho automático:
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::OnMeasureItem, CWnd::OnCompareItem, e CWnd::OnDeleteItem respectivamente.
Usando controles e menus de desenho automático
Para menus de desenho próprio, deve substituir ambos os métodos, OnMeasureItem e OnDrawItem.
Para caixas de listagem de desenho automático e caixas de combinação, você deve substituir OnMeasureItem e OnDrawItem. Você deve especificar o estilo LBS_OWNERDRAWVARIABLE para caixas de listagem ou estilo CBS_OWNERDRAWVARIABLE para caixas de combinação no modelo de diálogo. O estilo OWNERDRAWFIXED não funcionará com itens de desenho automático porque a altura fixa do item é determinada antes que os controles de autodesenho sejam anexados à caixa de listagem. (Você pode usar os métodos CListBox::SetItemHeight e CComboBox::SetItemHeight para superar essa limitação.)
Mudar para um 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 tiverem 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 de autodesenho e caixas de combinação com o estilo LBS_SORT ou CBS_SORT, deve-se substituir o método OnCompareItem.
Para caixas de listagem de auto-desenho e caixas de combinação, OnDeleteItem geralmente 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 Self-Drawing controles e menus
O exemplo geral do MFC CTRLTEST fornece amostras de um menu de auto-desenho e uma caixa de listagem de auto-desenho.
O exemplo mais típico de um botão de autodesenho é um botão bitmap. Um botão bitmap é um botão que mostra uma, duas ou três imagens bitmap para os diferentes estados. Um exemplo disso é fornecido na classe MFC CBitmapButton.
Subclassificação dinâmica
Ocasionalmente, você desejará alterar a funcionalidade de um objeto que já existe. Os exemplos anteriores exigiam que você personalizasse os controles antes que eles fossem criados. A subclassificação dinâmica permite personalizar um controle que já foi criado.
Subclassificação é o termo do Windows para substituir o WndProc de uma janela por um personalizado WndProc e chamar o antigo WndProc para a funcionalidade padrão.
Isso não deve ser confundido com derivação de classe C++. Para esclarecimento, os termos C++ classe base e classe derivada são análogos a superclasse e subclasse no modelo de objeto do Windows. A derivação C++ com MFC e a subclassificação do Windows são funcionalmente semelhantes, 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 de como estes se relacionam:
CWndcria oHWND. Você pode modificar o comportamento em uma classe derivada criando uma classe derivada deCWnd. OHWNDé criado quando seu aplicativo chama CWnd::Create.A aplicação anexa um
CWnda umHWND. O comportamento da janela existente não é modificado. Este é um caso de delegação e é tornado possível ao chamar CWnd::Attach para criar um alias de umHWNDnum objectoCWnd.CWndestá anexado a um existenteHWNDe você pode modificar o comportamento em uma classe derivada. Isso é chamado de subclassificação dinâmica porque estamos alterando o comportamento e, portanto, a classe de um objeto do Windows em tempo de execução.
Você pode obter subclassificação dinâmica usando os métodos CWnd::SubclassWindow e CWnd::SubclassDlgItem.
Ambas as rotinas anexam um objeto CWnd a um HWND existente.
SubclassWindow toma diretamente o HWND.
SubclassDlgItem é uma função auxiliar que usa um 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 diálogo.
Consulte o exemplo CTRLTEST para obter vários exemplos de quando usar SubclassWindow e SubclassDlgItem.