NovaMonoFix
Errores PHP
X
Usuario
Password
0 FPS

Tutorial WINAPI C++ 1.7 (Terminando la calculadora)

14 de Abril del 2010 por Josep Antoni Bover, 23 visitas, 0 comentarios, 0 votos
Categorías : Windows, Programación, C y C++.
La web está en segundo plano, animación en pausa.
Cargando animación...
Tutorial WINAPI C++ 1.7 (Terminando la calculadora)

Ya hemos llegado al punto en que ensamblaremos todo lo hecho anteriormente para formar nuestra calculadora. Si os digo la verdad nunca pensé que me curraría tanto el código para una calculadora, pero espero que eso os haya servido para familiarizaros con el API de Windows. Además no solo se ha hecho una calculadora, si no que también tenéis una base para hacer ventanas y controles para futuras aplicaciones.

Se podía haber hecho la calculadora utilizando controles de Windows y sin hacer objetos ni nada, a saco. Aunque probablemente no hubiera dado para enseñaros gran cosa, en cambio haciendo los botones, el marcador, nuestro objeto ventana y tal, espero que os hayan quedado claras cuatro cosas sobre las ventanas de Windows y el GDI.

En esta parte del tutorial no me queda gran cosa por mostrar, pero veremos la calculadora montada al fin, y también trataremos un poco el tema de enviar eventos.

Empezaremos por la declaración de la clase VentanaCalculadora, que será nuestro enlace entre los botones, el teclado y el marcador.

Archivo : Tutorial TerminandoCalculadora.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Objeto final : ObjetoHWND -> PlantillaEventos -> ObjetoVentana -> VentanaCalculadora
class VentanaCalculadora : public ObjetoVentana {
public : //////////// Miembros publicos
// -Constructor
VentanaCalculadora(void) { };
// -Destructor
~VentanaCalculadora(void) { };
//////////////////// Eventos
// -Reemplazamos el evento cerrar y añadimos la API PostQuitMessage
// De esta forma se cerrara la aplicación al cerrar la ventana
LRESULT Evento_Cerrar(void);
// -Re-emplazamos el evento ObjetoBoton_Click para enlazar los
// botones con el marcador
LRESULT Evento_ObjetoBoton_Click( ObjetoBoton *BotonPresionado,
const UINT Boton);
// -Re-emplazamos el evento Teclado_TeclaPresionada para enlazar
// los botones a las teclas correspondientes
LRESULT Evento_Teclado_Caracter( const UINT Caracter, const UINT Repeticion,
const UINT Params);
// -Función que crea la calculadora
void Crear(void);
protected : ///////// Miembros protegidos
// -Marcador de la calculadora y centro de operaciones
ObjetoMarcador Marcador;
// -Botones para cada función
ObjetoBoton Boton[10];
ObjetoBoton Boton_Punto;
ObjetoBoton Boton_Suma;
ObjetoBoton Boton_Resta;
ObjetoBoton Boton_Multiplicacion;
ObjetoBoton Boton_Division;
ObjetoBoton Boton_Resultado;
ObjetoBoton Boton_CE;
ObjetoBoton Boton_Borrar;
};

Se han re-emplazado 3 eventos, el cerrar para cerrar la aplicación con PostQuitMessage, el ObjetoBoton_Click para saber cuando se pulsa un botón de forma que se puedan mandar los datos necesarios al marcador, y el evento Teclado_Caracter que enlazara las teclas a los botones correspondientes.

Archivo : Tutorial TerminandoCalculadora.cpp
1
2
3
4
5
6
7
8
9
10
11
// Función que enlaza con el mensaje WM_CHAR
LRESULT VentanaCalculadora::Evento_Teclado_Caracter(const UINT Caracter, const UINT Repeticion, const UINT Params) {
UINT iBoton = 0;
switch (Caracter) {
case TEXT('0') : case TEXT('1') : case TEXT('2') : case TEXT('3') : case TEXT('4') :
case TEXT('5') : case TEXT('6') : case TEXT('7') : case TEXT('8') : case TEXT('9') :
iBoton = Caracter - TEXT('0');
SendMessage(Boton[iBoton].hWnd(), WM_LBUTTONDOWN, MAKELPARAM(5, 5), 0);
Sleep(50);
SendMessage(Boton[iBoton].hWnd(), WM_LBUTTONUP, MAKELPARAM(5, 5), 0);
return 0;

Podiamos haber enlazado las teclas directamente al marcador, pero entonces no se verían los botones de la calculadora presionados al pulsar una tecla. Hacer que los botones hagan el efecto de presión sobre ellos se puede hacer de varias formas, desde implementar unas funciones dentro del mismo botón, utilizar SendMessage o PostMessage para mandar mensajes directamente a su WindowProcedure, o llamar a las funciones evento que tiene el botón. En este caso lo vamos a hacer utilizando SendMessage para que así veáis un poco mas el funcionamiento de esta API.

La API SendMessage envía un mensaje al HWND especificado y espera a que sea procesado. También existe la API PostMessage que envía un mensaje al HWND especificado sin esperar a que sea procesado, ese mensaje se queda en cola y se procesara en cuanto sea posible. Por decirlo de otra forma SendMessage forzara el mensaje a que sea procesado, y al terminar nos dejara seguir con la ejecución de nuestro código, en cambio PostMessage proseguirá la ejecución de nuestro código, y luego cuando tenga tiempo libre procesara el mensaje.

En esta función en concreto si utilizáramos PostMessage, la llamada a Sleep seria inútil y probablemente ni se apreciaría el botón como se presiona al pulsar una tecla. Y para terminar la API Sleep lo que hace es dejar a la aplicación 'durmiendo' durante los milisegundos especificados, en este caso 50.

Ahora veamos la funcion Evento_ObjetoBoton_Click :

Archivo : Tutorial TerminandoCalculadora.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Función que enlaza con nuestro mensaje WM_BOTON_CLICK
LRESULT VentanaCalculadora::Evento_ObjetoBoton_Click(ObjetoBoton *BotonPresionado, const UINT Boton) {
const TCHAR *TextoBoton = NULL;
switch (BotonPresionado->ID()) {
case ID_BOTON0 : case ID_BOTON1 : case ID_BOTON2 : case ID_BOTON3 : case ID_BOTON4 :
case ID_BOTON5 : case ID_BOTON6 : case ID_BOTON7 : case ID_BOTON8 : case ID_BOTON9 :
TextoBoton = BotonPresionado->Texto();
Marcador.AgregarNumero(TextoBoton[0]);
break;
case ID_BOTON_SUMA : Marcador.AgregarOperacion(TipoDatos_Suma); break;
case ID_BOTON_RESTA : Marcador.AgregarOperacion(TipoDatos_Resta); break;
case ID_BOTON_MULTIPLICACION : Marcador.AgregarOperacion(TipoDatos_Multiplicacion); break;
case ID_BOTON_DIVISION : Marcador.AgregarOperacion(TipoDatos_Division); break;
case ID_BOTON_RESULTADO : Marcador.Resultado(); break;
case ID_BOTON_BORRAR : Marcador.BorrarCaracter(); break;
case ID_BOTON_CE : Marcador.CE(); break;
}
return 0;
}

Esta función se creó ante la necesidad de obtener cuando un ObjetoBoton es presionado, dicho objeto lo creamos con anterioridad en el tutorial, y cuando el ObjetoBoton recibía correctamente el Evento_Mouse_BotonSoltado mandaba un mensaje WM_BOTON_CLICK a su ventana padre con algunos parámetros. Esta forma de enlazar los mensajes es una de las mas acertadas a mi modo de ver, ya que es sencilla, fácil de implementar, y no requiere mucha parrafada de código.

En definitiva lo que hace esta función es mirar que botón se ha presionado, y le manda esa información al ObjetoMarcador.

Aquí termina el tutorial para hacer la calculadora, ahora viene el tutorial para hacer un juego como el nibbles / snake. Es el típico juego de la serpiente que crece y que no puede chocar con su cola : 2.0 - Introducción para empezar con el Snake.

Descargar tutorial WinAPI completo Calculadora compilada