Сложение двух чисел в Visual Studio 2015 на C++ (Win32 WinAPI приложение)
В статье рассказывается как создать Win32 приложение сложения двух чисел в Visual Studio 2015 на C++.
Чтоб я еще когда-нибудь связался с этими Win32 приложениями! После опыта написания приложения прекрасно понимаю, почему никто не любит так программировать. Использовал, в частности, материал статей этой и этой.
Создание проекта
Создадим пустой
проект:
Добавление файла
Мы создали пустой проект, поэтому нужно самим добавить файл cpp
:
Написание кода основной программы
Вначале подключим инклуды и пропишем главную функцию:
#include <windows.h>
#include <tchar.h>
//Главная функция
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
}
Нам потребуются глобальные переменные:
// Глобальные переменные
static TCHAR szWindowClass[] = _T("win32app"); // Имя класса главного окна
static TCHAR szTitle[] = _T("Сложение двух чисел"); // Заголовок окна
Теперь в функции можем прописать описание нашего окна:
// Определим внешний вид окна
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; // Тут прописана та функция, в которой прописан главный функционал
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));:
Обратите внимание на строчку wcex.lpfnWndProc = WndProc;
. Тут прописана функция, в которой мы пропишем основной функционал. Её пропишем далее.
Далее можем зарегистрировать класс нашего окна:
// Зарегистрируем наше окно
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
Теперь создадим наше окно:
// Создадим окно
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
200, 200,//Размеры окна
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Создать окно не получилось"),
_T("Ошибка"),
NULL);
return 1;
}
Запустим его:
// Теперь можем запустить наше окно
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
Жесть! Сколько уже кода написано!
Ну, а потом начнем слушать сообщения от операционной системы Windows:
// Слушаем сообщения от ОС
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
Пропишем болванку функции WndProc
, о которой мы уже говорили выше:
// Главный функционал
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return 0;
}
Сейчас код программы выглядит так:
#include <windows.h>
#include <tchar.h>
// Глобальные переменные
static TCHAR szWindowClass[] = _T("win32app"); // Имя класса главного окна
static TCHAR szTitle[] = _T("Сложение двух чисел"); // Заголовок окна
// Список функций
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
// Главная функция
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// Определим внешний вид окна
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; // Тут прописана та функция, в которой прописан главный функционал
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
// Зарегистрируем наше окно
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
// Создадим окно
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
200, 200,//Размеры окна
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Создать окно не получилось"),
_T("Ошибка"),
NULL);
return 1;
}
// Теперь можем запустить наше окно
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Слушаем сообщения от ОС
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return 0;
}
У нас будет два поля для ввода текста, одно поле для вывода и кнопка. Для каждого контрола создадим свой идентификатор уникальный. По нему потом будем искать нужен контрол:
// Идентификаторы наших контролов: полей ввода и кнопки
#define EDIT1 110
#define EDIT2 111
#define EDIT3 112
#define BUTTON 113
Теперь в функции WndProc
создадим нужные контролы:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
// Первое число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"),
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 10, 85, 25, hWnd, HMENU(EDIT1), GetModuleHandle(NULL), NULL);
// Второе число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"),
TEXT("0"), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 45, 85, 25, hWnd, HMENU(EDIT2), GetModuleHandle(NULL), NULL);
// Сюда будем выводить результат
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"),
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 85, 85, 25, hWnd, HMENU(EDIT3), GetModuleHandle(NULL), NULL);
// Кнопка сложения
CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("+"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
115, 45, 30, 25, hWnd, HMENU(BUTTON), GetModuleHandle(NULL), NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Обратите внимание, где мы используем идентификаторы вроде такого HMENU(EDIT1)
.
При запуске программы мы увидим вот такое приложение:
Но пока кнопка не работает. В нашу функцию WndProc
добавим отслеживание нажатия на кнопку:
case WM_COMMAND:
switch (LOWORD(wParam))
{
case BUTTON:
//Тут наш код
return 1;
}
break;
Функция примет вид:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
// Первое число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"),
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 10, 85, 25, hWnd, HMENU(EDIT1), GetModuleHandle(NULL), NULL);
// Второе число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"),
TEXT("0"), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 45, 85, 25, hWnd, HMENU(EDIT2), GetModuleHandle(NULL), NULL);
// Сюда будем выводить результат
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"),
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 85, 85, 25, hWnd, HMENU(EDIT3), GetModuleHandle(NULL), NULL);
// Кнопка сложения
CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("+"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
115, 45, 30, 25, hWnd, HMENU(BUTTON), GetModuleHandle(NULL), NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case BUTTON:
//Тут наш код
return 1;
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Чтобы не захламлять код вынесем обработку клика кнопки в отдельную функцию:
// Функция сложения двух чисел
void Addition(HWND hWnd)
{
BOOL success = false;
int a = GetDlgItemInt(hWnd, EDIT1, &success, true);
if (!success) {
MessageBox(hWnd, TEXT("В первом поле не целое число"), TEXT("Ошибка"), MB_OK);
}
int b = GetDlgItemInt(hWnd, EDIT2, &success, true);
if (!success) {
MessageBox(hWnd, TEXT("Во втором поле не целое число"), TEXT("Ошибка"), MB_OK);
}
int c = a + b;
SetDlgItemInt(hWnd, EDIT3, c, true);
}
И в итоге получим вот такой полный код нашего приложения:
#include <windows.h>
#include <tchar.h>
// Идентификаторы наших контролов: полей ввода и кнопки
#define EDIT1 110
#define EDIT2 111
#define EDIT3 112
#define BUTTON 113
// Глобальные переменные
static TCHAR szWindowClass[] = _T("win32app");//Имя класса главного окна
static TCHAR szTitle[] = _T("Сложение двух чисел");//Заголовок окна
// Список функций
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void Addition(HWND hWnd);
// Главная функция
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// Определим внешний вид окна
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc; // Тут прописана та функция, в которой прописан главный функционал
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION));
// Зарегистрируем наше окно
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
return 1;
}
// Создадим окно
HWND hWnd = CreateWindow(
szWindowClass,
szTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
200, 200,//Размеры окна
NULL,
NULL,
hInstance,
NULL
);
if (!hWnd)
{
MessageBox(NULL,
_T("Создать окно не получилось"),
_T("Ошибка"),
NULL);
return 1;
}
// Теперь можем запустить наше окно
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);
// Слушаем сообщения от ОС
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
// Функция сложения двух чисел
void Addition(HWND hWnd)
{
BOOL success = false;
int a = GetDlgItemInt(hWnd, EDIT1, &success, true);
if (!success) {
MessageBox(hWnd, TEXT("В первом поле не целое число"), TEXT("Ошибка"), MB_OK);
}
int b = GetDlgItemInt(hWnd, EDIT2, &success, true);
if (!success) {
MessageBox(hWnd, TEXT("Во втором поле не целое число"), TEXT("Ошибка"), MB_OK);
}
int c = a + b;
SetDlgItemInt(hWnd, EDIT3, c, true);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
// Первое число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"),
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 10, 85, 25, hWnd, HMENU(EDIT1), GetModuleHandle(NULL), NULL);
// Второе число
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"),
TEXT("0"), WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 45, 85, 25, hWnd, HMENU(EDIT2), GetModuleHandle(NULL), NULL);
// Сюда будем выводить результат
CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("EDIT"), TEXT("0"),
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | WS_TABSTOP,
20, 85, 85, 25, hWnd, HMENU(EDIT3), GetModuleHandle(NULL), NULL);
// Кнопка сложения
CreateWindowEx(NULL, TEXT("BUTTON"), TEXT("+"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP,
115, 45, 30, 25, hWnd, HMENU(BUTTON), GetModuleHandle(NULL), NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case BUTTON:
Addition(hWnd);
return 1;
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
Ну, и монстр получился! Зато теперь всё работает:
Вот наше приложение и написано. Пока всё)
P.S. До этого WinAPI я никогда не занимался, и надеюсь, что в дальнейшим не придется! Так что помочь в каких-нибудь вопросах не смогу.
Тэги:
- C++
- Visual Studio
- Сложение двух чисел
Категории:
- blog
- it
- programming
В статье рассказывается как создать Win32 приложение сложения двух чисел в Visual Studio 2015 на C++.
В статье рассказывается как создать Win32 приложение сложения двух чисел в Visual Studio 2015 на C++.