2024-01-05 12:04
BullseyeCoverage 9.6.4
calc/ Calculator.cpp
1 // Win32 calculator sample application 2 3 #include <windows.h> 4 #include "CalcCore.h" 5 6 // Layout dimensions 7 enum Layout { 8 // Number of columns and rows 9 colCount = 4, 10 rowCount = 5, 11 // Space between buttons 12 margin = 10, 13 // Width and height of button 14 buttonSize = 44, 15 // Display size 16 displayWidth = colCount * (buttonSize + margin) - margin, 17 displayHeight = 20, 18 // Window size 19 width = margin + colCount * (buttonSize + margin), 20 height = margin * 2 + displayHeight + rowCount * (buttonSize + margin), 21 }; 22 // Button arrangement 23 const wchar_t buttonGrid[Layout::rowCount][Layout::colCount] = { 24 { 'C', L'²', L'√', L'÷' }, 25 { '7', '8', '9', L'×' }, 26 { '4', '5', '6', '-' }, 27 { '1', '2', '3', '+' }, 28 { L'±', '0', '.', '=' }, 29 }; 30 CalcCore core; 31 HWND display; 32 HINSTANCE instance; 33 34 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 35 { 36 LRESULT result = 0; 37 switch (message) { 38 case WM_COMMAND: 39 switch (wParam) { 40 case '+': 41 core.apply(CalcCore::Operation::add); 42 break; 43 case '-': 44 core.apply(CalcCore::Operation::subtract); 45 break; 46 case '.': 47a case '0': 47b case '1': 47c case '2': 47d case '3': 47e case '4': 47f case '5': 47g case '6': 47h case '7': 47i case '8': 47j case '9': 48 core.addNumberChar(char(wParam)); 49 break; 50 case '=': 51 core.apply(); 52 break; 53 case 'C': 54 core.clear(); 55 break; 56 case L'√': 57 core.apply(CalcCore::Operation::sqrt); 58 break; 59 case L'±': 60 core.apply(CalcCore::Operation::negate); 61 break; 62 case L'²': 63 core.apply(CalcCore::Operation::pow2); 64 break; 65 case L'×': 66 core.apply(CalcCore::Operation::multiply); 67 break; 68 case L'÷': 69 core.apply(CalcCore::Operation::divide); 70 break; 71 default: 72 throw "unknown command"; 73 } 74 SetWindowTextA(display, core.display()); 75 break; 76 case WM_CREATE: 77 display = CreateWindowEx(0, L"STATIC", L"0", SS_RIGHT | WS_CHILD | WS_VISIBLE, Layout::margin, Layout::margin, Layout::displayWidth, Layout::displayHeight, hWnd, 0, instance, nullptr); 78 { 79 for (unsigned i = 0; i < Layout::colCount; i++) { 80 for (unsigned j = 0; j < Layout::rowCount; j++) { 81 const wchar_t c = buttonGrid[j][i]; 82 const wchar_t text[2] = { c, 0 }; 83 const int x = Layout::margin + i * (Layout::buttonSize + Layout::margin); 84 const int y = 2 * margin + Layout::displayHeight + j * (Layout::buttonSize + Layout::margin); 85 CreateWindowEx(0, L"BUTTON", text, WS_CHILD | WS_TABSTOP | WS_VISIBLE, x, y, Layout::buttonSize, Layout::buttonSize, hWnd, HMENU(c), instance, nullptr); 86 } 87 } 88 } 89 break; 90 case WM_DESTROY: 91 PostQuitMessage(0); 92 break; 93 default: 94 result = DefWindowProc(hWnd, message, wParam, lParam); 95 break; 96 } 97 return result; 98 } 99 100 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR, int) 101 { 102 CalcCore::unitTest(); 103 instance = hInstance; 104 // Register window class 105 WNDCLASS wc = { }; 106 wc.lpfnWndProc = WndProc; 107 wc.hInstance = hInstance; 108 wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION); 109 wc.hCursor = LoadCursor(nullptr, IDC_ARROW); 110 wc.hbrBackground = HBRUSH(GetStockObject(WHITE_BRUSH)); 111 wc.lpszClassName = L"CalculatorWndClass"; 112 RegisterClass(&wc); 113 // Calculate main window size 114 RECT rect{ 0, 0, Layout::width, Layout::height }; 115 AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW & ~WS_OVERLAPPED, false); 116 const SIZE size{ rect.right - rect.left, rect.bottom - rect.top }; 117 // Create main window 118 const HWND hWnd = CreateWindowEx(0, wc.lpszClassName, L"Calculator", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, size.cx, size.cy, nullptr, nullptr, hInstance, nullptr); 119 // Message pump 120 try { 121 MSG msg; 122 while (GetMessage(&msg, 0, 0, 0)) { 123 DispatchMessage(&msg); 124 } 125 } 126 catch (const char* string) { 127 MessageBoxA(hWnd, string, "Error", MB_OK); 128 } 129 return 0; 130 }