Ir para conteúdo
Faça parte da equipe! (2024) ×

[C++] Programar para Windows - Interface Gráfica


lcsmail
 Compartilhar

Meu tópico merece ser colocado na quick list?  

  1. 1. Meu tópico merece ser colocado na quick list?

    • Sim
      0
    • Não
      0
    • Talvez
      0


Posts Recomendados

Objetivo:

 

Depois de tanto vir aqui para pedir ajuda, me deu vontade de contribuir. O objetivo desse tópico é elevar um pouco o nível de nossa programação(Falo da galerinha que tá começando). Mas não pensem que no tutorial vai ser utilizado algum IDE que ofereça suporte gráfico(botões prontos). Esqueçam o Visual C++ Express, esqueçam o C++ Builder, ou qualquer coisa do tipo. Simplesmente iremos utilizar o DevC++, que é gratuito. Vamos criar nossos botões na base do código.

 

Requisitos:

 

O DevC++ que pode ser encontrado em seu Site Oficial ou:

[DOWN]https://rapidshare.com/files/2950296202/devcpp-4.9.9.2_setup.exe[/DOWN]

[sCAN]VirusTotal - Free Online Virus, Malware and URL Scanner[/sCAN]

Entender Programação Orientada a Objetos(Pelo menos o básico.)

Conhecimentos básicos dos Componentes do Windows(Button, Label, Edit, ...)

Conhecimentos básicos de C++(Óbvio)

Tempo pra aprender(Não falei decorar, falei aprender.)

Vontade e Curiosidade de saber o que faz cada componente(Pois não vou explicar o que significa tudo.)

 

Programa que iremos criar:

 

Nós iremos utilizar um programa bem básico, para que todos entendam, afinal todo mundo sabe como funciona uma Calculadora. Se você espera que nossa Calculadora saia igual ao do Windows, suma desse tópico, afinal como eu falei, é pra ajudar os iniciantes. Iremos utilizar apenas um arquivo .cpp e nada mais.

Preparação:

 

1 - Instale o DevC++

2 - Clique em New -> Project-> Windows Application (Deixe marcado C++, e dê um nome se quiser.)

3 - Vai aparecer um monte de código, então apague tudo.

 

Parte 1 - Janela:

 

Copie esse código e Aperte F9(Compile e Run), escolha um local para salvar a calculadora e veja o resultado.

 

É necessário se cadastrar para acessar o conteúdo.

Depois de dar o F9, vai perceber que ela está vazia, vou agora explicar como que fazemos para criar um janela vazia assim, para abrigar nossos futuros botões.

Iremos usar 2 diretivas #include, para incluir o windows.h e o stdlib.h. O windows.h está aí para que possamos utilizar a janela com Interface Gráfica do Windows. O stdlib está aí porque iremos utilizar as funções atoi() e itoa() que serão explicadas mais tarde.

Para criar uma janela do windows é preciso basicamente de duas funções; WinMain e WindowProcedure.

 

A função WinMain é o inicio, é néla que se cria a estrutura WNDCLASS, preenche-se com dados e se regista RegisterClassEx (&wincl).

Nós aprenderemos apenas o que cada componente faz, sem alterá-los, por enquanto.

O que precisamos saber é que a função WinMain vai criar uma janela de Windows com os botões padrões(Minimizar, Maximizar e Fechar), vai também tornar a janela visivel e quando o usuário do programa interagir com essa janela ela vai executar a função WindowProcedure.

 

Por sua vez, a função WindowProcedure é a nossa função de trabalho, é lá que vamos definir as ações que serão executadas quando o usuário do programa clicou no botão A ou B, quando ele maximiza, minimiza ou clica no fechar. Tudo isto com apenas 4 variáveis que a função nos dá, hwnd, message, wParam e lParam.

 

hwnd é o manipulador, a nossa janela principal.

 

message é o espaço onde você vai definir as ações de cada botão, apenas te interessam três:

Usaremos WM_CREATE - Para confirmar que a janela principal foi criada, não confudir “janela criada” com “janela visivel”

Usaremos WM_COMMAND - Para especificar as ações que os botões farão quando alguém interagir com um objeto dentro da janela.

Usaremos WM_DESTROY - Aqui fica o comando a ser executado quando a janela for fechada. No nosso caso, PostQuitMessage (0);, caso você retire essa linha o programa fecha a interface gráfica, mas continua sendo executado no seu computador, te obrigando a fechar o processo com o gerenciador de tarefas.

wParam divide-se em duas partes, sendo de 32bits, divide-se em duas words de 16bits, e assim conseguimos extrair duas informações:

A parte alta “HIWORD(wParam)” te dá uma submensagem do WM_COMMAND (ex: BN_CLICKED quando alguem clicar num botão)

A parte baixa “LOWORD(wParam)” identifica o objeto a ser processado com um numero. (ex. 2400 quando alguem clicar no botão com id=2400)

 

lParam é usada juntamente com o GetLParam() e não a vamos útilizar.

 

A linha “return DefWindowProc (hwnd, message, wParam, lParam);” que está em default é algo que temos sempre de fazer. Não vamos modificar.

 

Parte 2 - Desenhando Objetos:

 

Copie esse código onde tem /* Parte 2 do Tut */, localizado acima da função WindowProcedure e NÃO APERTE F9 AINDA.

 

É necessário se cadastrar para acessar o conteúdo.

Vamos retirar as duas barras "//" da função "DesenharObjectos(hwnd,message,wParam,lParam); " na função WindowProcedure dentro do “case WM_CREATE:” para que ela possa ser executada. Agora sim Aperte F9(Compile e Run).

Ao executar o programa você vai notar que agora temos 3 Edits, 1 Label, e 4 Button, apesar de não funcionarem.

 

A janela principal foi criada pela função WinMain, esta executou a função WindowProcedure e enviou-nos a “message” de WM_CREATE que significa que a janela acabou de ser criada, tal como seria de esperar.

Fizemos com que um switch filtraste o momento de quando ela foi criada “case WM_CREATE:” então vamos aproveitar esse local de criação para desenhar os botões, edits etc.

Como a parte de desenhar objectos é algo extenso onde 90% do código é repetido, eu decidi criar uma outra função para não bagunçar a nossa função de trabalho que é a WindowProcedure.

A técnica que usei foi criar uma função sem retorno. A função vai-se chamar DesenharObjectos() e é dentro dela que vais desenhar tudo, se prestar atenção, a função transporta as 4 variáveis que já expliquei na Parte 1 do Tutorial, ela faz esse transporte porque convém carregar conosco as ferramentas já que vamos trabalhar em outro local..

Então a função “DesenharObjectos(hwnd,message,wParam,lParam) ;” apenas te transporta para outra parte do código ("lá pra cima" neste caso).

 

Antes da função DesenharObjectos() terá sempre que declarar as variáveis, neste caso vou declarar os objectos com que vou trabalhar:

Aqui estão os nomes dos teus 3 edits e dos 4 butoes

HWND EditNum1,EditNum2,EditTotal,ButtonMais,ButtonMenos ,ButtonVezes,ButtonDividir;

 

Vamos passar agora para dentro da função DesenharObjectos()(saltei a instrução “HINSTANCE g_inst;” de prepósito).

 

É necessário se cadastrar para acessar o conteúdo.

Logo no início da função temos isso:

 

É necessário se cadastrar para acessar o conteúdo.

Este pequeno código vai criar uma editbox, o processo de criação é igual para quase todos os objetos.

 

É necessário se cadastrar para acessar o conteúdo.

Esta linha diz que EditNum1 vai ser igual a um objeto criado pela função CreateWindowEx().

A função CreateWindowEx para ser executada precisa sempre de 12 parametros(no 5º parâmetro eu resumi os 4 seguintes) que são os seguintes (por ordem).

 

1º - Aparência do Objeto: Neste caso é “WS_EX_CLIENTEDGE” que dá o efeito 3d ao edit, experimente colocar um 0 em vez do “WS_EX_CLIENTEDGE” e corre o programa, ficou flat nao foi? (depois deixe do jeito que deveria ser.)

 

2º - Classe do objeto: Neste caso é “EDIT” porque queremos uma editbox, se quizessemos um botão teriamos que por “BUTTON", experimenta colocar “BUTTON”. Vai transformar num botão. (Não esqueça de desfazer.)

 

3º - Texto Default do Objeto: Neste caso o default é “5” experimenta por algo do tipo “rotfl”. (Não esqueça de desfazer.)

 

4º - Aparencia Específica do Objeto: Neste caso usamos 3 constantes: WS_VISIBLE|WS_CHILD|WS_BORDER. O WS_VISIBLE faz com que o objecto seja visivel, WS_BORDER faz que tenha uma borda/moldura neste caso 3d, WS_CHILD informa que o objecto está dentro de uma janela. Todas estas constantes são separadas por uma barra “|” para poder funcionar. Experimente adicionar ES_RIGHT e vai ver que ele alinhou o texto à direita. Lembre-se que pode adicionar o que quiser, 2, 5 ou 10 aparências malucas, apenas não esqueça da barra pra separar.

 

5º - Distancia da esquerda: Esquerda ou direita, se tiveres habituado a programação por objetos, fazes isto com alguma facilidade. Distancia do topo, essas coordenadas são sempre em pixels, se alterar os valores vais fazer com que o edit se mova pra cima ou para baixo. Logo depois vem a Largura e Altura que são autoexplicativos.

 

6º - Janela em que vai ser criado o objeto: Na Parte 1 do tutorial já te mostrei que hwnd era o ponteiro da nossa janela, como vamos querer colocar o objeto dentro da nossa janela mãe, só temos que indicar o apontador aqui “hwnd”.

 

7º - Numero de identificação: Neste caso é NULL, ou seja, não foi atribuído nenhum número ID a esta edit, isto porque não é necessário. Fica assim.

 

8º - Instância: Lembra que saltamos o “HINSTANCE g_inst;” na seção das variaveis? É aqui que devemos por o “g_inst” que é o manipulador da instância associada à nossa janela.

 

9º - lparam É sempre NULL.

 

Os objetos EditNum2 e EditTotal são editboxs iguais a esta que acabamos de criar, só muda o nome e as coordenadas onde vão ser desenhadas (porque senão ficavam todas umas em cima das outras, também muda o texto default, 3º parametro)

O aspecto diferente do código é porque eu compactei vários parâmetros na mesma linha note também que todos os 12 parametros são separados por virgulas ",".

 

Seguiremos o código até encontrarmos “ButtonMais = CreateWindowEx (

 

É necessário se cadastrar para acessar o conteúdo.

As anteriores eram “EDIT”, estes agora são “BUTTON”, o processo de criação é igual, mas neste caso o botão não precisa de WS_BORDER no 4º parametro, nem "WS_EX_CLIENTEDGE" no 1º como as editboxs, MAS tem um Número de Identificação no 10º!

Vou-te explicar o que é o Número de Identificação (ID).

O ID é um número que se atribui a um objeto, a atribuição é feita da seguinte maneira “(HMENU) NumeroAqui” neste caso defini que seria 1001. (se notar, no inicio do programa defini que “ID_BUTTONmais” seria igual a 1001;“#define ID_BUTTONmais 1001”)

Costuma-se usar “#define QualquerCoisa ID” porque é mais facil para programar com nomes do que com números. Este é um programa pequeno, sei que há 4 botões com os IDs: 1001 para o ButtonMais, 1002 para o ButtonMenos etc,etc, mas num programa grande convém sempre usar o #define para facilitar.

Quando o botão ButtonMais é clicado o Windows recebe as informações BN_CLICKED na variavel HIWORD(wParam) e o ID na LOWORD(wParam), BN_CLICKED é quando o user clica num botão, e se ele receber também 1001 é porque o ButtonMais foi clicado, 1002 foi o ButtonMenos, 1003 foi o ButtonVezes etc.

Resumindo: se ((HIWORD(wParam) == BN_CLICKED) && (LOWORD(wParam) == 1001)) é porque alguém clicou no botão de mais.

 

Seguimos o código até encontrar:

 

É necessário se cadastrar para acessar o conteúdo.

Sabemos que “BUTTON” faz botões, que “EDIT” faz editboxs, mas “STATIC” é novo!

“STATIC” é conhecido por Label, na nossa calculadora esta label é o sinal de igual “=”, é um objeto que não serve para nada, apenas aparece para fazer sentido na interface da nossa calculadora. Como este “STATIC” não vai fazer nada, não temos que atribuir variável nenhuma, nem tanto um ID.

 

Mais a frente teremos:

 

É necessário se cadastrar para acessar o conteúdo.

Antes de saber para que serve este pequeno código temos que ter a noção que:

o Windows se comunica com o nosso programa basicamente através de mensagens, envia mensagens, recebe mensagens, a função SendMessage() é composto por 4 parametros:

 

1º - Objeto destino: Este é o objeto a que é destinado a mensagem, no código a cima podemos ver que é o EditNum1.

 

2º - Mensagem enviada: Conforme a mensagem enviada, faz o objecto reagir de formas diferentes, no nosso caso a mensagem é WM_SETFONT, ou seja

o objecto vai trocar o seu tipo de letra, e o novo tipo de letra será enviado atravez do 3º parametro (wParam).

 

3º - wParam: Estamos no 3º parametro, e tu deves tar a perguntar “Como é que sabemos que o tipo de letra tem de ir como 3º parametro e como sabes que WM_SETFONT muda de letra? Minha Resposta: Simplesmente não sabemos decorado, para saber só tem uma solução: PESQUISA, isso mesmo, pesquisando durante a criação do programa.”

 

4º - lParam: Esse não se mexe.

 

Pois é, esta SendMessage() faz mudar o tipo de letra da caixa de texto EditNum1, a nova letra que vais usar é o tipo de letra DEFAULT_GUI_FONT (tipo default do windows).

Sim, é preciso dizer ao Windows que o tipo de letra que queremos é o default do Windows, experimenta tirar o “(WPARAM) GetStockObject(DEFAULT_GUI_FONT),” e colocar “(WPARAM) 0,”.

O resto do código até ao terminar da função DesenharObjector() apenas muda os tipos de letras aos restantes objectos da nossa janela, não deves ter dificuldades em decifrar.

 

Parte 3 - Fazendo os Objetos Funcionarem:

 

Vamos copiar a última parte do código, onde tem /* Parte 3 do Tut */" dentro do "case WM_COMMAND:" na WindowProcedure().

 

É necessário se cadastrar para acessar o conteúdo.

Tire as barras de comentários "/* */" nas variáveis antes da WindowProcedure() para que possam ser executadas. E é tudo!

Podes agora Compilar & Run para ver se está tudo OK. Calculadora terminada e a fazer funcionando.

 

Antes de analizar o código vamos analisar umas coisas.

O user ao clicar num dos quatro botões, o nosso programa vai executar a tua função de trabalho WindowProcedure() e ao executar essa função vai informar do seguinte:

Se a variável “message” for WM_COMMANDé porque o user fez qualquer coisa a um dos objetos dentro da tua janela mãe.

Se a HIWORD(wParam) for igual a BN_CLICKEDé porque essa “qualquer coisa” que o user fez, foi clicar num dos botões.

Se a LOWORD(wParam) for igual a 1002 é porque o botão clicado foi o ButtonMenos.

Agora vais atacar o problema comigo, seguindo o código dentro da função WindowProcedure()

Vais parar já nesse “switch (message)”, aqui só te interessa quando a “message” é igual a WM_COMMAND, por isso passa já para dentro da “case: WM_COMMAND” e começa a analisar as novas linhas de código que te dei nesta Parte 3 do Tutorial.

 

Neste momento já sabemos que o user fez “qualquer coisa” a um dos objeto dentro da tua janelinha, agora só temos que identificar o que é que ouser fez a esse objecto, e a variável HIWORD(wParam) informa-te isso.

HIWORD(wParam)pode ser muita coisa! HIWORD(wParam) pode ser igual aBN_PUSHED, BN_PAINT, BN_UNPUSHED, e BN_CLICKED, mas o que te interessa é quando ela é igual a “BN_CLICKED” ou seja, quando o user clica num objecto.

Então: if ((HIWORD(wParam) == BN_CLICKED)) vai filtrar todos os cliques.

 

Mais uma etapa concluida, todo o código que escreveres dentro deste “if” só vai ser executado se o user clicar (HIWORD(wParam)==BN_CLICKED) num objeto dentro da tua janela mãe (message==WM_COMMAND).

Ainda não sabe qual dos objetos (qual dos botões) foi clicado, mas já podes fazer uma coisa, que é guardar o que está dentro do EditNum1 e do EditNum2 para dentro de variáveis.

Então vamos a isso.

Todo o texto que está dentro de uma EditBox é considerado pelo Windows como uma string mesmo que sejam números é sempre uma string, por isso tens que criar uma variável string para guardar o texto da EditNum1 (primeiro valor), essa variável vai-se chamar s_valor1 do tipo string.

Já que está com a mão na massa, e como são duas EditBoxs pode criar já duas variáveis do tipo string.

 

Vais agora guardar o que está dentro das EditBoxs para as variáveis.

O que vais fazer é enviar uma mensagem ao Windows atravez do SendMessage() com os seguintes parametros (lembra que são preciso 4 parametros, como já te expliquei na Parte 2 do Tutorial, ao enviar um novo tipo de letra para os objetos)

 

Objecto destino: Esta é facil, o objecto que queremos é a EditNum1, então o primeiro parametro é “(HWND) EditNum1,”.

 

Mensagem enviada: Como queremos receber o texto dentro dessa EditBox, se pesquisar encontrará que a mensagem tem de ser EM_GETLINE. Então que “(UINT) EM_GETLINE,”.

 

Linha a ser enviada: Aqui temos que especificar qual linha é que queremos. Uma EditBox só tem uma linha, mas nem sempre, as EditBoxs podem ser também multiline. Sendo a tua EditBox monoline a linha é sempre igual a 1. Por isso, o 3º parametro é “(WPARAM) 1,

 

Ponteiro para a variável: Aqui oferecemos o ponteiro para a nossa variável onde quer que seja guardado o texto, s_valor1, como é ponteiro convem por o “&” antes. O que ele vai fazer é guardar o texto da linha nº 1, do objecto EditNum1 para a variável s_valor1. Então, 4º parametro é “(LPARAM) &s_valor1

 

O SendMessage()seguinte faz o mesmo que este, mas guardar o que está dentro do EditNum2 para a variável s_valor2 também do tipo string.

 

Já está! O que estava dentro das EditBoxs estão agora dentro das tuas variáveis s_valor1 e s_valor2.

Agora só tens que identificar qual dos botões foi clicado e fazer a respectiva operação logica “+” “-“ “*” ou “/”.

Podemos fazer uma coisa antes! Que é converter as strings em integers para que o compilador nos deixe somar, subtrair, multiplicar ou dividir.

Criei duas variáveis do tipo integer para guardar este novos integers.

Isto é algo básico de C, mas aqui vai: o include “stdlib.h” te oferece a função atoi() que converte strings em integers.

 

É necessário se cadastrar para acessar o conteúdo.

Ok, valor1 e valor2 sao agora variáveis com os valores numéricos correspondentes aos que o user introduziu na EditNum1 e na EditNum2.

Vamos finalmente identificar qual dos objetos o user clicou e efetuar a operação lógica usando as variáveis valor1 e valor2.

A parte baixa do wParam “LOWORD(wParam)” dá-te o ID do objecto usado, então se o ID for 1001 foi clicado o ButtonMais, se for 1002 foi o ButtonMenos etc.

Vais fazer um switch para isso.

 

É necessário se cadastrar para acessar o conteúdo.

Por fim, só temos que enviar o total para o EditNum3 que é este.

Antes disso, ainda temos que converter a variável total do tipo integer para uma do tipo String, para que o compilador te deixe enviar o resultado.

Mais uma vez, recorres a uma função da include “stdlib.h”, a função é a itoa ().

 

É necessário se cadastrar para acessar o conteúdo.

Crie mais uma variável chamada s_total do tipo string, para guardar o total da operação.

É esta que vai mostrar o resultado! Tem de ser atravez de outra SendMessage() para o Windows.

 

É necessário se cadastrar para acessar o conteúdo.

1º a SendMessage() tem como destino a EditTotal que é a EditBox de resultado.

 

2º a mensagem é WM_SETTEXT, que faz com que um objeto troque o seu texto, no caso de uma EditBox ela muda o texto dentro da caixa.

 

3º O wParam não é usado, por isso pode ser o que quiser (eu coloquei 0)

 

4º O lParam é um ponteiro para uma variável string, que neste caso é a nossa variável s_total, que é onde está o resultado que o utilizador quer.

 

FIM

 

Nesse ponto a calculadora está "perfeita".

Espero ter ajudado muita gente.

Link para o comentário
Compartilhar em outros sites

Zaphey, bota meu tópico no teu quick list? Acho que meu tópico pode ajudar mais gente se estiver na quick list, tou desesperado chamando sua atenção. (Obs: Não sei se isso é flood, tou em dúvida...)

 

Edit: Se eu tivesse floodando eu já teria sido punido, mas como é apenas pra adicionar meu post pra quick list ninguém liga...

postpunido.png

Link para o comentário
Compartilhar em outros sites

Este tópico está impedido de receber novos posts.
 Compartilhar

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...

Informação Importante

Nós fazemos uso de cookies no seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies , caso contrário, vamos supor que você está bem para continuar.