C GUI no Windows: do printf ao MessageBox com LLVM e Make
Muito painel de chão ainda é Windows embarcado ou PC industrial com Windows. Enquanto o estudo irmão c_gui_linux parte do GTK3, o repositório c_gui_win treina a mesma disciplina no ecossistema Microsoft: toolchain explícita + dois programas mínimos — console e GUI Win32.
Este texto é estudo próprio de bancada. Sem métrica inventada, sem screenshot gerado por IA, sem pitch de produto web. O que importa é o que o código e o README documentam, e como isso se traduz em ferramenta de oficina: utilitário que o técnico abre no notebook de manutenção, confirma uma ação e fecha — sem depender do Visual Studio completo nem de runtime Python.
Dependências que o README fixa
Três peças, nessa ordem mental:
- Chocolatey — gerenciador de pacotes no Windows (
chocolatey.org/install). choco install make— trazmakepara repetir o mesmo hábito de build usado no Linux.- LLVM — downloads oficiais em
releases.llvm.org; o makefile do repo chamaclang.
A decisão de projeto por trás disso: não depender do Visual Studio completo só para um hello GUI. Em notebook de engenharia ou imagem enxuta de manutenção, Chocolatey + LLVM + Make cabem no SOP. Quem já tem MSVC pode adaptar; o estudo escolhe Clang de propósito, alinhado ao makefile do c_gui_linux (CC = clang).
Na prática de TI industrial, Chocolatey exige política de admin. Trate isso como requisito de comissionamento da bancada, não como “atalho pessoal”: documente quem pode instalar, qual versão do LLVM foi validada na imagem, e se o antivírus precisa de exclusão para a pasta de build. Ferramenta de oficina que só o autor consegue compilar não é ferramenta — é hobby no pen drive.
Duas pastas, dois contratos com o SO
hello/ → processo de console
hello_gui/ → processo de janela (subsystem GUI / WinMain)
Essa divisão é o coração pedagógico do repo. Console e GUI no Windows não são o mesmo tipo de processo. Trocar main por WinMain e incluir windows.h muda entry point, subsystem do linker e expectativas sobre stdout. Quem ignora isso passa uma tarde achando que “o MessageBox não funciona” quando o problema é PATH do clang ou makefile rodando na pasta errada.
hello — validar a toolchain antes da GUI
hello.c é o mínimo absoluto:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("hello");
return 0;
}
Makefile:
all: hello.c
clang -o hello hello.c
Por que isso existe num repo de “C GUI”? Porque metade dos problemas de “não abre a janela” na bancada Windows são, na verdade, PATH, clang, make ou antivírus atrapalhando o build. Se hello.exe imprime hello no console, a ferramenta de compilação está viva. Só então você sobe para Win32.
Roteiro de isolamento (pass/fail, sem métrica de tempo):
where clangewhere makeno Prompt — ambos resolvem?cd hello && make— gerahello.exe?- Rodar
hello.exe— imprimehello? - Só então
cd ../hello_gui && make.
Se o passo 1 falha, pare. Instalar LLVM e reabrir o terminal (PATH novo). Se o passo 2 falha com erro de comando, o problema ainda não é Win32. Subir complexidade cedo demais é o jeito mais caro de aprender.
hello_gui — o salto para a API de usuário
#include <stdio.h>
#include <windows.h>
#pragma comment (lib, "User32.lib")
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
printf("hello");
MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK);
return 0;
}
Makefile idêntico em espírito:
all: hello_gui.c
clang -o hello_gui hello_gui.c
Pontos técnicos que o estudo força você a notar:
| Detalhe | Por que importa |
|---|---|
WinMain em vez de main |
Entry point de aplicativo Windows com parâmetros de instância e show |
windows.h |
Porta de entrada das APIs Win32 |
#pragma comment (lib, "User32.lib") |
Pede link com User32 (MessageBox mora aí); com Clang/MinGW o link às vezes exige flag explícita — anote o que funcionar na sua instalação |
MessageBox(..., MB_OK) |
Diálogo modal nativo: bloqueia até o operador clicar |
O printf("hello") dentro do WinMain é detalhe de aprendizado: em binário GUI puro, stdout pode não ter console. Em debug com terminal anexado, você ainda vê a linha. Em deploy de painel, use log em arquivo ou OutputDebugString — não conte com console do operador. O técnico de campo não vai abrir o Prompt para ver se o utilitário “falou hello”.
Sobre o #pragma comment: em ecossistema MSVC ele é idiomático. Com Clang no Windows, o comportamento depende de como o LLVM foi instalado e de qual linker entra na jogada. Se o link falhar reclamando de MessageBox, o próximo passo honesto é acrescentar flag de link explícita no makefile (-luser32 ou caminho equivalente) e documentar no README da ferramenta o que funcionou naquela imagem — não ficar com “no meu PC compila” eterno.
Ponte industrial: Windows no chão vs Linux no painel
Na prática da Wilson Tecnologia e de muita oficina brasileira, o mapa costuma ser:
- PC de engenharia / manutenção — Windows; drivers de IHM, software de CLP, Excel, PDF.
- Painel Linux — imagem controlada, menos “surpresa” de update, bom para app nativo GTK.
- HMI do fabricante — caixa fechada; você não reescreve o runtime.
c_gui_win treina a camada em que você escreve ferramenta auxiliar no Windows: utilitário que abre, mostra um status, confirma uma ação, talvez depois leia um CSV ou manda um comando serial. Não substitui SCADA. Complementa.
Exemplos de encaixe realista (escopo pequeno):
- diálogo “Confirma gravação do parâmetro X?” antes de um script de manutenção;
- aviso modal quando arquivo de receita não foi encontrado;
- hello estendido depois com campos mínimos (IP, porta, caminho de log) numa janela própria;
- launcher que dispara outro
.exede diagnóstico e reporta código de saída.
Exemplos de não encaixe:
- reescrever a IHM touch da célula;
- trilha de auditoria multiestação;
- qualquer coisa com requisito de segurança de máquina atribuído à UI.
Comparando com o irmão Linux:
c_gui_linux |
c_gui_win |
|
|---|---|---|
| Toolkit | GTK3 | Win32 (MessageBox / User32) |
| Entry | main + gtk_main / GtkApplication |
WinMain |
| Build | pkg-config + clang |
clang + make via Chocolatey |
| Próximo passo natural | widgets GTK, CSS, .desktop | janela própria (CreateWindow), message loop, controles |
O paralelo pedagógico é intencional: mesmo rigor de makefile, duas famílias de API. Quem domina os dois não fica refém de “só roda no meu Ubuntu” ou “só no Visual Studio da fábrica”.
Message loop: o que o repo ainda não mostra (e você precisa saber)
MessageBox é atalho: a API cria a janela modal e o loop interno. Um painel de verdade exige:
- Registrar classe de janela (
WNDCLASS/WNDCLASSEX). CreateWindowEx.- Loop
GetMessage/TranslateMessage/DispatchMessage. WndProctratandoWM_COMMAND,WM_CLOSE,WM_DESTROY→PostQuitMessage.
Esse é o equivalente Win32 do gtk_main() e dos sinais GObject. O repo para no primeiro diálogo de propósito — igual ao activate vazio do startGtkApp.c no Linux. O valor está em fechar o ambiente e o primeiro binário GUI linkado.
Por que parar no MessageBox não é preguiça: é controle de escopo de laboratório. O message loop completo introduz imediatamente subclassificação de controles, recursos (LoadIcon, LoadCursor), e decisões de Unicode (W vs A). Tudo isso importa — mas só depois que clang, make e o link com User32 estão estáveis. Empilhar “hello incompleto + CreateWindow + serial + log” no mesmo fim de semana é receita de repo abandonado.
Quando for além do MessageBox, priorize nesta ordem:
- Janela vazia que fecha limpo (
WM_DESTROY→PostQuitMessage). - Um botão e um estático de texto — feedback visível de clique.
- Separar I/O bloqueante do
WndProc(mesmo problema do callback GTK: não travar o loop). - Só então falar com equipamento.
Antivírus, PATH e a realidade do PC de manutenção
Três atritos recorrentes em Windows de oficina, todos fora do código-fonte:
- SmartScreen / antivírus —
.exenovo sem assinatura assusta política corporativa. Planeje como o binário chega ao PC (pasta aprovada, hash documentado, não “baixe do Zap”). - PATH de sessão — instalou LLVM, mas o Prompt aberto ainda é o antigo. Feche e abra o terminal; confirme com
where clang. - Mistura de toolchains — MinGW de uma instalação, LLVM de outra, Make do Chocolatey. O makefile curto do repo ajuda porque não esconde flags em vinte variáveis; ainda assim, anote qual
clangrespondeu.
Nenhum desses problemas se resolve com mais widget. Resolvem com SOP de bancada.
Empacote mental para oficina
Antes de crescer o código, documente no SOP da bancada:
- Instalar Chocolatey (política de admin).
choco install make.- Instalar LLVM e garantir
clangno PATH. cd hello && make→ validar.cd hello_gui && make→ validar MessageBox.- Só então criar pasta
ferramenta_xyzcom o mesmo padrão de makefile.
Para distribuição ao técnico de campo: um .exe + DLLs do runtime (se houver) + README de versão. Evite depender de “abra o Visual Studio e rode”. Make + Clang aproximam o fluxo Windows do fluxo Linux — o mesmo cérebro opera os dois painéis.
Checklist de entrega (conteúdo, não marketing):
- nome do utilitário e o que ele não faz;
- versão do LLVM/Clang usada no build;
- comando
makee pasta de origem; - comportamento esperado do MessageBox / da janela;
- como reportar falha (print da mensagem de erro, não “não abriu”).
Quando escolher esta trilha
Escolha C + Win32 quando:
- o PC alvo é Windows e você quer binário nativo sem runtime Python;
- a UI é enxuta (status, confirmação, poucos campos);
- auditoria e dependências mínimas importam mais que velocidade de prototipagem;
- o time já pensa em C no restante da bancada (MCU, drivers, utilitários).
Prefira PyQt6 (pyqt6_book) quando o formulário cresce (menus, PDF, grids, temas). Prefira Kivy (kivy_Framework) quando o operador trabalha em touch full-screen e o objetivo ainda é protótipo de interação. Prefira GTK no Linux (c_gui_linux) quando o painel já é Debian/Ubuntu LTS.
Há também o meio-termo honesto: protótipo em PyQt6, utilitário crítico mínimo em Win32. Não é dogma — é reconhecer que produtividade de formulário e previsibilidade de deploy não sempre cabem na mesma stack.
Ligação com o restante da família de estudos
A série de GUIs do portfólio não compete consigo mesma; ela marca contratos:
c_gui_win— entry Win32 + toolchain Chocolatey/LLVM;c_gui_linux— GTK3 + pkg-config;pyqt6_book— formulário de engenharia + PDF + PyInstaller;kivy_Framework— canvas/touch +.kv+ dor de--add-data.
Usar o MessageBox como “HMI final” seria overclaim. Usar o MessageBox como prova de que a ponte console→GUI está viva é exatamente o tamanho do repo. Em conteúdo técnico para oficina, tamanho certo gera mais confiança do que feature inventada.
Do MessageBox ao utilitário de manutenção: escopo controlado
Depois que hello_gui.exe mostra o diálogo, a tentação é abrir tutorial de common controls e desenhar um painel inteiro numa tarde. Em oficina, o caminho mais seguro é outro: um utilitário, uma responsabilidade.
Exemplos de escopo que cabem na evolução natural deste repo sem virar SCADA:
- ler um arquivo de configuração local e exibir três campos em labels;
- pedir confirmação modal antes de sobrescrever receita;
- gravar um timestamp em log texto quando o operador confirma;
- falhar de forma visível se o arquivo não existe (MessageBox de erro, não crash silencioso).
O que adiar de propósito:
- login/senha sofisticado (outro domínio de requisito);
- comunicação com CLP antes da janela fechar limpo;
- temas visuais e owner-draw — primeiro texto legível e botão que responde.
Essa contenção parece conservadora. É operacional: cada feature nova no Win32 puxa mais superfície de Unicode, recursos e teste em máquina limpa. O laboratório c_gui_win existe para deixar a base inegociável — toolchain e primeiro binário GUI — antes da lista de desejos da planta.
Conclusão
c_gui_win é o exercício de disciplina: Chocolatey, Make, LLVM, hello e hello_gui. Do printf ao MessageBox você valida a ponte entre console e GUI no Windows — base para utilitários de manutenção e futuros painéis simples. O HMI industrial completo virá de requisitos (tags, alarme, receita); a bancada começa aqui, com toolchain que você controla. Se o build não repete em máquina limpa, o widget seguinte é irrelevante. Se repete, você tem o mesmo tipo de fundamento que o makefile GTK oferece no Linux — e a oficina ganha uma linguagem comum de entrega nos dois sistemas.