Harrix Блог

  • Списки статей
    • Все статьи
    • IT
    • Qt
    • C++
    • Сложение двух чисел
    • Web программированиe
    • FAQ
    • Latex
    • Установка программ
    • Мифы
    • Видео
    • Про фото
  • Проекты
  • Harrix.org
  • RSS
  • Контакты

Сложение двух чисел в Visual Studio 2015 на С++ (Win32 приложение)

Win32 приложение в Visual Studio 2015 на С++.

03.04.2016 2 комментария 3 985 просмотров

В статье рассказывается как создать Win32 приложение сложения двух чисел в Visual Studio 2015 на С++.

Статья из цикла «Сложение двух чисел». Для меня минимальное освоение любой системы программирования начинается с возможности создания такой программы. Если можно написать приложение, в которой пользователь может ввести два числа, считать их, провести с ними какие-то действия, а потом вывести результат, то, значит, базовое владение имеется. И много задач именно из области программирования, алгоритмики можно будет решать, зная, как в конкретной системе программирования запрограммировать такую программу.

Содержание

  • Создание проекта
  • Добавление файла
  • Написание кода основной программы

Чтоб я еще когда-нибудь связался с этим Win32 приложениями! После опыта написания приложения прекрасно понимаю, почему никто не любит так программировать. Использовал в частности материал статей этой и этой.

Создание проекта

Создадим пустой проект.

2016-04-03_010052

2016-04-03_010159

2016-04-03_010226

2016-04-03_010603

2016-04-03_010735

Добавление файла

Мы создали пустой проект, поэтому нужно самим добавить файл cpp.

2016-04-03_011906

2016-04-03_011924

2016-04-03_011943

Написание кода основной программы

Вначале подключим инклуды и пропишем главную функцию:

1
2
3
4
5
6
7
8
9
10
#include <windows.h>
#include <tchar.h>
 
//Главная функция
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
}

Нам потребуются глобальные переменные:

1
2
3
//Глобальные переменные
static TCHAR szWindowClass[] = _T("win32app");//Имя класса главного окна
static TCHAR szTitle[] = _T("Сложение двух чисел");//Заголовок окна

Теперь в функции можем прописать описание нашего окна.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Определим внешний вид окна
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;. Тут прописана функция, в которой мы пропишем основной функционал. Её пропишем далее.

Далее можем зарегистрировать класс нашего окна:

1
2
3
4
5
6
7
8
9
10
//Зарегистрируем наше окно
if (!RegisterClassEx(&wcex))
{
MessageBox(NULL,
_T("Call to RegisterClassEx failed!"),
_T("Win32 Guided Tour"),
NULL);
 
return 1;
}

Теперь создадим наше окно:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Создадим окно
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;
}

И запустим его:

1
2
3
4
// Теперь можем запустить наше окно
ShowWindow(hWnd,
nCmdShow);
UpdateWindow(hWnd);

Жесть! Сколько уже кода написано!

Ну, а потом начнем слушать сообщения от операционной системы Windows.

1
2
3
4
5
6
7
8
9
// Слушаем сообщения от ОС
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
 
return (int)msg.wParam;

Пропишем болванку функции WndProc, о которой мы уже говорили выше:

1
2
3
4
5
//Главный функционал
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return 0;
}

Сейчас код программы выглядит так:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#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;
}

У нас будет два поля для ввода текста, одно поле для вывода и кнопка. Для каждого контрола создадим свой индентификатор уникальный. По нему потом будем искать нужен контрол.

1
2
3
4
5
//Идентификаторы наших контролов: полей ввода и кнопки
#define EDIT1  110
#define EDIT2  111
#define EDIT3  112
#define BUTTON 113

Теперь в функции WndProc создадим нужные контролы.

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
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).

При запуске программы мы увидим вот такое приложение:

2016-04-03_014905

Но пока кнопка не работает. В нашу функцию WndProc добавим отслеживание нажатия на кнопку.

1
2
3
4
5
6
7
8
case WM_COMMAND:
switch (LOWORD(wParam))
{
case BUTTON:
//Тут наш код
return 1;
}
break;

Функция примет вид:

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
38
39
40
41
42
43
44
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;
}

Чтобы не захламлять код вынесем обработку клика кнопки в отдельную функцию:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Функция сложения двух чисел
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);
}

И в итоге получим вот такой полный код нашего приложения:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#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;
}

Ну, и монстр получился! Зато теперь всё работает:

2016-04-03_015913

Вот наше приложение и написано. Пока всё)

P.S. До этого WinAPI я никогда не занимался, и надеюсь, что в дальнейшим не придется! Так что помочь в каких-нибудь вопросах не смогу.


Статьи по теме:

  1. Сложение двух чисел в Visual Studio 2013 (консольное Win32 приложение)
  2. Сложение двух чисел в Visual Studio 2015 на С++ (консольное Win32 приложение без stdafx.h)
  3. Сложение двух чисел в Visual Studio 2015 на С++ (CLR приложение)
  4. Сложение двух чисел из файла в Visual Studio 2015 на C++ (консольное Win32 приложение)

IT Visual Studio, Win32, Программа сложения двух чисел, С++

© 2014 Harrix