=-=[ Programando API em C++ para Windows ]=-= Por: Vo Essa matéria é em homenagem à meu chegado, Inferninh0. É mais como desculpa pela minha primeira matéria que saiu um lixo, espero que essa compense =] C++ API Não vou dar noções básicas sobre C/C++. A interface API (Application Program Interface) corresponde a um conjunto de system calls oferecidas por um determinado sistema operacional. Neste caso, Windows. A biblioteca API de Windows é extensa, contendo as mais variadas funções. Não pretendo citar todas, mas sim as que eu considerar mais importantes, mesmo assim, pretendo fazer um trabalho extenso. Para não tornar essa matéria um tanto monótona, vou restringi-la à explicação à nível superficial. Não entrarei em detalhes como estrutura das funções, pois isso somente consumirá mais e mais bytes. Um dos maiores atrativos do Windows é seu sistema de janelas, que permite ao usuário navegar entre elas e coloca-las à disposição mais conveniente. Programadores de VB sabem o quanto é fácil criar uma janela, mas em C++, isso pode se tornar um processo que requer alguns procedimentos iniciais. Primeiramente vamos analisar a estrutura mais básica de um programa Win32 em C++: #include int _stdcall WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR nCmdLine, int nCmdShow) { return 0; } Para manter compatibilidade, a função é declarada como _stdcall, porém em alguns compiladores pode estar definida como WINAPI ou outras macros. A função WinMain tem como objetivo definir o inicio do programa. É relativamente semelhante à função main, só que é executada em contexto Win32 hehe. Os parâmetros são bem simples: Antes, o int de retorno: Da mesma maneira que a função main(), quando a função WinMain() retornar um valor, esta finalizará o programa. HINSTANCE: a HINSTANCE representa um valor de 32 bit´s que identifica um objeto no sistema. O sistema operacional passa este valor para o aplicativo para identificar o aplicativo enquanto ele está sendo executado e o libera quando o aplicativo é finalizado. A primeira HINSTANCE (hInstance) refere-se ao valor de identificação passado ao aplicativo. A segunda (hPrevInstance) refere-se á um valor curioso, é nela que vc recebe o valor da HINSTANCE de outra instância de seu aplicativo, dessa maneira você pode monitorar se seu aplicativo está sendo executado mais de uma vez e bloquear as instanciações de seu programa, caso o programa esteja sendo executado primariamente, esse valor passa a ser NULL. LPSTR é uma implementação de char*. nCmdLine corresponde á linha de comando passada ao seu aplicativo, ou, aos parâmetros á ele passados. Como um simples exemplo posso citar o Internet Explorer. A linha de comando á ele passada corresponde à página que será exibida. nCmdShow corresponde a um valor identificando o estado inicial da janela, é recomendável que esse valor seja passado como 2º parâmetro de ShowWindow(). Aí está o ponto de entrada para qualquer programa Win32. Como esse tutorial tem como foco a criação de um programa Win32, iremos direto ao ponto: Como criar uma simples janela? A API do Windows fornece uma estrutura que descreve os comportamentos padrões para qualquer janela. Um tópico importante, é que num ambiente de programação em C++ todas as classes e estruturas são consideradas como objetos. Essa visão se traduz no Windows quando falamos sobre janelas e controles. Tanto uma janela quanto um controle são objetos primários na construção de um aplicativo Win32, e, pela analise do Windows, são iguais. Uma janela corresponde à uma área (geralmente retangular) num espaço virtual conhecido como desktop, não seria correto afirmar que um controle não passa de uma janela dentro de um espaço conhecido como outra janela qualquer? É assim que você deve interpretar janelas e controles, não como estruturas que diferem entre si, mas estruturas semelhantes entre si. A API do Windows fornece uma estrutura básica para qualquer janela, que, geralmente em controles já é predefinida. Essa estrutura é conhecida como WNDCLASS. Como essa estrutura é pertencente à API do Win95, ficou atrasada para as evoluções do software, assim sendo, foi criada uma estrutura equivalente, que possui mais opções, a WNDCLASSEX. Ao longo do tutorial, você verá muitas funções e estruturas que foram recriadas com o sufixo EX, porém todas as funções e estruturas mais antigas prevalecem ainda hoje. Por razões de compatibilidade vou citar mais as funções EX (EXtended) do que as mais antigas. A estrutura WNDCLASSEX possui os seguintes membros: cbClsExtra – Corresponde à um valor em bytes que devem ser alocados depois da WNDCLASSEX na memória, o Windows inicializa este valor como zero. cbSize – Um unsigned int que corresponde ao tamanho da estrutura, geralmente um sizeof(WNDCLASSEX) é suficiente ;] cbWndExtra – Um valor que corresponde ao número de bytes que devem ser alocados após a instância da janela, o Windows inicializa esse valor como zero, porém é recomendável que este valor seja alterado para DLGWINDOWEXTRA caso você deseje utilizar caixas de diálogos criadas com WNDCLASSEX. hbrBackground – Um HBRUSH que corresponde ao fundo inicial da janela, geralmente esse valor é igualado à um dos valores predefinidos do sistema, como WINDOW_COLOR. hCursor – Corresponde à um HCURSOR que representa o cursor que será exibido dentro da janela. hIcon – Corresponde ao Ícone grande a ser exibido representando a janela, como no menu de alt+tab. hIconSm – Corresponde ao ícone pequeno a ser exibido na barra de título da janela. hInstance – Corresponde à instância que identifica um objeto no sistema, esse valor é passado ao programa para que ele não possa acessar objetos externos à seu processo indevidamente. Deve-se atribuir à esse valor a hInstance que foi passada à função WinMain. lpfnWndProc – Corresponde à uma função que recebe as mensagens enviadas à janela, em termos de leigo, corresponde à função responsável por gerenciar os eventos que ocorrem dentro da janela. lpszClassName – Corresponde à uma string que identifica a classe. lpszMenuName – Corresponde à uma string que aponta para o nome de menu associado à esta janela. Este tipo de menu é criado no arquivo de resources do aplicativo. Caso o valor seja identificado como um inteiro no arquivo de resource, deve-se utilizar a macro MAKEINTRESOURCE. style – Corresponde à um comportamento padrão da janela. Qualquer um destes membros pode ser validado como NULL, porém alguns são essenciais na construção de uma janela. Agora vamos analisar algumas peculiaridades de alguns deles. A WNDCLASS não apresenta os seguintes valores: cbSize e hIconSm. hbrBackground Esta propriedade refere-se à um HBRUSH que identifica o tipo de fundo que uma janela receberá. É recomendável que se utilize somente cores. Há valores padrões do sistema que podem ser utilizados: COLOR_ACTIVEBORDER COLOR_ACTIVECAPTION COLOR_APPWORKSPACE COLOR_BACKGROUND COLOR_BTNFACE COLOR_BTNSHADOW COLOR_BTNTEXT COLOR_CAPTIONTEXT COLOR_GRAYTEXT COLOR_HIGHLIGHT COLOR_HIGHLIGHTTEXT COLOR_INACTIVEBORDER COLOR_INACTIVECAPTION COLOR_MENU COLOR_MENUTEXT COLOR_SCROLLBAR COLOR_WINDOW COLOR_WINDOWFRAME COLOR_WINDOWTEXT hCursor Assim como hIcon e hIconSm, este valor pode ser criado no arquivo de resource, porém há tipos predefinidos de cursors que podem ser carregados utilizando-se a função LoadCursor, passando o primeiro valor (hInstance) como NULL e o segundo como o valor a ser utilizado: IDC_APPSTARTING IDC_ARROW IDC_CROSS IDC_IBEAM IDC_ICON IDC_NO IDC_SIZE IDC_SIZEALL IDC_SIZENESW IDC_SIZENS IDC_SIZENWSE IDC_SIZEWE IDC_UPARROW IDC_WAIT hIcon e hIconSm Podem ser carregados valores do sistema utilizando-se a função LoadCursor, passando o primeiro valor como NULL e o segundo como o valor a ser utilizado: IDI_APPLICATION IDI_ASTERISK IDI_EXCLAMATION IDI_HAND IDI_QUESTION IDI_WINLOGO lpfnWndProc O Window Procedure é uma função responsável por gerenciar as mensagens recebidas em uma janela. A sintaxe do Window Procedure é: LRESULT CALLBACK WinProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); O valor de retorno corresponde a um long. HWND é um unsigned int que corresponde ao valor do window handle, ou seja, um valor utilizado para a manipulação da janela. Msg corresponde ao valor numérico da mensagem recebida pela janela, wParam corresponde à um DWORD com valores passados à Msg, o mesmo vale para lParam. style Define estilos padrões que alteram a performance da janela: CS_BYTEALIGNCLIENT e CS_BYTEALIGNWINDOW Alinham a janela em um determinado contexto na posição horizontal para melhorar a performance em operações gráficas. Estes estilos afetam a posição horizontal e largura da janela. Não é muito utilizado CS_CLASSDC Aloca um DC para ser utilizado por todas as janelas da classe. É utilizado para diminuir o tempo de espera em operações gráficas. Este estilo permite que somente uma janela manipule operações gráficas por vez CS_DBLCLKS Permite que a janela receba mensagens sobre cliques duplos (DblClick) CS_GLOBALCLASS Permite que uma janela seja criada sem a necessidade que a hInstance da classe seja a mesma da janela. É utilizada em controles que são inicializados em DLLs CS_HREDRAW e CS_VREDRAW Redesenha toda a janela caso esta seja modificada horizontalmente ou verticalmente respectivamente. Tanto vale para movimentações como para reajustes de tamanho CS_NOCLOSE Desabilita todas as opções naturais para se fechar uma janela CS_OWNDC Aloca um DC único para cada janela da classe CS_PARENTDC Permite que janelas Child possam realizar operações gráficas em suas janelas pai. Essa opção aumenta a performance de operações gráficas, já que uma janela dessa classe recebe um cachê de memória maior para alocar seu DC CS_SAVEBITS Caso uma janela seja parcialmente obscurecida por outra janela, essa opção salva a parte obscurecida como um bitmap na memória para aumentar a rapidez no processo de redesenhar a janela, porém um certo tempo é perdido para alocar o bitmap. Essa opção não é recomendada DC´s serão explicados mais tarde. Operações gráficas referem-se ao ato de desenhar uma janela ou controle ou outras funções GDI. Um simples exemplo da construção de uma WNDCLASSEX: WNDCLASSEX wnd; wnd.cbClsExtra = 0; wnd.cbSize = sizeof(WNDCLASSEX); wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH)(COLOR_WINDOW); wnd.hCursor = LoadCursor(NULL,IDC_ARROW); wnd.hIcon = LoadIcon(NULL,IDI_APPLICATION); wnd.hIconSm = LoadIcon(NULL,IDI_APPLICATION); wnd.hInstance = hInstance; wnd.lpfnWndProc = (WNDPROC) WProc; wnd.lpszClassName = "MainWnd"; wnd.lpszMenuName = NULL; wnd.style = CS_OWNDC; Programadores mais “avançados” podem estudar a sintaxe da WNDCLASSEX e montá-la em somente uma linha de código ;] Bom, após a criação da WNDCLASSEX, deve-se registrá-la para que possa ser utilizada pelos threads do processo em execução. Isso se faz com o auxílio da função RegisterClassEx. RegisterClassEx(&wnd); O único parâmetro é o endereço da WNDCLASSEX a ser registrada. Logicamente há seu equivalente para a WNDCLASS: RegisterClass(&WNDCLASS); Estas funções retornam um valor (ATOM) que identifica unicamente a classe no sistema. Caso haja erro, o valor de retorno é 0. Bom, e agora? Agora vamos a parte principal, a tão esperada função que realmente cria a janela, a CreateWindow(Ex). A CreateWindowEX() possui 12 parâmetros, enquanto que a CreateWindow() possui 11, sendo assim elas só diferem no parâmetro dwExStyle, que, logicamente, pertence à CreateWindowEx e não à CreateWindow. Vamos dar uma olhada nos seus parâmetros: dwExStyle – Esse valor é uma DWORD (int de 32 bit´s para os mais leigos) que relata à função alguns comportamentos extendidos referentes à janela. Veremos seus possíveis valores mais à frente. lpClassName – Esse valor refere-se ao nome da WNDCLASS registrada, ou seja deve ser o mesmo que lpszClassName da classe registrada. lpWindowName – Um valor que na maioria das vezes serve como string primária da janela. dwtyle – Comportamentos padrões das janelas. x e y – int´s que definem as posições horizontal e vertical (respectivamente) da janela (Left e Top). nWidth e nHeight – int´s que definem a largura e a altura da janela (respectivamente) (Width e Height). hWndParent – Corresponde à um HWND (calma aí) que identifica a janela pai da janela a ser criada. É recomendável que este valor não seja NULL, assim sendo, para janelas comuns, deve-se utilizar a função GetDesktopWindow(void); como parâmetro para este valor. hMenu – Identifica um Menu criado em API pertencente à esta janela. HInstance – Use sua imaginação ;] lpParam – Há muito esse parâmetro deixou de ser utilizado. Seu valor consiste em uma estrutura que contêm todos os valores acima citados e estes da função são substituídos pelos desta estrutura. Perda de memória, não? ;/ O valor de retorno corresponde à um HWND. O HWND, ou Window Handle, é um valor de 32 bit´s que identifica uma janela para que esta possa ser manipulada por diversas funções. Caso a função falhe, o retorno é NULL. Em API, toda função, quando retorna um erro, pode ter esse valor de erro re-adquirido com a função GetLastError(void), que retorna uma DWORD (int) com o valor de retorno da função que retornou o erro. Os possíveis valores para dwExStyle são: WS_EX_ACCEPTFILES Esta janela aceita arquivos arrastados até ela WS_EX_CLIENTEDGE Cria uma borda interna à área interna da janela WS_EX_CONTEXTHELP Inclui o botão de interrogação na barra de título da janela WS_EX_CONTROLPARENT Permite que seja possível navegar entre as janelas child desta janela utilizando-se a tecla TAB WS_EX_DLGMODALFRAME Cria bordas em janelas com o valor WS_POPUP em dwStyle WS_EX_LEFT e WS_EX_RIGHT Cria uma janela que possui propriedades de texto alinhado à esquerda (padrão) ou à direita, respectivamente WS_EX_LEFTSCROLLBAR e WS_EX_RIGHTSCROLLBAR Se a barra de rolagem estiver visível na janela, essas opções definem seu alinhamento, à esquerda ou à direita (padrão) respectivamente WS_EX_LTRREADING e WS_EX_RTLREADING O texto da janela é apresentado da ordem especificada, esquerda-para-direita (padrão) ou direita-para-esquerda. O segundo valor só funciona em línguas que possuem suporte para este tipo de escrita, como o Hebraico WS_EX_MDICHILD Cria uma janela child WS_EX_NOPARENTNOTIFY Especifica que uma janela child não irá notificar sua janela-pai sobre sua criação ou destruição WS_EX_OVERLAPPEDWINDOW Combina WS_EX_CLIENTEDGE e WS_EX_WINDOWEDGE WS_EX_PALETTEWINDOW Combina WS_EX_WINDOWEDGE, WS_EX_TOOLWINDOW e WS_EX_TOPMOST WS_EX_STATICEDGE Cria uma janela com uma borda (interna) em sua área externa, geralmente utilizados em controles estáticos WS_EX_TOOLWINDOW Cria uma janela geralmente utilizada como janela de ferramentas, com uma borda e fonte de título menores que o original. Esse tipo de janela não aparece na barra de tarefas ou no menu de ALT+TAB WS_EX_TOPMOST Especifica que a janela deve sempre sobrepor as janelas que não possuem este valor WS_EX_TRANSPARENT Cria uma janela 100% transparente (não translúcida ;|). Este tipo de janela é comumente utilizado em operações de realinhamento de janela. Este tipo de janela não é, geralmente, utilizado por aplicativos WS_EX_WINDOWEDGE Cria uma janela com uma borda (externa) em sua área externa Para x,y, nWidth e nHeight, o sistema provê valores padrões que podem ser utilizados igualando estes valores à CW_USEDEFAULT. Os possíveis valores de dwStyle: WS_BORDER Cria uma janela com uma borda fina WS_CAPTION Cria uma janela com uma barra de título e WS_BORDER WS_CHILD e WS_CHILDWINDOW Cria uma janela child. Este valor não pode ser mesclado com WS_POPUP WS_CLIPCHILDREN Exclui a área ocupada pelas janelas child quando uma janela receber uma mensagem WM_PAINT (operação gráfica). Esse valor deve ser utilizado em janelas pai WS_CLIPSIBLINGS Esse valor evita alguns problemas gráficos com janelas child. Você mesmo poderá fazer um teste utilizandp 2 janelas child, uma com este valor e outra sem, coloque uma sobre a outra e mude-as de tamanho e posição ;] WS_DISABLED Cria uma janela desabilitada. Esse tipo de janela não recebe entrada do usuário WS_DLGFRAME Cria uma borda que é comumente utilizada em caixas de diálogo WS_GROUP Especifica o primeiro controle em um grupo de controles WS_HSCROLL e WS_VSCROLL Cria uma janela que possui uma barra de rolagem horizontal e/ou vertical (respectivamente) WS_ICONIC e WS_MINIMIZE Cria uma janela que está inicialmente minimizada WS_MAXIMIZE Cria uma janela que está inicialmente maximizada WS_MAXIMIZEBOX e WS_MINIMIZEBOX Cria uma janela que possui um botão de maximizar e/ou minimizar (respectivamente) WS_OVERLAPPED e WS_TILED Cria uma janela que possui uma borda e uma barra de titulo WS_OVERLAPPEDWINDOW e WS_TILEDWINDOW Cria uma janela num estilo mais comum mesclando WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX e WS_MAXIMIZEBOX WS_POPUP Cria uma janela popup, sem bordas ou barra de titulo WS_POPUPWINDOW Mescla WS_BORDER, WS_POPUP e WS_SYSMENU WS_SIZEBOX e WS_THICKFRAME Cria uma janela que possui uma barra de reajuste de tamanho WS_SYSMENU Cria uma janela com um menu de janela comum. O valor WS_CAPTION é recomendado WS_TABSTOP Especifica um controle que pode receber o foco quando o usuário pressiona a tecla TAB WS_VISIBLE Cria uma janela que esta inicialmente visível Exemplo =D: HWND MainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,"MainWnd","Janela de exemplo", WS_OVERLAPPEDWINDOW,120,150, CW_USEDEFAULT,450,GetDesktopWindow(),NULL,hInstance,NULL); Uma simples verificação: If(!MainWnd){PostQuitMessage(0);} A função PostQuitMessage(int) finaliza o programa terminando o seu Message Loop que será visto adiante. Após a criação da janela, se esta não houver sido criada com WS_SHOW, é necessário mostrá-la. Para isso utiliza-se ShowWindow(HWND, int). Exemplo: ShowWindow(MainWnd,SW_SHOWNORMAL); Os valores do 2º parâmetro são: SW_HIDE - Esconde a janela e passa o foco para a próxima janela SW_MAXIMIZE - Maximiza a janela e recebe o foco SW_MINIMIZE – Minimiza a janela e recebe o foco SW_RESTORE - Restaura a janela a seu status padrão e recebe o foco SW_SHOW – Mostra a janela e recebe o foco SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED – Mostra a janela e a maximiza ou minimiza (respectivamente) SW_SHOWMINNOACTIVE – Minimiza a janela e não recebe foco SW_SHOWNA – Mostra a janela em seu estado atual, não recebe o foco SW_SHOWNOACTIVE – Mostra a janela em sua posição e tamanho recentes, não recebe o foco SW_SHOWNORMAL – Mostra a janela, faz o mesmo que SW_RESTORE e recebe o foco nCmdShow – Isso mesmo, este é o valor passado ao aplicativo por WinMain, que pode ser utilizado como valor padrão para o inicio das janelas do aplicativo. O valor de retorno é um bool. Caso a janela estivesse anteriormente escondida, o valor de retorno é false (0), caso contrário é true (1). É comum utilizar também UpdateWindow(HWND); para redesenhar a janela após mostra-la: UpdateWindow(MainWnd); Caso a função falhe, o valor de retorno (bool) é false. A partir daqui, caso você deseje que função subseqüentes sejam realizadas, pode incluí-las no código. Após tudo isso você pensa que acabamos com a WinMain??? Lembra-se que quando a função retorna um valor ou chega ao seu fim o programa termina? Então, como os programas Win32 rodam por tempo indefinido? Simples, com a utilização de um pequeno artifício chamado Message Loop. O Message Loop, como seu nome sugere, consiste em um loop no qual uma mensagem é analisada e enviada à janela. O loop consiste em 3 funções simples: GetMessage(&MSG,HWND,unsigned int, unsigned int); TranslateMessage(&MSG); DispatchMessage(&MSG) O MSG corresponde à um valor que identifica uma mensagem de sistema. Sintáxe comum de um message loop: MSG msg; while ( GetMessage(&msg,NULL,0,0) ) { TranslateMessage(&msg); DispatchMessage(&msg); } Um sistema de mensagens é um artifício do sistema operacional para coordenar a comunicação entre processos e não será abordado aqui. A descrição do loop é simples: while ( GetMessage(&msg,NULL,0,0) ) Esse linha simplesmente cria um loop no qual a função GetMessage pega a primeira mensagem na fila de mensagens do thread atual. O fato de que as mensagens correspondem ao thread atual e não à uma janela especifica provêm de que o segundo parâmetro é neutro, e assim deve permanecer, pois, caso uma janela seja descrita, com o fechamento de tal janela o aplicativo todo seria finalizado de maneira indesejável. O valor de retorno (bool), é true em casos normais, é false quando é processada uma mensagem WM_QUIT (Assim como a enviada por PostQuitMessage()) e –1 quando a função falha. Caso você feche a janela descrita em HWND, a função retornaria –1 para o while gerando, assim, um erro fatal ao aplicativo. Por estas razões, no message loop, HWND deve sempre ser NULL. O 3º parâmetro indica a primeira mensagem na fila e o 2º, a última. Estes valores devem ser 0 para que as mensagens sejam processadas assim que chegarem à fila. TranslateMessage(&msg); Essa função traduz mensagens que apresentam códigos virtuais para código ASCII. Tais mensagens são geralmente enviadas somente pelo teclado. DispatchMessage(&msg); Essa função envia a mensagem para a WindowProc responsável pela janela que recebeu a mensagem. Após o message loop, pode-se incluir normalmente o return ;] return 0; Aí está uma simples WinMain. Agora, vamos à WindowProc, que analisará as mensagens enviadas para a janela. Como já vimos, a sintaxe do Window Procedure é: LRESULT CALLBACK WinProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); E o valor de retorno corresponde a um long. O primeiro parâmetro da função corresponde ao HWND da janela responsável por receber a mensagem. O segundo, à mensagem em si, o terceiro e o quarto à demais parâmetros da mensagem. O método mais comum de se trabalhar com o WinProc é dando um switch e verificando as mensagens enviadas: LRESULT CALLBACK WinProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_DESTROY:{ PostQuitMessage(1); } case WM_CREATE:{ FazAlgumaCoisa(); } } return DefWindowProc(hWnd,msg,wParam,lParam); } As mensagens aí enviadas correspondem, respectivamente, à quando a janela é finalizada e criada. DefWindowProc corresponde à uma função que recepta as mensagens que não são processadas pela WinProc. Os parâmetros são os mesmos da WinProc. Essa função garante que todas as mensagens sejam receptadas de maneira correta. return 0; geralmente funciona também ;] As mensagens mais comuns são citadas a seguir com seus respectivos eventos: WM_ACTIVATE OnActivate, OnGetFocus, OnEnter WM_ACTIVATEAPP, WM_KILLFOCUS OnLostFocus, OnExit, OnDeactivate WM_CLOSE OnClose WM_COPY OnCopy WM_CREATE OnCreate, OnLoad WM_CUT OnCut WM_DESTROY OnDestroy WM_ENABLE OnEnable WM_HELP OnHelp WM_KEYDOWN OnKeyDown WM_KEYUP OnKeyUp WM_KILLFOCUS OnLostFocus, OnExit, OnDeactivate WM_LBUTTONDNLCLK OnDblClick (Botão esquerdo) WM_LBUTTONDOWN OnMouseDown (Botão esquerdo) WM_LBUTTONUP OnMouseUp (Botão esquerdo) WM_MBUTTONDBLCLK OnDblClick (Botão do meio) WM_MBUTTONDOWN OnMouseDown (Botão do meio) WM_MBUTTONUP OnMouseUp (Botão do meio) WM_MOUSEMOVE OnMouseMove WM_MOUSEWHEEL OnMouseWheel WM_MOVE OnMoved WM_MOVING OnMove WM_PAINT OnPaint, OnRepaint WM_PASTE OnPaste WM_QUIT OnTerminate WM_RBUTTONDNLCLK OnDblClick (Botão direito) WM_RBUTTONDOWN OnMouseDown (Botão direito) WM_RBUTTONUP OnMouseUp (Botão direito) WM_SETFOCUS OnActivate, OnGetFocus, OnEnter WM_SIZE OnResized WM_SIZING OnResizing, OnResize WM_TIMER OnTimer WM_UNDO OnUndo A partir daí você já está apto a monitorar suas próprias mensagens, mas, por enquanto, vamos montar um simples programa que não faça nada menos do que aquilo que aprendemos até agora, exceto o uso da função API SetWindowText(HWND,char *) que modifica a string da barra de título da janela (Caption): /*Programa simples de exemplo*/ #include #pragma hdrstop //diretiva de pré-processador LRESULT CALLBACK WinProc(HWND,UINT,WPARAM,LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR nCmdLine, int nCmdShow) { MSG msg; WNDCLASSEX wnd; wnd.cbClsExtra = 0; wnd.cbSize = sizeof(WNDCLASSEX); wnd.cbWndExtra = 0; wnd.hbrBackground = (HBRUSH) COLOR_WINDOW; wnd.hCursor = LoadCursor(NULL,IDC_ARROW); wnd.hIcon = LoadIcon(NULL,IDI_APPLICATION); wnd.hIconSm = LoadIcon(NULL,IDI_APPLICATION); wnd.hInstance = hInstance; wnd.lpfnWndProc = (WNDPROC) WinProc; wnd.lpszClassName = "Janela"; wnd.lpszMenuName = NULL; wnd.style = NULL; if(!RegisterClassEx(&wnd)){PostQuitMessage(0);} HWND handle = CreateWindowEx(NULL,"Janela","Janela de Exemplo", WS_OVERLAPPEDWINDOW,150,150,300,300,GetDesktopWindow(),NULL,hInstance,NULL); if(!handle){PostQuitMessage(0);} ShowWindow(handle,nCmdShow); UpdateWindow(handle); while(GetMessage(&msg,NULL,0,0)){ TranslateMessage(&msg); DispatchMessage(&msg); } return 0; } LRESULT CALLBACK WinProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch(Msg){ case WM_RBUTTONDOWN: SetWindowText(hWnd,"Clique direito"); break; case WM_LBUTTONDOWN: SetWindowText(hWnd,"Clique esquerdo"); break; case WM_MBUTTONDOWN: SetWindowText(hWnd,"Clique com botão do meio"); break; case WM_MOVE: SetWindowText(hWnd,"Janela movida"); break; case WM_SIZE: SetWindowText(hWnd,"Tamanho modificado"); break; case WM_KEYDOWN: SetWindowText(hWnd,"Tecla pressionada"); break; case WM_DESTROY: PostQuitMessage(0); } return DefWindowProc(hWnd,Msg,wParam,lParam); } /*Fim do programa! Este programa foi compilado em Visual Studio 6.0. A macro WIN_32_LEAN_AND_MEAN foi utilizada, embora não tenha sido citada aqui. O programa compilado está disponível aqui e possui 152 KB.*/ Bom, agora você já sabe criar uma janela simples e manipular as principais mensagens que podem vir a ocorrer. No próximo capítulo entraremos em detalhes nos controles simples de Windows, e ainda veremos alguns parâmetros das mensagens mais comuns e aprenderemos alguns truquezinhos ;]] Xor´s para todos ;]