Esse tutorial
é para você que já sabe programar em C, e apenas quer
migrar para o Windows. Bons compiladores comerciais de C/C++ pra Windows
são Visual C++ e Borland C++, mas há um compilador grátis
na Internet, o LCC.
Eu mesmo sou extremamente
iniciante em programação para Windows, portanto, não
garanto que este tutorial vá ensinar a melhor ou mais rápida
maneira de programar para Windows, mas estou aberto a sugestões.
Ao contrário do tutorial anterior, desta vez eu não vou começar com um exemplo, porque este ficaria meio grande demais e poderia assustar... Criar uma simples janela vazia envolve um mecanismo relativamente complexo, e é melhor que você primeiro entenda o mecanismo. Quando você quer criar uma janela no Windows, você tem que fazer tudo isso:
Eu vou ir fazendo um exemplo
aos poucos, assim fica mais fácil de entender.
Antes de qualquer outra
coisa, vamos fazer o "esqueleto" de qualquer programa para Windows. Nesse
"esqueleto" eu já vou colocar declarações algumas
variáveis e funcões (em azul), mas você não
precisa nem ligar pra isso agora (finja que não está aí,
você vai se sentir melhor...).
/* EX03.C - uma simples janela vazia */ #include <windows.h> const char *NOME = "TantoFaz",
LRESULT CALLBACK FuncaoDaJanela(HWND hJanela,
UINT MsgID,
int WINAPI WinMain(HINSTANCE hInstancia, HINSTANCE hInstanciaAnt,
Agora vamos realmente começar a implementar aqueles itens do início do capítulo: 1. Criar a classe da sua janela, incluindo nela alguns dados iniciais. Ok, a primeira coisa que você deve fazer é declarar uma variável do tipo WNDCLASS (classe de janela). No nosso exemplo (acima), nós temos: Entao, ClasseDaJanela passa a ser um struct com os mesmos elementos de WNDCLASS (definido em win.h). Aí continua nosso exemplo, dessa vez definindo valores para esses elementos (os dados iniciais):
#include <windows.h> const char *NOME = "TantoFaz",
LRESULT CALLBACK FuncaoDaJanela(HWND hJanela,
UINT MsgID,
int WINAPI WinMain(HINSTANCE hInstancia, HINSTANCE hInstanciaAnt,
ClasseDaJanela.style = CS_HREDRAW | CS_VREDRAW;
Agora
acompanhe no quadro a descrição de cada elemento:
Agora que já definimos os valores de cada elemento, temos que informar ao Windows que está tudo pronto, só falta portanto registrar a classe. 2. Registrar a classe da janela. Depois que você fez a pior parte do trabalho, basta um comando para registrar a classe de janela: RegisterClass(&ClasseDaJanela); Isso basta para registrar a classe, mas pode ocorrer de você ter feito alguma coisa errada no passo anterior, e aí o Windows não vai conseguir registrar a classe... Nesse caso, RegisterClass vai retornar 0 (a mesma coisa que FALSE). Portanto você pode fazer com que o programa exiba uma mensagem de texto e saia, o que poderia ficar assim: if (!RegisterClass(&ClasseDaJanela))
Note que ainda usamos NULL no MessageBox, já que nossa janela ainda não foi criada... Observação1:
Coloque o comando MessageBox em uma linha só.
Estamos prontos portanto para o próximo passo: 3. Criar a janela em si, informando outros dados importantes para sua criação. Podemos dizer que esse terceiro passo é tão detalhado quanto o primeiro. Para criar a janela (depois de ter registrado a classe), você usa apenas uma função: CreateWindow, que cria a janela e retorna um "handle" para a janela. Mas essa função tem muitos parâmetros (11, para ser exato). Ta aí o exemplo: hJanela = CreateWindow(NOME, TITULO, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 100, NULL, hJanela, hInstancia, NULL); Inclua isso no programa
também.
2. Título da janela. 3. Tipo de janela. Há várias opções, que você pode encontrar no win.h, todas começadas com WS_. 4. Posição (coordenada X) do lado esquerdo da janela (CW_DEFAULT faz com que o Windows determine a posição). 5. Posição (coordenada Y) do canto superior da janela (pode usar CW_DEFAULT também). 6. A largura da janela (use CW_DEFAULT se quiser). 7. A altura da janela (veja acima). 8. A janela a qual a sua janela pertence. NULL significa que a sua janela não pertence a nenhuma outra. 9. "Handle" para o menu (não usamos menu, portanto: NULL) 10. A instância do seu programa. 11. Não nos interessa no momento. Próximo passo: 4. Mostrar a janela na tela. Já essa parte é tão fácil quanto o passo 2: ShowWindow(hJanela, Visualizacao); Não preciso dizer
que você deve incluir isso no programa...
O penúltimo passo (estamos quase terminando): 5. Verificar se aconteceu alguma coisa envolvendo a sua janela. Você deve se lembrar do exemplo no início do tutorial, onde tínhamos: Pois é, é através dessa variável que o Windows vai enviar mensagens pra você, do tipo: "O usuário mandou fechar a janela", "O usuário movimentou o mouse", etc. Mas é claro que o Windows não se comunica com você dessa maneira... Quando você declara uma variável do tipo MSG, você na verdade está declarando uma struct com os seguintes elementos: hwnd - indica
em que janela a ação foi executada.
while(GetMessage(&Mensagem, hJanela,
0, 0))
GetMessage vai retornar 0 (ou seja, FALSE) quando o Windows enviar uma mensagem WM_QUIT. Portanto, enquanto isso não acontecer, o programa executa DispatchMessage(&Mensagem);. Esse comando DispatchMessage apenas chama FuncaoDaJanela, passando todos os parâmetros necessários. E, quando GetMessage retornar 0, o programa será finalizado retornando um código de erro. No caso, wParam contém o código de erro que o Windows definiu, e recomendo que você o use. A esta altura, nosso programa deve estar assim:
/* EX03.C - uma simples janela vazia */ #include <windows.h> const char *NOME = "TantoFaz",
LRESULT CALLBACK FuncaoDaJanela(HWND hJanela,
UINT MsgID,
int WINAPI WinMain(HINSTANCE hInstancia,
HINSTANCE hInstanciaAnt,
ClasseDaJanela.style = CS_HREDRAW
| CS_VREDRAW;
if (!RegisterClass(&ClasseDaJanela))
hJanela = CreateWindow(NOME, TITULO, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 100, NULL, hJanela, hInstancia, NULL); ShowWindow(hJanela, Visualizacao); while(GetMessage(&Mensagem,
hJanela, 0, 0))
return Mensagem.wParam;
Ufa! Exemplo bem grandinho, no entanto, não é hora de compilar ainda... Precisamos ainda fazer a função que vai cuidar dos eventos da janela. A declaração de uma função desse tipo fica mais ou menos assim: LRESULT CALLBACK FuncaoDaJanela(HWND hJanela, UINT MsgID, WPARAM ParamW, LPARAM ParamL); Eu tenho que dizer uma coisa... O win.h é cheio de definições e typedefs. Por exemplo, se você quer dizer long, você pode dizer LRESULT, LPARAM, LONG, entre outros... são a mesma coisa que long. UINT e WPARAM são a mesma coisa que unsigned int. Então por que existem tantas formas diferentes de se dizer uma mesma coisa? Eu tenho um palpite. Acho que isso é para quem estar lendo seu código perceber logo de que se trata determinada variável. Você não vai precisar chamar essa função: o DispatchMessage já faz isso, e passa todos os parâmetros necessários (que mordomia!)... Mas acho que você deve saber que parâmetros o DispatchMessage passa para FuncaoDaJanela. No primeiro parâmetro,
DispatchMessage passa Mensagem.hwnd
Tudo o que temos que fazer, portanto, é checar qual a mensagem do Windows e, se nos interessar, escrever o que deve ser feito. Você pode colocar um tanto de if's, mas é pra evitar isso que existe o switch, afinal. Então, depois do WinMain, coloque o seguinte: LRESULT CALLBACK FuncaoDaJanela(HWND hJanela,
UINT MsgID,
return 0;
Calma, vou explicar... Primeiro, verificamos qual fo a mensagem. Se a mensagem foi WM_CLOSE ou WM_DESTROY, vai aparecer a pergunta "Deseja realmente sair?". Se o usuário escolher Sim, o programa acaba. Se o usuário escolher Não, o programa continua e FuncaoDaJanela vai retornar 0, indicando que o Windows não precisa fazer nada, está tudo sob controle. Mas se qualquer acontecer qualquer outra coisa, então FuncaoDaJanela vai retornar DefWindowProc(hJanela, MsgID, ParamW, ParamL). E para que serve essa função DefwindowProc? Para cuidar das mensagens que não cuidamos em FuncaoDaJanela (seriam necessários muitos case para cuidar de todas as mensagens que o Windows pode retornar...). Você apenas passa os parâmetros que foram passados para FuncaoDaJanela. A partir disso, DefWindowProc vai retornar um número, e você repassa ele. Através desse número é que o Windows vai decidir o que ele vai fazer, mas isso não tem nada a ver com seu programa, é responsabilidade do Windows. Apenas retorne o valor que DefWindowProc retornou, e o resto acontece sozinho... Aqui acaba o nosso exemplo,
que fica assim:
/* EX03.C - uma simples janela vazia */ #include <windows.h> const char *NOME = "TantoFaz",
LRESULT CALLBACK FuncaoDaJanela(HWND hJanela,
UINT MsgID,
int WINAPI WinMain(HINSTANCE hInstancia,
HINSTANCE hInstanciaAnt,
ClasseDaJanela.style = CS_HREDRAW
| CS_VREDRAW;
if (!RegisterClass(&ClasseDaJanela))
hJanela = CreateWindow(NOME, TITULO, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 100, NULL, hJanela, hInstancia, NULL); ShowWindow(hJanela, Visualizacao); while(GetMessage(&Mensagem,
hJanela, 0, 0))
return Mensagem.wParam;
LRESULT CALLBACK FuncaoDaJanela(HWND hJanela,
UINT MsgID,
return 0;
Pode compilar e executar, deve funcionar. Eu mesmo copiei o código daqui, colei no Bloco de Notas, coloquei o Messagebox em uma linha só, gravei como EX03.C, compilei, executei e funcionou. Vai aparecer uma janela pequena, com fundo branco, vazia, mas você sabe o quanto foi difícil fazer essa pobre janela aparecer na tela e fazer tudo o que ela faz =) |