(Tutorial) WinAPI Eventos(pt2)

Ir em baixo

(Tutorial) WinAPI Eventos(pt2)

Mensagem por Willian Luigi em Sab Jul 27, 2013 7:17 am

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)

Í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:
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)
Para ler mais a respeito acesso o tópico Link do tópico passado: WinAPI Introdução(pt1)

-----------------------------------------------------------------------------------------------

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:


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)

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
Quando inserimos isto ao botão, estamos dizendo que '1' será o identificador que utilizaremos bata encontrar o botão quando alguma mensagem for enviada por ele para o HWND principal.

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 Smile, 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;
}
Como podem perceber, mudamos a forma de recepção da mensagem de wParam, para lParam.
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:

ValorSignificado
WM_ACTIVATEJanela recebe foco
WM_CLOSEJanela é fechada
WM_CREATEJanela é criada
WM_DESTROYJanela está para ser destruída
WM_MOVEJanela foi movida
WM_MOUSEMOVEMouse 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_KEYUPUma tecla foi solta
WM_KEYDOWNUma tecla foi pressionada
WM_TIMERQuando um ciclo de timer ocorre
WM_COMMANDQuando um controle é utilizado (clicado em geral)
WM_PAINTJanela necessita ser re-pintada
WM_SIZEJanela é redimensionada
WM_QUITQuando um aplicativo é terminado
Tendo está tabelinha em mente vocês podem montar scripts com um grau de relevância maior.

-----------------------------------------------------------------------------------------------

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 Sab Jul 27, 2013 7:28 am, editado 2 vez(es)

_________________
<br>
avatar
Willian Luigi
Fundador
Fundador

Mensagens : 63
Data de inscrição : 22/07/2013
Idade : 23
Localização : CODE.ME company

Ver perfil do usuário http://codeme.forumeiros.com

Voltar ao Topo Ir em baixo

Re: (Tutorial) WinAPI Eventos(pt2)

Mensagem por Willian Luigi em Sab Jul 27, 2013 7:17 am

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.

_________________
<br>
avatar
Willian Luigi
Fundador
Fundador

Mensagens : 63
Data de inscrição : 22/07/2013
Idade : 23
Localização : CODE.ME company

Ver perfil do usuário http://codeme.forumeiros.com

Voltar ao Topo Ir em baixo

Re: (Tutorial) WinAPI Eventos(pt2)

Mensagem por Voltz em Sab Ago 17, 2013 3:52 am

Ó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.Laughing 

_________________
_____lol!
avatar
Voltz
Novato
Novato

Mensagens : 7
Data de inscrição : 14/08/2013
Idade : 24
Localização : Barueri

Ver perfil do usuário

Voltar ao Topo Ir em baixo

Re: (Tutorial) WinAPI Eventos(pt2)

Mensagem por Conteúdo patrocinado


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

Voltar ao Topo


 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum