(Tutorial) WinAPI Introdução(pt1)

Ir em baixo

(Tutorial) WinAPI Introdução(pt1)

Mensagem por Willian Luigi em Ter Jul 23, 2013 12:02 am

Estou dando inicio a uma 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
- métodos de produção
- definição & estruturação: WinMain
- outros tipos de handles(filhos)


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

Primeira visão/Métodos de produção:

Well, vamos dar inicio lembrando de relance conceitos que aprendemos desde o Pawn até

o próprio C/C++/C#/Java dente outras linguagens quando desenvolvimento em modo CONSOLE.

Talvez alguns não percebam isso, mas quando estamos desenvolvendo em console,

sempre provemos da ajuda de uma função chamada MAIN.

Pois como já diz o próprio nome: Main = Principal, é a função que dá entrada

no nosso projeto, pois sem ela oque escrevemos em outros métodos auxiliares, criados pelo

desenvolvedor, não executariam a sua devida função.

Bom, lembrando disso, podemos fazer uma breve comparação.

Assim como temos o Main que dá a entrada ao nosso console,

no WinAPI temos o nosso WinMain(Definição padrão), que é o que dá entrada em nosso desenvolvimento desktop,

janelas, handles, etc...

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 da estrutura padrão do WinMain:
Código:

//Definição:
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int);

//Pronto para uso:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//hInstance, o handle da atual instância da aplicação.
//hPrevInstance, o handle da instância antiga da aplicação.
//lpCmdLine
//nCmdShow, controles de como a janela deve ser mostrada. Propriedades básicas abaixo:
/*
| - SW_HIDE (0): Esconde a janela atual e ativa outra.
| - SW_MAXIMIZE (3): Maximiza uma janela específica.
| - SW_MINIZE (6): Minimiza uma janela específica.
| - SW_RESTORE (9): Ativa e mostra a janela, caso esteja minimiza, caso esteja maximizada ele
|                     retorna a janela para o tamanho e para a posição padrão.
| - SW_SHOW (5): Ativa uma janela e a mostra em sua atual posição e tamanho.
*/
}

Definição da estrutura padrão do WinProcc:
Código:

//Definição:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

//Pronto para uso:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//hWnd, handle da janela que acionou o evento(botão, textboxes, labels, etc).
//message, id da mensagem recebida
//wParam, é uma forma de tratar eventos quando a requisição é por botões(F5, F6) etc..
//lParam, forma de tratar eventos quando a requisição vem do HWND.(Exemplo: clicar em um botão)
}


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

Definição & estruturação(WinMain):

Como já diz o nome do tutorial (Introdução), eu vou deixar para falar sobre a callback WndProcc no próximo tutorial, neste vou tratar especificamente da definição e utilização do WinMain.

Vamos lá, como já expliquei um pouco sobre a definição do winMain, vou mostrar um exemplo de uso

de acordo com um que fiz aqui para demonstrar nesse tutorial, nele estarei apenas criando

handles para o visual do hwnd principal, não estarei tratando sobre desgin propriamente dito,

pois eu não sou bom e nem tão criativo assim para mexer com cores, alinhamento, etc.

Exemplo de uso:
Código:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wcex; //Classe usada para fazer o cadastro de todos detalhes da nossa HANDLE principal.

wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style         = CS_HREDRAW | CS_VREDRAW; //Estilo da handle
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = 0;
wcex.hInstance     = hInstance; //Instância da handle atual do aplicativo.
wcex.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); //Icone que será utilizado(default neste caso)
wcex.hCursor     = LoadCursor(NULL, IDC_ARROW); //Cursor que será utilizado(default neste caso)
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //Cor de fundo da HANDLE principal
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"code.me"; //Nome da classe que iremos registrar, para poder adicionar outros hwnd como ferramentas
wcex.hIconSm     = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); //Handle do Icone pequeno associado a classe.

//hWnd, será a HANDLE principal que estaremos criando.
HWND hWnd = CreateWindow(
     L"code.me", // Nome da classe que definimos no nosso registro, para poder herdar as propriedades e os detalhes.
     L"code.me tutorial: Criando seu primeiro aplicativo(WinAPI).", // titulo da janela
     WS_OVERLAPPEDWINDOW, //estilo
     CW_USEDEFAULT, CW_USEDEFAULT, //posição da janela (x, y)
     500, 100, //tamanho da janela(width, height)
     NULL, // utilizado para associar a uma HANDLE pai, no caso da hwnd principal não usaremos, ou seja(null, 0)
     NULL, // utilizado para definir um nome 'abstrato' para podermos identificar quando fomos acionar um evento no winprocc
     hInstance, // instância utilizada.
     NULL
);

ShowWindow(hWnd, nCmdShow); //Utilizado para mostrar a HANDLE principal, sem isso a janela não aparece.

MSG msg; //instância de mensagens, utilizaremos para fazer o processo dos 'eventos'
while (GetMessage(&msg, NULL, 0, 0)) //Pegamos as mensagens enviadas pelo cliente, usuário
{
     TranslateMessage(&msg); //Traduzimos as mensagens para podermos interpretar pelo WinProcc
    
     DispatchMessage(&msg); //Enviamos as mensagens para o WinProcc
}

return (int) msg.wParam; // retorno = 0, valor do postQuitMessage
}
Este é um exemplo de como estruturamos a nossa callback que vai dar inicio ao projeto, tentei comentar ao máximo de uma forma entendível para todos, mas se caso sobrar dúvidas nós resolvemos isto ao longo dos comentáros.

Agora citarei um exemplo que eu costumo utilizar, que é com callbacks auxiliares, para manter a organização do código.

Não estarei comentando este, pois ele tem a mesma função do antigo acima, apenas está dividido.
Código:
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );

if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
     return 0;
    
MSG msg = {0};
while( GetMessage( &msg, NULL, 0, 0 ) )
{
     TranslateMessage( &msg );
     DispatchMessage( &msg );
}

return ( int )msg.wParam;
}

HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof( WNDCLASSEX );
wcex.style = CS_HREDRAW | CS_VREDRAW;
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);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"code.me";
wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
if( !RegisterClassEx( &wcex ) )
     return E_FAIL;

RECT rc = { 0, 0, 470, 240 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );

HWND g_hWnd = CreateWindow( L"code.me", L"code.me tutorial: Criando seu primeiro aplicativo(WinAPI).", WS_OVERLAPPEDWINDOW,
                         CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
                         NULL );
if( !g_hWnd )
     return E_FAIL;

ShowWindow( g_hWnd, nCmdShow );

return S_OK;
}
Como podem ver, eu dividi em duas callbacks, assim deixando uma responsável pelo registro, outra responsável pela inicialização.

Teve algumas modificações deste exemplo para o primeiro, como o seguinte código:
Código:
RECT rc = { 0, 0, 470, 240 };
Que eu preferi utilizar para definir o tamanho da HWND principal, é apenas preferência mesmo, mas dá no mesmo desta forma e da forma antiga.


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

Outros tipos de handles(filhos):

Bom, chegando ao fim, vamos agora falar um pouco sobre outros tipos de HWND(handles)

que podem ser criados com um estilo diferente do principal, que são os que são denominados de

handles filhos, que estabelecem um parêntesco com o handle principal(qual ?),

eles são impostos DENTRO do handle principal, exemplo: botões são um ótimo exemplo de hwnds filhos

que você associou a um pai(handle principal), atráves de uma pequena alteração no código

que vou lhes mostrar atráves de um exemplo reduzido, mas estarei explicando em comentários.

Vamos supor que já criamos toda a estruturação do WinMain, e lá onde inserimos a criação do hwnd principal:
Código:
//hWnd, será a HANDLE principal que estaremos criando.
HWND hWnd = CreateWindow(
     L"code.me", // Nome da classe que definimos no nosso registro, para poder herdar as propriedades e os detalhes.
     L"code.me tutorial: Criando seu primeiro aplicativo(WinAPI).", // titulo da janela
     WS_OVERLAPPEDWINDOW, //estilo
     CW_USEDEFAULT, CW_USEDEFAULT, //posição da janela (x, y)
     500, 100, //tamanho da janela(width, height)
     NULL, // utilizado para associar a uma HANDLE pai, no caso da hwnd principal não usaremos, ou seja(null, 0)
     NULL, // utilizado para definir um nome 'abstrato' para podermos identificar quando fomos acionar um evento no winprocc
     hInstance, // instância utilizada.
     NULL
);

Logo abaixo disto(por questões de organização de código), vamos meter os handles filhos que serão impostos ao handle principal, vejamos:
Código:
CreateWindow(
L"BUTTON", //Aqui o nome da classe será diferente, pois não pretendemos herdar detalhes da
//classe que registramos, pretendemos herdas detalhes de um BOTÃO, por isso classe: "BUTTON"
L"Procurar", //Título do botão
WS_CHILD + WS_VISIBLE, //Estilo do botão.
/*
| - WS_CHILD, estamos indicando que ele será FILHO de um hwnd pai.
| - WS_VISIBLE, estamos indicando que ele estára visível.
*/
270, 50, 70, 25, //Posição dentro da janela(hwnd pai)(x,y), tamanho do hwnd filho(width, height)
     hWnd, //Aqui está a diferença, estaremos indicando que ele será parente do handle principal(pertencerá)
NULL, //Aqui não estaremos atribuindo nada, pois ainda não aprendemos sobre WinProcc.
hInstance, //Instância do aplicativo.
NULL
);


Eu dei um exemplo sobre botões, mas podem ser herdadas outras classes também, deixarei uma lista de mais algumas abaixo:
Código:

BUTTON - Botões, que podem ser checkbox, radio, comando, etc...
COMBOBOX - caixa de combinações.
EDIT - textbox, caixa de texo.
LISTBOX     - Lista de opções.
STATIC     - Cria um objeto stático, exemplo: Label, texts de título, etc...
SCROLLBAR - Barra de rolagem.
OBS: Não citei todas, estou citando apenas as que eu considero mais importantes e utilizadas em um projeto básico/intermediário.


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

Conclusão:

No mais é isso, eu espero ter deixado algo importante para vocês,

caso tenham dúvidas ou dicas estarei esperando pelos comentários.

OBS: Só continuarei a parte 2, se tiver um bom aproveitamento deste tópico, então aguardo

comentário a respeito do mesmo,

abraços.


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

Referências:

Créditos: Willian Luigi (© code.me - 2013.1)

Agradecimentos: Gustavo Araújo, pela ideia.

_________________
<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 Introdução(pt1)

Mensagem por BrunnoVinicius em Qui Jul 25, 2013 3:40 am

Não consegui ler tudo pois está tarde aqui ,
mais estou pensando em me aprofundar mais em C++..
Oque acha ? vale a pena ? ..
Parabéns pelo tutorial...
avatar
BrunnoVinicius
Novato
Novato

Mensagens : 27
Data de inscrição : 25/07/2013
Idade : 20

Ver perfil do usuário

Voltar ao Topo Ir em baixo

Re: (Tutorial) WinAPI Introdução(pt1)

Mensagem por Willian Luigi em Qui Jul 25, 2013 4:39 am

BrunnoVinicius escreveu:Não consegui ler tudo pois está tarde aqui ,
mais estou pensando em me aprofundar mais em C++..
Oque acha ? vale a pena ? ..
Parabéns pelo tutorial...

Boa noite Brunno, eu só posso te dizer oque vale apena você aprender, quando eu souber oque você pretende seguir dentro do ramo. Smile

Dá um like na nossa page no facebook, ai você vai ficar atualizado dos tutoriais novos que eu estou dando entrada.

Abraços.

_________________
<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 Introdução(pt1)

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

gostei do tópico, muito interessante.

_________________
_____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 Introdução(pt1)

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