(Tutorial) WinAPI Eventos(pt2)
2 participantes
Página 1 de 1
(Tutorial) WinAPI Eventos(pt2)
Estou dando continuidade a sequência de mini-tutoriais divididos por partes para o desenvolvimento básico em C++
usando a estrutura do WinAPI, nos permitindo criar janelas e handles de uma forma nem tão
simples, mas bem completa por assim dizer.
(Recomendado para pessoas que já tenham uma noção básica de desenvolvimento)
usando a estrutura do WinAPI, nos permitindo criar janelas e handles de uma forma nem tão
simples, mas bem completa por assim dizer.
(Recomendado para pessoas que já tenham uma noção básica de desenvolvimento)
Índice:
- Primeira visão
- Definição & estruturação: WinProcedure
- Tratamentos de mensagens
-----------------------------------------------------------------------------------------------
Primeira visão:
Bom, como este tópico será especificamente para a callback denominada por padrão de WinProcedure(WinProcc),
falando sobre os "eventos" que podemos gerar a partir dos handles que vimos no tópico passado...
No tópico passado falamos sobre métodos de produção e neles citamos o WinProcc e seu funcionamento, que
é no geral, definir eventos para determinadas mensagens tratadas pelo handle principal.
Prévia do tópico passado:
Para ler mais a respeito acesso o tópico Link do tópico passado: WinAPI Introdução(pt1)Willian Luigi escreveu:Definimos um WinMain para fazer toda a produção de um software visualmente dentre o Registro, até adicionar botões, textboxes, labels, e todas as parafernalhas que utilizamos em um software qualquer.
Definimos logo após um WinProcc para fazer toda a produção estrutural do software, que seria os eventos e as determinadas funções que cada hwnd que você adicionou no WinMain vai executar, botões, textboxes, labels, etc...
Essas dois métodos são os mais utilizados e definidos como padrão(muito usado) de desenvolvimento de WinAPI C++,
mas existem muitas outras maneiras de serem feitas, eu por exemplo utilizo métodos auxiliares, pra manter a organização e a 'estética' do meu código, haha.
Exemplo: eu costumo utilizar o WinMain apenas para tratar as formas de mensagem que o HANDLE principal recebe, como quando você clica com o mouse, como quando você aperta algum botão do teclado...
Eu costumo utilizar o WinProcc, por padrão, para receber as mensagens tratadas do WinMain e atribuir a elas um determinado "evento", função a executar...(tratamento)
-----------------------------------------------------------------------------------------------
Definição & estruturação(WinProcedure):
Bom, a definição dessa callback se dá por 4 parâmetros e uma forma de retorno diferenciada que estarei explicando outra hora.
Definição:
Definição:
OBS: A nomenclatura das callbacks utilizadas ao longo desta série de tutoriais a respeito de WinAPI, não necessariamente precisam ser da forma
como eu estou exemplificando, você pode usar outros tipos de nomenclatura, com tanto que tenha os parâmetros necessários, e que você estruture ela de uma forma que siga seus padrões explicados nos tutoriais.
A estruturação dessa callback pode se dar ao desenrolo do código, quando você vai definir eventos para as mensagens tratadas.
Vejamos um exemplo.
Existem padrões de programação que em certas ocasiões te permitem substituir o if por um switch, então estarei citando 2 exemplos que fazem a mesma coisa, porém estão feitos 1 com if, outro com switch.
Exemplo:
(IDE utilizada: Visual Studio 2010)
(IDE utilizada: Visual Studio 2010)
Agora irei relembrar de um exemplo da estruturação do WinMain, para dar continuidade.
Temos um hwnd de um botão, e queremos fazer com que ao clicar nele, ele executa alguma função.
Botão:
- Código:
CreateWindow(L"BUTTON", L"Clica", WS_CHILD + WS_VISIBLE + WS_TABSTOP, 270, 50, 70, 25, g_hWnd, (HMENU)1, hInstance, NULL);
O botão está associado ao HWND principal:
- HWND principal:
- HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = ( HBRUSH )GetStockObject(LTGRAY_BRUSH);//( COLOR_WINDOW + 1 );
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"code.me";
wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
if( !RegisterClassEx( &wcex ) )
return E_FAIL;
g_hInst = hInstance;
RECT rc = { 0, 0, 470, 240 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
g_hWnd = CreateWindow( L"code.me", L"Codeme: Setting Up Window Process.", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
NULL );
CreateWindow(L"BUTTON", L"Clica", WS_CHILD + WS_VISIBLE + WS_TABSTOP, 270, 50, 70, 25, g_hWnd, (HMENU)1, hInstance, NULL);
if( !g_hWnd )
return E_FAIL;
ShowWindow( g_hWnd, nCmdShow );
return S_OK;
}
Definiremos um evento/ação para este botão, ao clicarmos nele, ele irá exibir uma mensagem de Hello World.
Iniciaremos utilizando um parâmetro que foi atribuído ao botão dentro da callback de inicialização
- Código:
(HMENU)1
- Código:
LRESULT CALLBACK wWndProcc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
{
if (LOWORD(wParam) == 1)
{
MessageBox(NULL, L"Olá mundo, este é o meu primeiro evento com WinAPI C++", L"Boas vindas", MB_ICONINFORMATION);
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return 0;
}
As questões definições "WM_COMMAND" e "WM_DESTROY" eu estarei explicando no ultimo ponto do tópico(Tratamentos de mensagens).
Como eu havia comentado, utilizamos um identificador do tipo (HMENU) para o nosso botão, e ele seria o id 1, neste exemplo atribuímos o evento/ação ao botão através do seu ID.
- Código:
if (LOWORD(wParam) == 1)
Se caso o identificador(HMENU) que tivéssemos atribuído ao botão fosse '2', ao fazer a verificação do wParam, utilizaríamos '2' ao invés de '1', e por ai adiante , ou seja sempre que quisermos adicionar um hwnd novo e meter um evento/ação no mesmo, utilizamos um identificador de HMENU diferenciado dos demais, pois se o identificador for o mesmo, ambos ao serem chamado irão executar o mesmo evento/ação.
OBS: Estamos citando eventos tratados pelo main como vindos de um hwnd(botão, text, etc).
- Como assim ?
- R: sempre que algum hwnd recebe uma requisição, como clique(botões), edição de texto(textbox), qualquer coisa que seja relacionada a somente aquele HWND, o parâmetro é tratado pelo WinMain e recebido pelo WinProcedure como wParam.
Quando utilizamos requisições gerais como apertar um botão enquanto a janela do software estiver aberta, este tipo de evento vem tratado como lParam, e sua forma de verificação não é através de um identificador do tipo HMENU.
Eu estarei dando um exemplo para verificar, quando a requisição for por teclas(lembrem-se disso).
Que é utilizando uma função da include(windows.h).
função:
- Código:
GetAsyncKeyState(botão)
a diferença não chega a ser tanta na alteração da estruturação.
Exemplificamos utilizando um botão, no exemplo acima, agora faremos supondo que o usuário aperte F5.
Exemplo:
- Código:
LRESULT CALLBACK wWndProcc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_KEYUP:
{
if (LOWORD(lParam) == GetAsyncKeyState(VK_F5))
{
MessageBox(NULL, L"Olá mundo, este é o meu primeiro evento com WinAPI C++", L"Boas vindas", MB_ICONINFORMATION);
}
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return 0;
}
Mudamos também o chamado, não estamos mais chamando por um comando(WM_COMMAND), estamos chamando agora
quando uma tecla for solta(WM_KEYUP).
-----------------------------------------------------------------------------------------------
Tratamentos de mensagens:
Todas as mensagens(eventos/ações) enviadas para o programa são acumuladas em uma lista, que por sua vez é lida e interpretada por uma função que roda em um loop até não encontrar mais mensagens(GetMessage), essas mensagens após serem traduzidas são enviadas para a callback WndProcedure.
As mensagens recebidas pelo WndProcedure podem ser interpretadas por:
Valor | Significado |
WM_ACTIVATE | Janela recebe foco |
WM_CLOSE | Janela é fechada |
WM_CREATE | Janela é criada |
WM_DESTROY | Janela está para ser destruída |
WM_MOVE | Janela foi movida |
WM_MOUSEMOVE | Mouse foi movido |
WM_{L ou R}BUTTON{UP, DOWN ou DBLCLK} | Um botão (esquerdo ou direito) do mouse é utilizado (pressionado, solto ou clicado duas vezes) |
WM_KEYUP | Uma tecla foi solta |
WM_KEYDOWN | Uma tecla foi pressionada |
WM_TIMER | Quando um ciclo de timer ocorre |
WM_COMMAND | Quando um controle é utilizado (clicado em geral) |
WM_PAINT | Janela necessita ser re-pintada |
WM_SIZE | Janela é redimensionada |
WM_QUIT | Quando um aplicativo é terminado |
-----------------------------------------------------------------------------------------------
Referência:
Série WinAPI tuto links:
WinAPI Introdução(pt1)
Créditos: Willian Luigi ((c) CODE.ME - 2013.1)
Tabela de mensagens: MSDN
Última edição por Willian Luigi em Sáb Jul 27, 2013 7:28 am, editado 2 vez(es)
Re: (Tutorial) WinAPI Eventos(pt2)
EXTRA FINAL PT2
Fiz um código simples para quem quiser estudar e melhorar a prática.
Funcionamento:
O código está dentro dos parâmetros do que eu ensinei a respeito de WinAPI até agora, em relação a eventos e estruturação (design), só tem alguns poréns a mais
que alguns irão gostar de estudar e perguntar...
CÓDIGO AQUI.
Fiz um código simples para quem quiser estudar e melhorar a prática.
Funcionamento:
O código está dentro dos parâmetros do que eu ensinei a respeito de WinAPI até agora, em relação a eventos e estruturação (design), só tem alguns poréns a mais
que alguns irão gostar de estudar e perguntar...
CÓDIGO AQUI.
Re: (Tutorial) WinAPI Eventos(pt2)
Ótimo tópico, até agora entendi tudo e aprendi mais um pouco do que ainda não conhecia direito, e o melhor em português. Parabéns e obrigado por esse maravilhoso material.
Voltz- Novato
- Mensagens : 7
Data de inscrição : 14/08/2013
Idade : 30
Localização : Barueri
Tópicos semelhantes
» (Tutorial) WinAPI Introdução(pt1)
» (C++) Identificando processo
» (Tutorial) CallRemoteFuncion (dicas)
» (Tutorial) Introdução a linguagem
» [Tutorial]Dicas para mapear mtasa/samp
» (C++) Identificando processo
» (Tutorial) CallRemoteFuncion (dicas)
» (Tutorial) Introdução a linguagem
» [Tutorial]Dicas para mapear mtasa/samp
Página 1 de 1
Permissões neste sub-fórum
Não podes responder a tópicos
|
|