sessão 11 – Programação gráfica orientada a eventos (2ª versão)
Referências bibliográficas:
Capítulos 2-5 e 7-9 do Livro Windows NT 4 Programming
MSDN:
Introduction to Windows Programming in C++
https://msdn.microsoft.com/en-us/library/ff381398(v=vs.85).aspx
Mouse Input
https://msdn.microsoft.com/en-us/library/gg153549(v=vs.85).aspx
Keyboard Input
https://msdn.microsoft.com/en-us/library/gg153546(v=vs.85).aspx
Mouse Movement
https://msdn.microsoft.com/en-us/library/gg153550(v=vs.85).aspx
Dialog Boxes
https://msdn.microsoft.com/en-us/library/windows/desktop/ms632588(v=vs.85).aspx
Menus
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646977(v=vs.85).aspx
Windows Graphics Device Interface (GDI)
https://msdn.microsoft.com/en-us/library/dd145203(v=vs.85).aspx
Tutorial online: Win32 Fundamentals
http://www.functionx.com/win32/Lesson01.htm
Events
http://www.functionx.com/win32/Lesson05.htm
Object-Oriented Win32
http://www.functionx.com/win32/Lesson06.htm
Esta é a segunda revisão destes conteúdos, usar os recursos do win32 GDI:
1) adicionar recurso
2) escolher Icon
e apagar todos.. e ficar só com um.
3) aceder ao ID do recurso, e alterar para IDI_ICON_APP
4) adicionar um menu, com duas opções fixas e uma opção com submenus
o login, com popup a FALSE
e atribuir os ID a cada uma das opções.
5) as caixas de dialogo
e os componentes para a caixa de diálogo:
6) atalhos de teclas, aceleradores no windows
7) string table
ter um texto configurável, num recurso à parte. Utilidade: internacionalização da aplicação (tradução)
7) pointer
8) os comportamentos, usar o seguinte:
#include <windows.h>
#include <Windowsx.h>
#include <tchar.h>
#include "resource.h"
#define NUM_CLIENTES 3
#define LIST_SIZE 8
TCHAR* LIST_ITENS[] = {
TEXT("10€"),
TEXT("20€"),
TEXT("40€"),
TEXT("60€"),
TEXT("80€"),
TEXT("100€"),
TEXT("150€"),
TEXT("200€")
};
LRESULT CALLBACK TrataEventos(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TrataEventosLogin(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TrataEventosLevantar(HWND, UINT, WPARAM, LPARAM);
TCHAR szProgName[] = TEXT("Ficha8");
typedef struct {
unsigned int ID;
TCHAR username[16];
TCHAR password[16];
unsigned int saldo;
} cliente;
typedef struct {
unsigned int tipo; // 1 = depósito, 2 = levantamento
unsigned int quantia;
unsigned int ID;
} operacao;
typedef struct {
cliente clientes[NUM_CLIENTES];
operacao historico[200];
unsigned int numOperacoes;
} dados;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG lpMsg;
WNDCLASSEX wcApp;
HANDLE hAccel;
dados dadosPartilhados;
wcApp.cbSize = sizeof(WNDCLASSEX);
wcApp.hInstance = hInst;
wcApp.lpszClassName = szProgName;
wcApp.lpfnWndProc = TrataEventos;
wcApp.style = CS_HREDRAW | CS_VREDRAW;
wcApp.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_APP));
wcApp.hIconSm = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_APP));
wcApp.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_POINTER));
wcApp.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_PRINCIPAL);
wcApp.cbClsExtra = sizeof(dados);
wcApp.cbWndExtra = 0;
wcApp.hbrBackground = CreateSolidBrush(RGB(220, 220, 220));
if (!RegisterClassEx(&wcApp))
return(0);
hWnd = CreateWindow(
szProgName,
TEXT("SO2 - Ficha 8"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
300,
150,
(HWND)HWND_DESKTOP,
(HMENU)NULL,
(HINSTANCE)hInst,
0);
dadosPartilhados.numOperacoes = 5; // Apenas para testar...
LONG_PTR x = SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)&dadosPartilhados);
ShowWindow(hWnd, nCmdShow);
hAccel = LoadAccelerators(NULL, MAKEINTRESOURCE(IDR_ACCELERATOR));
while (GetMessage(&lpMsg, NULL, 0, 0))
{
if (!TranslateAccelerator(hWnd, hAccel, &lpMsg))
{
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
}
return((int)lpMsg.wParam);
}
LRESULT CALLBACK TrataEventos(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
TCHAR str1[512], str2[512];
dados* dadosPartilhados;
dadosPartilhados = (dados*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch (messg)
{
case WM_CREATE:
EnableMenuItem(GetMenu(hWnd), ID_CONSULTA, MF_DISABLED | MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), ID_LEVANTAMENTOS, MF_DISABLED | MF_GRAYED);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_LOGIN:
DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG_LOGIN), hWnd, TrataEventosLogin);
EnableMenuItem(GetMenu(hWnd), ID_CONSULTA, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_LEVANTAMENTOS, MF_ENABLED);
break;
case ID_CONSULTA:
case ID_ACCELERATOR_CONSULTA:
LoadString(NULL, IDS_STR_CONSULTA, str1, 512);
_stprintf_s(str2, 512, TEXT("%s (%d)"), str1, dadosPartilhados->numOperacoes);
MessageBox(hWnd, str2, TEXT("String Table"), MB_OK | MB_ICONINFORMATION);
break;
case ID_ACCELERATOR_LEVANTAMENTOS:
case ID_LEVANTAMENTOS:
DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG_LEVANTAMENTO), NULL, TrataEventosLevantar);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, messg, wParam, lParam);
break;
}
return(0);
}
LRESULT CALLBACK TrataEventosLogin(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
TCHAR username[16];
switch (messg)
{
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
GetDlgItemText(hWnd, IDC_EDIT_LOGIN, username, 16);
MessageBox(hWnd, username, TEXT("Username"), MB_OK | MB_ICONINFORMATION);
}
else if (LOWORD(wParam) == IDCANCEL)
{
EndDialog(hWnd, 0);
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
}
return FALSE;
}
LRESULT CALLBACK TrataEventosLevantar(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
int i;
switch (messg)
{
case WM_INITDIALOG:
HWND hwndList = GetDlgItem(hWnd, IDC_LIST_MONTANTES);
SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
for (i = 0; i < LIST_SIZE; i++)
SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)LIST_ITENS[i]);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_LIST_MONTANTES)
{
switch (HIWORD(wParam))
{
case LBN_DBLCLK:
HWND hwndList = GetDlgItem(hWnd, IDC_LIST_MONTANTES);
i = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0);
MessageBox(hWnd, LIST_ITENS[i], TEXT("ListBox"), MB_OK | MB_ICONINFORMATION);
break;
}
}
break;
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
}
return FALSE;
}
Alguns comentários:
#include <windows.h>
#include <Windowsx.h>
#include <tchar.h>
#include "resource.h" //aceder aos ids, macros simbólicas
#define NUM_CLIENTES 3
#define LIST_SIZE 8
TCHAR* LIST_ITENS[] = {
TEXT("10€"),
TEXT("20€"),
TEXT("40€"),
TEXT("60€"),
TEXT("80€"),
TEXT("100€"),
TEXT("150€"),
TEXT("200€")
};
//tratamento de eventos das janelas
LRESULT CALLBACK TrataEventos(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TrataEventosLogin(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TrataEventosLevantar(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK TrataEventosAcerca(HWND, UINT, WPARAM, LPARAM);
TCHAR szProgName[] = TEXT("Ficha8");
typedef struct {
unsigned int ID;
TCHAR username[16];
TCHAR password[16];
unsigned int saldo;
} cliente;
typedef struct {
unsigned int tipo; // 1 = depósito, 2 = levantamento
unsigned int quantia;
unsigned int ID;
} operacao;
//partilhar informação entre o mains e as funções de tratamentos de eventos
typedef struct {
cliente clientes[NUM_CLIENTES];
operacao historico[200];
unsigned int numOperacoes;
} dados;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG lpMsg;
WNDCLASSEX wcApp;
HANDLE hAccel;
dados dadosPartilhados; //partilha de recursos
wcApp.cbSize = sizeof(WNDCLASSEX);
wcApp.hInstance = hInst;
wcApp.lpszClassName = szProgName;
wcApp.lpfnWndProc = TrataEventos;
wcApp.style = CS_HREDRAW | CS_VREDRAW;
//para poder usar as macros fazer uso do MAKEINTRESOURCE
wcApp.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_APP));
wcApp.hIconSm = LoadIcon(hInst, MAKEINTRESOURCE(IDI_ICON_APP));
wcApp.hCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_POINTER));
wcApp.lpszMenuName = MAKEINTRESOURCE(IDR_MENU_PRINCIPAL);
wcApp.cbClsExtra = sizeof(dados);
wcApp.cbWndExtra = 0;
wcApp.hbrBackground = CreateSolidBrush(RGB(220, 220, 220));
if (!RegisterClassEx(&wcApp))
return(0);
hWnd = CreateWindow(
szProgName,
TEXT("SO2 - Ficha 8"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
300,
150,
(HWND)HWND_DESKTOP,
(HMENU)NULL,
(HINSTANCE)hInst,
0);
//partilha de recursos
dadosPartilhados.numOperacoes = 5; // Apenas para testar...
LONG_PTR x = SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)&dadosPartilhados);
ShowWindow(hWnd, nCmdShow);
//ciclo de processamentos das mensagens, dos atalhos
hAccel = LoadAccelerators(NULL, MAKEINTRESOURCE(IDR_ACCELERATOR));
while (GetMessage(&lpMsg, NULL, 0, 0))
{
if (!TranslateAccelerator(hWnd, hAccel, &lpMsg))
{
TranslateMessage(&lpMsg);
DispatchMessage(&lpMsg);
}
}
return((int)lpMsg.wParam);
}
LRESULT CALLBACK TrataEventos(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
TCHAR str1[512], str2[512];
dados* dadosPartilhados;
dadosPartilhados = (dados*)GetWindowLongPtr(hWnd, GWLP_USERDATA); //partilha de recursos
switch (messg)
{
case WM_CREATE:
//código de inicialização do sistema
EnableMenuItem(GetMenu(hWnd), ID_CONSULTA, MF_DISABLED | MF_GRAYED);
EnableMenuItem(GetMenu(hWnd), ID_LEVANTAMENTOS, MF_DISABLED | MF_GRAYED);
break;
case WM_COMMAND:
//a parte menos significativa trás o ID da opção da janela que deu origem ao WM_COMMAND
switch (LOWORD(wParam))
{
case ID_LOGIN:
//contexto, ID da macro da dialog box, o handler da janela principal, função para tratar o evento
DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG_LOGIN), hWnd, TrataEventosLogin);
EnableMenuItem(GetMenu(hWnd), ID_CONSULTA, MF_ENABLED);
EnableMenuItem(GetMenu(hWnd), ID_LEVANTAMENTOS, MF_ENABLED);
break;
//a parte menos significativa trás o ID da opção da janela que deu origem ao WM_COMMAND
case ID_CONSULTA:
case ID_ACCELERATOR_CONSULTA:
LoadString(NULL, IDS_STR_CONSULTA, str1, 512);
_stprintf_s(str2, 512, TEXT("%s (%d)"), str1, dadosPartilhados->numOperacoes);
MessageBox(hWnd, str2, TEXT("String Table"), MB_OK | MB_ICONINFORMATION);
break;
case ID_ACCELERATOR_LEVANTAMENTOS:
case ID_LEVANTAMENTOS:
DialogBox(NULL, MAKEINTRESOURCE(IDD_DIALOG_LEVANTAMENTO), NULL, TrataEventosLevantar);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, messg, wParam, lParam);
break;
}
return(0);
}
LRESULT CALLBACK TrataEventosLogin(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
TCHAR username[16];
switch (messg)
{
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
GetDlgItemText(hWnd, IDC_EDIT_LOGIN, username, 16);
MessageBox(hWnd, username, TEXT("Username"), MB_OK | MB_ICONINFORMATION);
}
else if (LOWORD(wParam) == IDCANCEL)
{
EndDialog(hWnd, 0);
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
}
return FALSE;
}
LRESULT CALLBACK TrataEventosLevantar(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
int i;
switch (messg)
{
case WM_INITDIALOG:
HWND hwndList = GetDlgItem(hWnd, IDC_LIST_MONTANTES);
SendMessage(hwndList, LB_RESETCONTENT, 0, 0);
for (i = 0; i < LIST_SIZE; i++)
SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)LIST_ITENS[i]);
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDC_LIST_MONTANTES)
{
switch (HIWORD(wParam))
{
case LBN_DBLCLK:
HWND hwndList = GetDlgItem(hWnd, IDC_LIST_MONTANTES);
i = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0);
MessageBox(hWnd, LIST_ITENS[i], TEXT("ListBox"), MB_OK | MB_ICONINFORMATION);
break;
}
}
break;
case WM_CLOSE:
EndDialog(hWnd, 0);
return TRUE;
}
return FALSE;
}

















0 thoughts on “sessão 11 – Programação gráfica orientada a eventos (2ª versão)”