Implementação de Controles Customizados com MFC e C++

O framework MFC (Microsoft Foundation Classes) permite a criação de componentes de interface personalizados através do uso de "Custom Controls". Este processo envolve a definição de uma classe de janela no Windows, a vinculação a uma classe C++ derivada de CWnd e a manipulação de mensagens de renderização.

1. Configuração do Ambiente de Diálogo

Para iniciar, crie um projeto do tipo MFC Application e selecione Dialog based como tipo de aplicação. No editor de recursos (Resource View), abra o diálogo principal e arraste um Custom Control da Toolbox para a interface.

Nas propriedades do controle inserido, localize o campo Class. Defina um identificador único, como "MeuComponenteGrafico". Este nome é fundamental, pois será utilizado no registro da classe de janela via API do Windows.

2. Desenvolvimento da Classe do Componente

Crie uma nova classe C++ (ex: CVisualizadorCustom) herdando de CWnd. Esta classe será responsável por gerenciar o comportamento e a aparência do controle.

Registro da Classe de Janela

Diferente de controles padrão como botões ou editores de texto, o Custom Control exige que a classe de janela seja registrada no sistema antes da sua criação. Implemente uma função estática ou membro para realizar esse registro:

BOOL CVisualizadorCustom::RegistrarClasseHibrida()
{
    WNDCLASS estruturaJanela;
    HINSTANCE hInst = AfxGetInstanceHandle();
    LPCTSTR nomeClasse = _T("MeuComponenteGrafico");

    // Verifica se a classe já foi registrada anteriormente
    if (!(::GetClassInfo(hInst, nomeClasse, &estruturaJanela)))
    {
        estruturaJanela.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
        estruturaJanela.lpfnWndProc = ::DefWindowProc;
        estruturaJanela.cbClsExtra = 0;
        estruturaJanela.cbWndExtra = 0;
        estruturaJanela.hInstance = hInst;
        estruturaJanela.hIcon = NULL;
        estruturaJanela.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
        estruturaJanela.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
        estruturaJanela.lpszMenuName = NULL;
        estruturaJanela.lpszClassName = nomeClasse;

        if (!AfxRegisterClass(&estruturaJanela))
        {
            AfxThrowResourceException();
            return FALSE;
        }
    }
    return TRUE;
}

No construtor da classe CVisualizadorCustom, invoque o método de registro para garantir que o Windows reconheça o identificador definido no editor de recursos:

CVisualizadorCustom::CVisualizadorCustom()
{
    RegistrarClasseHibrida();
}

3. Vinculação de Dados (DDX)

Para que o objeto C++ controle a instância do componente no diálogo, é necessário realizar o mapeamento no arquivo de cabeçalho do diálogo principal:

CVisualizadorCustom m_ctrlGrafico;

No arquivo .cpp do diálogo, dentro da função DoDataExchange, adicione a macro de controle:

void CProjetoExemploDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_CUSTOM_GRAFICO, m_ctrlGrafico);
}

4. Customização da Interface (Desenho GDI)

A customização visual ocorre interceptando a mensagem WM_PAINT. Através do Class Wizard, adicione o handler OnPaint à sua classe CVisualizadorCustom.

void CVisualizadorCustom::OnPaint()
{
    CPaintDC dc(this); // Device context para renderização
    
    CRect retanguloCliente;
    GetClientRect(&retanguloCliente);

    // Exemplo: Desenhar uma borda e uma linha diagonal
    CPen canetaDestaque(PS_SOLID, 2, RGB(0, 120, 215));
    CPen* pCanetaAntiga = dc.SelectObject(&canetaDestaque);

    dc.Rectangle(retanguloCliente);
    dc.MoveTo(retanguloCliente.left, retanguloCliente.top);
    dc.LineTo(retanguloCliente.right, retanguloCliente.bottom);

    dc.SelectObject(pCanetaAntiga);
}

Este procedimento permite total contorle sobre a renderização do elemento, possibilitando a criação de gráficos, medidores ou dashboards complexos dentro de aplicações legadas ou modernas baseadas em MFC.

Tags: mfc C++ Win32 gui gdi

Publicado em 7-28 23:51