Ядро Windows:
GUI (Graphics User Interface) – стандартный графический интерфейс пользователя. Это та часть Windows, которая обеспечивает поддержку аппаратно-независимой графики.
API (Application Program Interface) — интерфейс прикладных программ (набор функций, сосредоточенных в ядре Windows и дополнительных библиотеках).
DLL (Dynamic Link Libraries) — библиотека динамической компоновки. Функции API содержатся в библиотеках динамической загрузки.
DDE – динамический обмен данными.
При программировании под Windows принято использовать префиксы перед именами переменных, указывающие на принадлежность к типу данных. Рекомендуется давать имена собственным переменным и идентификаторам, придерживаясь следующих принципов:
| Префикс | Значение |
|---|---|
A |
массив |
B |
логический тип (int) |
By |
беззнаковый символьный тип (byte) |
C |
символьный тип (1 байт) |
Cb |
счетчик байтов |
Cr |
цвет |
cx,cy |
короткий тип (short) |
Dbl |
double (с плавающей точкой) |
Dw |
беззнаковое длинное целое число (dword) |
Flt |
float (вещественная с плавающей точкой) |
Fn |
функция |
g_ |
префикс для глобальной переменной (глобальная переменная) |
H |
handle (беззнаковое целое число) |
|
handle (указатель на контекст устройства) |
I |
целое (integer) |
Id |
интегральное значение идентификатора |
L |
длинный тип (long) |
Lp |
длинный указатель |
Lpsz |
дальний указатель на строку, заканчивающуюся нулевым байтом |
m_ |
переменная класса |
N |
short или int |
Np |
ближний указатель |
P |
указатель |
|
указатель на функцию |
|
указатель на структуру |
Psz |
указатель на строку, заканчивающуюся нулевым байтом |
Pv |
указатель на тип void |
S |
строка |
Sz |
строка, заканчивающая |
U |
беззнаковый символ |
Tm |
текстовая метрика |
V |
тип void |
W |
беззнаковое целое (word, 16-бит) |
x, y |
короткое целое число (координата x или y) |
| Тип данных | Описание |
|---|---|
HANDLE |
определяет идентификатор; 32-разрядное целое, используемое в качестве дескриптора – числа, определяющего некоторый ресурс |
HWND |
определяет идентификатор окна |
|
определяет идентификатор контекста устройства |
LONG |
32-битовое целое со знаком |
LPSTR |
определяет линейный указатель |
NULL |
0 |
UINT |
тип данных Win32 (32 бита для Win32) |
WCHAR |
16-битовый символ UNICODE. Используется для представления символов языков мира |
Построение приложения Windows включает выполнение следующих этапов:
WinMain(...) и связанных с ней функций на языке C или C++.Создадим пустой проект Windows- приложения с помощью мастера:
Добавим следующий код:
#include <windows.h>
LONG WINAPI WndProc(HWND, UINT, WPARAM,LPARAM);
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS w;
memset(w,0,sizeof(WNDCLASS));
w.style = CS_HREDRAW | CS_VREDRAW;
w.lpfnWndProc = WndProc;
w.hInstance = hInstance;
w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
w.lpszClassName = "My Class";
RegisterClass(w);
hwnd = CreateWindow("My Class", "Окно пользователя", WS_OVERLAPPEDWINDOW,500, 300, 500, 380, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(msg,NULL,0,0))
{
TranslateMessage(msg);
DispatchMessage(msg);
}
return msg.wParam;
}
LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
switch (Message)
{
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, Message, wparam, lparam);
}
return 0;
}
Скомпилируем и запустим программу. На экране появится Windows-окно.
Все приложения Windows должны содержать два основных элемента: функцию WinMain(...) и функцию окна WndProc.
Функция WinMain(...) служит точкой входа в приложение. Эта функция отвечает за следующие действия:
WM_QUIT ).Функция WndProc отвечает за обработку сообщений Windows. Эта часть программы является наиболее содержательной с точки зрения выполнения поставленных перед программой задач. Если мы хотим, чтобы программа обращала на наши действия внимание, то необходимо добавить ветки case для оператора switch в оконную процедуру WndProc. Например, если мы хотим, чтобы наше приложение обращало внимание на щелчок левой кнопкой мыши – добавляем ветку case WM_LBUTTONDOWN. В настоящий момент в оконной процедуре происходит только обработка сообщения WM_DESTROY. Больше Windows-окно пока ничего делать не умеет.
Заголовочный файл windows.h нужен для любой традиционной Windows программы на C. Именно в нем содержатся разные определения констант ( WM_DESTROY и т. д.).
HINSTANCE ) – является идентификатором текущего экземпляра приложения. Данное число однозначно определяет программу, работающую под управлением Windows.HINSTANCE ) – указывал ранее (Windows 3.1) на предыдущий запущенный экземпляр приложения. В современных версиях Windows он равен NULL.NULL ).SW_SHOWNORMAL, SW_SHOWMAXIMIZED или SW_SHOWMINIMIZED ).Каждое окно, которое создается в рамках приложения Windows, должно основываться на классе окна – шаблоне, в котором определены выбранные пользователем стили, шрифты, заголовки и т.д. Для всех определений класса окна используется стандартный тип структуры. Таким образом, сначала определяется структура WNDCLASS w, а затем поля структуры заполняются информацией о классе окна. У этой структуры много полей, но большинство из них можно определить нулем. В программе это делается строкой memset(w,0,sizeof(WNDCLASS)) ;
Рассмотрим следующий фрагмент программы:
w.style = CS_HREDRAW | CS_VREDRAW; w.lpfnWndProc = WndProc; w.hInstance = hInstance; w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); w.lpszClassName = "My Class"; RegisterClass(w);
В этом фрагменте определяется стиль класса (все идентификаторы стилей начинаются с префикса CS_ ). В программе значения поля стиля задаются константами. CS_HREDRAW ¬– обеспечивает перерисовку содержимого клиентской области окна при изменении размера окна по горизонтали, CS_VREDRAW – обеспечивает перерисовку содержимого клиентской области окна при изменении размера окна по вертикали.
w.lpfnWndProc = WndProc - значение указателя на функцию окна ( WndProc ), которая выполняет все задачи, связанные с окном.
w.hInstance = hInstance - определяется экземпляр приложения, регистрирующий класс окна.
w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH) - определяется кисть, используемая для закраски фона окна.
w.lpszClassName = "My Class" - указатель на строку символов, заканчивающуюся на 0, которая определяет имя класса. Класс здесь – это не класс в смысле ООП (объектно-ориентированного программирования). Термин один, но смысла два. Исторически классы окон возникли раньше, чем классы ООП.
RegisterClass(w) - регистрация происходит при помощи вызова функции RegisterClass().
hwnd = CreateWindow("My Class","Окно пользователя", WS_OVERLAPPEDWINDOW,500,300,500,380,NULL,NULL,hInstance,NULL);
Первый параметр функции служит для задания класса окна. Второй – это заголовок окна. Третий – определяет стиль окна (обычное перекрывающее окно с заголовком, кнопкой вызова системного меню, кнопками минимизации и максимизации и рамкой). Следующие шесть параметров определяют положение окна на экране (по оси X и по оси Y), размеры окна по оси X и по оси Y, идентификатор родительского окна и идентификатор меню окна. Следующее поле ( hInstance ) содержит идентификатор экземпляра программы, далее следует информация об отсутствии дополнительных параметров ( NULL ). Если создание окна прошло успешно, то функция CreateWindow(...) возвращает идентификатор созданного окна, в противном случае – NULL. После того как окно создано, его надо показать и обновить. Для того чтобы вывести главное окно приложения на экран, необходимо вызвать функцию Windows ShowWindow(...).
ShowWindow(hwnd,nCmdShow) выводит окно на экран. Параметр hwnd содержит идентификатор окна, созданного при вызове CreateWindow(...). Второй параметр определяет, как окно выводится в первый момент.
Последний шаг при выводе окна на экран заключается в вызове функции Windows UpdateWindow(hwnd) , которая приводит к перерисовке клиентской области окна.
Теперь программа готова выполнять свою главную задачу – обрабатывать сообщения. Используется стандартный цикл С/С++ цикл while:
while(GetMessage(msg,NULL,0,0))
{
TranslateMessage(msg);
DispatchMessage(msg);
}
Вызов этой функции позволяет получить для обработки следующее сообщение из очереди сообщений приложения. Данная функция копирует сообщение в структуру сообщения, на которую указывает указатель msg, и передает его в основной блок программы. Если значение следующего параметра NULL, то будут поступать сообщения, относящиеся к любому окну приложения. Значения последних параметров (0,0) указывает функции, что не надо применять никаких фильтров сообщений. Фильтры могут применяться для распределения получаемых сообщений по категориям, например, нажатия на клавишу или перемещение мыши. После входа в цикл обработки сообщений, выйти из него можно, получив только одно сообщение: WM_QUIT. Когда обрабатывается сообщение WM_QUIT, то возвращается значение "ложь" и цикл обработки сообщений завершается.
Функция TranslateMessage(...) преобразует сообщения виртуальных клавиш в сообщения о символах.
Функция DispatchMessage(...) используется для распределения текущего сообщения соответствующей функции окна.
Вторая часть в любой программе под Windows – это оконная процедура. В рассматриваемом примере она маленькая (так как программа ничего не делает), но, именно эта часть и является самой главной и интересной в приложении.
Рассмотрим функцию WndProc:
LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
switch (Message)
{
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, Message, wparam, lparam);
}
return 0;
}
Основное назначение hwnd типа HWND задает окно, которое будет обрабатывать сообщение. Второй UINT Message – это передаваемое сообщение. Два последних WPARAM wparam, LPARAM lparam задают дополнительные параметры для передаваемого сообщения. Они для каждого сообщения свои. Оконная процедура отправляет сообщение в switch, который в примере имеет только один case:
switch (Message)
{
case WM_DESTROY:
...
То есть, пока рассматриваемая программа обращает внимание только на сообщение WM_DESTROY. Это сообщение окно получает только при своем уничтожении. После принятия этого сообщения необходимо вызвать функцию PostQuitMessage(...). В ответ на сообщение WM_DESTROY необходимо поместить в очередь сообщение WM_QUIT. Это и делает функция PostQuitMessage(...), посылая это сообщение в очередь и говоря, что процесс должен быть завершен. Если мы хотим, чтобы наша программа реагировала еще на что-нибудь, то надо написать еще case.
Рассмотрим далее ветку default. В ней идет вызов функции DefWindowProc(hwnd, Message, wparam, lparam) . Основное предназначение этой функции – обработка сообщений Windows, которые не обрабатываются в нашей программе (то есть, для которых нет своего case ). При этом ничего не делается, но очередь из сообщений идет.
Проиллюстируем рассмотренный в предыдущем параграфе теоретичекий материал на примере написания Windows-приложения решения задачи о разложении в ряд некоторой функции.
Задача: Разложить в ряд Тейлора в окрестности точки 0 функции .
Напишем функции вычисления синуса и косинуса –
const double epsilon = 0.0000001;
const double pi = 3.14159265;
const double x_start = -2*pi;
const double x_end = 2*pi;
double sin_e(double arg, double eps)
{
double result = 0, rn = arg;
for(int i = 1; ;i++)
{
if(rn < eps rn > -eps) return result;
result += rn;
rn = -rn*arg*arg/(i+1)/(i+2);
i++;
}
}
double cos_e(double arg, double eps)
{
double result = 0, rn = 1;
for(int i = 0; ;i++)
{
if(rn < eps rn > -eps) return result;
result += rn;
rn = -rn*arg*arg/(i+1)/(i+2);
i++;
}
}
Для дальнейшего решения задачи – вывода графика функции в клиентском окне, будем обрабатывать сообщения, которые будут посылаться окну. Когда необходима перерисовка окна (изменились размеры окна, часть окна перекрылась другим окном и т.п.), система посылает окну сообщение WM_PAINT.
Добавим функции, которые будут выводить в клиентскую часть окна график и координатные оси, а также, необходимые ветви case в операторе switch.
Для построения изображения используем API функции операционной системы: MoveToEx(...), LineTo(...), GetClientRect(...) и т.д. Информацию об этих функциях можно получить в справочной системе.
void DrawAxis(HDC hdc, RECT rectClient)
{
HPEN penGraph = CreatePen(PS_SOLID,2,RGB(0,0,255));
HGDIOBJ gdiOld = SelectObject(hdc, penGraph);
MoveToEx(hdc, 0, rectClient.bottom/2, NULL);
LineTo(hdc, rectClient.right, rectClient.bottom/2);
LineTo(hdc, rectClient.right - 5, rectClient.bottom/2 + 2);
MoveToEx(hdc, rectClient.right, rectClient.bottom/2, NULL);
LineTo(hdc, rectClient.right - 5, rectClient.bottom/2 - 2);
MoveToEx(hdc, rectClient.right/2, rectClient.bottom, NULL);
LineTo(hdc, rectClient.right/2, rectClient.top);
LineTo(hdc, rectClient.right/2 - 2, rectClient.top + 5);
MoveToEx(hdc, rectClient.right/2, rectClient.top, NULL);
LineTo(hdc, rectClient.right/2 + 2, rectClient.top + 5);
SelectObject(hdc, gdiOld);
}
void DrawGraph(HDC hdc, RECT rectClient)
{
HPEN penGraph = CreatePen(PS_SOLID,2,RGB(255,0,0));
HGDIOBJ gdiOld = SelectObject(hdc, penGraph);
double x_current = x_start;
double step = (x_end - x_start)/rectClient.right;
double y_start = cos_e(x_start, epsilon) + cos_e(x_start, epsilon);
MoveToEx(hdc, 0, int(-y_start/step) + rectClient.bottom/2, NULL);
while(x_current < x_end)
{
x_current += step;
double y_next = cos_e(x_current, epsilon) + cos_e(x_current, epsilon);
LineTo(hdc, int(x_current/step) + rectClient.right/2, int(-y_next/step) + rectClient.bottom/2);
}
SelectObject(hdc, gdiOld);
}
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
RECT rectClient;
HDC hdc = BeginPaint(hwnd,ps);
GetClientRect(hwnd, rectClient);
DrawAxis(hdc, rectClient);
DrawGraph(hdc, rectClient);
ValidateRect(hwnd,NULL);
EndPaint(hwnd,ps);
}
LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
switch (Message)
{
case WM_PAINT:
OnPaint(hwnd);
break;
case WM_MOUSEMOVE:
SetCapture(hwnd);
SetCursor(LoadCursor(NULL,IDC_ARROW));
ReleaseCapture();
break;
case WM_WINDOWPOSCHANGED:
UpdateWindow(hwnd);
break;
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, Message, wparam, lparam);
}
UpdateWindow(hwnd);
return 0;
}
Функция :рис 1.1
(рис 1.1) Построение графика функции Ядро Windows:
GUI (Graphics User Interface) – стандартный графический интерфейс пользователя. Это та часть Windows, которая обеспечивает поддержку аппаратно-независимой графики.
API (Application Program Interface) — интерфейс прикладных программ (набор функций, сосредоточенных в ядре Windows и дополнительных библиотеках).
DLL (Dynamic Link Libraries) — библиотека динамической компоновки. Функции API содержатся в библиотеках динамической загрузки.
DDE – динамический обмен данными.
При программировании под Windows принято использовать префиксы перед именами переменных, указывающие на принадлежность к типу данных. Рекомендуется давать имена собственным переменным и идентификаторам, придерживаясь следующих принципов:
| Префикс | Значение |
|---|---|
A |
массив |
B |
логический тип (int) |
By |
беззнаковый символьный тип (byte) |
C |
символьный тип (1 байт) |
Cb |
счетчик байтов |
Cr |
цвет |
cx,cy |
короткий тип (short) |
Dbl |
double (с плавающей точкой) |
Dw |
беззнаковое длинное целое число (dword) |
Flt |
float (вещественная с плавающей точкой) |
Fn |
функция |
g_ |
префикс для глобальной переменной (глобальная переменная) |
H |
handle (беззнаковое целое число) |
|
handle (указатель на контекст устройства) |
I |
целое (integer) |
Id |
интегральное значение идентификатора |
L |
длинный тип (long) |
Lp |
длинный указатель |
Lpsz |
дальний указатель на строку, заканчивающуюся нулевым байтом |
m_ |
переменная класса |
N |
short или int |
Np |
ближний указатель |
P |
указатель |
|
указатель на функцию |
|
указатель на структуру |
Psz |
указатель на строку, заканчивающуюся нулевым байтом |
Pv |
указатель на тип void |
S |
строка |
Sz |
строка, заканчивающая |
U |
беззнаковый символ |
Tm |
текстовая метрика |
V |
тип void |
W |
беззнаковое целое (word, 16-бит) |
x, y |
короткое целое число (координата x или y) |
| Тип данных | Описание |
|---|---|
HANDLE |
определяет идентификатор; 32-разрядное целое, используемое в качестве дескриптора – числа, определяющего некоторый ресурс |
HWND |
определяет идентификатор окна |
|
определяет идентификатор контекста устройства |
LONG |
32-битовое целое со знаком |
LPSTR |
определяет линейный указатель |
NULL |
0 |
UINT |
тип данных Win32 (32 бита для Win32) |
WCHAR |
16-битовый символ UNICODE. Используется для представления символов языков мира |
Построение приложения Windows включает выполнение следующих этапов:
WinMain(...) и связанных с ней функций на языке C или C++.Создадим пустой проект Windows- приложения с помощью мастера:
Добавим следующий код:
#include <windows.h>
LONG WINAPI WndProc(HWND, UINT, WPARAM,LPARAM);
int WINAPI WinMain (HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hwnd;
MSG msg;
WNDCLASS w;
memset(w,0,sizeof(WNDCLASS));
w.style = CS_HREDRAW | CS_VREDRAW;
w.lpfnWndProc = WndProc;
w.hInstance = hInstance;
w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
w.lpszClassName = "My Class";
RegisterClass(w);
hwnd = CreateWindow("My Class", "Окно пользователя", WS_OVERLAPPEDWINDOW,500, 300, 500, 380, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(msg,NULL,0,0))
{
TranslateMessage(msg);
DispatchMessage(msg);
}
return msg.wParam;
}
LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
switch (Message)
{
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, Message, wparam, lparam);
}
return 0;
}
Скомпилируем и запустим программу. На экране появится Windows-окно.
Все приложения Windows должны содержать два основных элемента: функцию WinMain(...) и функцию окна WndProc.
Функция WinMain(...) служит точкой входа в приложение. Эта функция отвечает за следующие действия:
WM_QUIT ).Функция WndProc отвечает за обработку сообщений Windows. Эта часть программы является наиболее содержательной с точки зрения выполнения поставленных перед программой задач. Если мы хотим, чтобы программа обращала на наши действия внимание, то необходимо добавить ветки case для оператора switch в оконную процедуру WndProc. Например, если мы хотим, чтобы наше приложение обращало внимание на щелчок левой кнопкой мыши – добавляем ветку case WM_LBUTTONDOWN. В настоящий момент в оконной процедуре происходит только обработка сообщения WM_DESTROY. Больше Windows-окно пока ничего делать не умеет.
Заголовочный файл windows.h нужен для любой традиционной Windows программы на C. Именно в нем содержатся разные определения констант ( WM_DESTROY и т. д.).
HINSTANCE ) – является идентификатором текущего экземпляра приложения. Данное число однозначно определяет программу, работающую под управлением Windows.HINSTANCE ) – указывал ранее (Windows 3.1) на предыдущий запущенный экземпляр приложения. В современных версиях Windows он равен NULL.NULL ).SW_SHOWNORMAL, SW_SHOWMAXIMIZED или SW_SHOWMINIMIZED ).Каждое окно, которое создается в рамках приложения Windows, должно основываться на классе окна – шаблоне, в котором определены выбранные пользователем стили, шрифты, заголовки и т.д. Для всех определений класса окна используется стандартный тип структуры. Таким образом, сначала определяется структура WNDCLASS w, а затем поля структуры заполняются информацией о классе окна. У этой структуры много полей, но большинство из них можно определить нулем. В программе это делается строкой memset(w,0,sizeof(WNDCLASS)) ;
Рассмотрим следующий фрагмент программы:
w.style = CS_HREDRAW | CS_VREDRAW; w.lpfnWndProc = WndProc; w.hInstance = hInstance; w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); w.lpszClassName = "My Class"; RegisterClass(w);
В этом фрагменте определяется стиль класса (все идентификаторы стилей начинаются с префикса CS_ ). В программе значения поля стиля задаются константами. CS_HREDRAW ¬– обеспечивает перерисовку содержимого клиентской области окна при изменении размера окна по горизонтали, CS_VREDRAW – обеспечивает перерисовку содержимого клиентской области окна при изменении размера окна по вертикали.
w.lpfnWndProc = WndProc - значение указателя на функцию окна ( WndProc ), которая выполняет все задачи, связанные с окном.
w.hInstance = hInstance - определяется экземпляр приложения, регистрирующий класс окна.
w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH) - определяется кисть, используемая для закраски фона окна.
w.lpszClassName = "My Class" - указатель на строку символов, заканчивающуюся на 0, которая определяет имя класса. Класс здесь – это не класс в смысле ООП (объектно-ориентированного программирования). Термин один, но смысла два. Исторически классы окон возникли раньше, чем классы ООП.
RegisterClass(w) - регистрация происходит при помощи вызова функции RegisterClass().
hwnd = CreateWindow("My Class","Окно пользователя", WS_OVERLAPPEDWINDOW,500,300,500,380,NULL,NULL,hInstance,NULL);
Первый параметр функции служит для задания класса окна. Второй – это заголовок окна. Третий – определяет стиль окна (обычное перекрывающее окно с заголовком, кнопкой вызова системного меню, кнопками минимизации и максимизации и рамкой). Следующие шесть параметров определяют положение окна на экране (по оси X и по оси Y), размеры окна по оси X и по оси Y, идентификатор родительского окна и идентификатор меню окна. Следующее поле ( hInstance ) содержит идентификатор экземпляра программы, далее следует информация об отсутствии дополнительных параметров ( NULL ). Если создание окна прошло успешно, то функция CreateWindow(...) возвращает идентификатор созданного окна, в противном случае – NULL. После того как окно создано, его надо показать и обновить. Для того чтобы вывести главное окно приложения на экран, необходимо вызвать функцию Windows ShowWindow(...).
ShowWindow(hwnd,nCmdShow) выводит окно на экран. Параметр hwnd содержит идентификатор окна, созданного при вызове CreateWindow(...). Второй параметр определяет, как окно выводится в первый момент.
Последний шаг при выводе окна на экран заключается в вызове функции Windows UpdateWindow(hwnd) , которая приводит к перерисовке клиентской области окна.
Теперь программа готова выполнять свою главную задачу – обрабатывать сообщения. Используется стандартный цикл С/С++ цикл while:
while(GetMessage(msg,NULL,0,0))
{
TranslateMessage(msg);
DispatchMessage(msg);
}
Вызов этой функции позволяет получить для обработки следующее сообщение из очереди сообщений приложения. Данная функция копирует сообщение в структуру сообщения, на которую указывает указатель msg, и передает его в основной блок программы. Если значение следующего параметра NULL, то будут поступать сообщения, относящиеся к любому окну приложения. Значения последних параметров (0,0) указывает функции, что не надо применять никаких фильтров сообщений. Фильтры могут применяться для распределения получаемых сообщений по категориям, например, нажатия на клавишу или перемещение мыши. После входа в цикл обработки сообщений, выйти из него можно, получив только одно сообщение: WM_QUIT. Когда обрабатывается сообщение WM_QUIT, то возвращается значение "ложь" и цикл обработки сообщений завершается.
Функция TranslateMessage(...) преобразует сообщения виртуальных клавиш в сообщения о символах.
Функция DispatchMessage(...) используется для распределения текущего сообщения соответствующей функции окна.
Вторая часть в любой программе под Windows – это оконная процедура. В рассматриваемом примере она маленькая (так как программа ничего не делает), но, именно эта часть и является самой главной и интересной в приложении.
Рассмотрим функцию WndProc:
LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
switch (Message)
{
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, Message, wparam, lparam);
}
return 0;
}
Основное назначение hwnd типа HWND задает окно, которое будет обрабатывать сообщение. Второй UINT Message – это передаваемое сообщение. Два последних WPARAM wparam, LPARAM lparam задают дополнительные параметры для передаваемого сообщения. Они для каждого сообщения свои. Оконная процедура отправляет сообщение в switch, который в примере имеет только один case:
switch (Message)
{
case WM_DESTROY:
...
То есть, пока рассматриваемая программа обращает внимание только на сообщение WM_DESTROY. Это сообщение окно получает только при своем уничтожении. После принятия этого сообщения необходимо вызвать функцию PostQuitMessage(...). В ответ на сообщение WM_DESTROY необходимо поместить в очередь сообщение WM_QUIT. Это и делает функция PostQuitMessage(...), посылая это сообщение в очередь и говоря, что процесс должен быть завершен. Если мы хотим, чтобы наша программа реагировала еще на что-нибудь, то надо написать еще case.
Рассмотрим далее ветку default. В ней идет вызов функции DefWindowProc(hwnd, Message, wparam, lparam) . Основное предназначение этой функции – обработка сообщений Windows, которые не обрабатываются в нашей программе (то есть, для которых нет своего case ). При этом ничего не делается, но очередь из сообщений идет.
Проиллюстируем рассмотренный в предыдущем параграфе теоретичекий материал на примере написания Windows-приложения решения задачи о разложении в ряд некоторой функции.
Задача: Разложить в ряд Тейлора в окрестности точки 0 функции .
Напишем функции вычисления синуса и косинуса –
const double epsilon = 0.0000001;
const double pi = 3.14159265;
const double x_start = -2*pi;
const double x_end = 2*pi;
double sin_e(double arg, double eps)
{
double result = 0, rn = arg;
for(int i = 1; ;i++)
{
if(rn < eps rn > -eps) return result;
result += rn;
rn = -rn*arg*arg/(i+1)/(i+2);
i++;
}
}
double cos_e(double arg, double eps)
{
double result = 0, rn = 1;
for(int i = 0; ;i++)
{
if(rn < eps rn > -eps) return result;
result += rn;
rn = -rn*arg*arg/(i+1)/(i+2);
i++;
}
}
Для дальнейшего решения задачи – вывода графика функции в клиентском окне, будем обрабатывать сообщения, которые будут посылаться окну. Когда необходима перерисовка окна (изменились размеры окна, часть окна перекрылась другим окном и т.п.), система посылает окну сообщение WM_PAINT.
Добавим функции, которые будут выводить в клиентскую часть окна график и координатные оси, а также, необходимые ветви case в операторе switch.
Для построения изображения используем API функции операционной системы: MoveToEx(...), LineTo(...), GetClientRect(...) и т.д. Информацию об этих функциях можно получить в справочной системе.
void DrawAxis(HDC hdc, RECT rectClient)
{
HPEN penGraph = CreatePen(PS_SOLID,2,RGB(0,0,255));
HGDIOBJ gdiOld = SelectObject(hdc, penGraph);
MoveToEx(hdc, 0, rectClient.bottom/2, NULL);
LineTo(hdc, rectClient.right, rectClient.bottom/2);
LineTo(hdc, rectClient.right - 5, rectClient.bottom/2 + 2);
MoveToEx(hdc, rectClient.right, rectClient.bottom/2, NULL);
LineTo(hdc, rectClient.right - 5, rectClient.bottom/2 - 2);
MoveToEx(hdc, rectClient.right/2, rectClient.bottom, NULL);
LineTo(hdc, rectClient.right/2, rectClient.top);
LineTo(hdc, rectClient.right/2 - 2, rectClient.top + 5);
MoveToEx(hdc, rectClient.right/2, rectClient.top, NULL);
LineTo(hdc, rectClient.right/2 + 2, rectClient.top + 5);
SelectObject(hdc, gdiOld);
}
void DrawGraph(HDC hdc, RECT rectClient)
{
HPEN penGraph = CreatePen(PS_SOLID,2,RGB(255,0,0));
HGDIOBJ gdiOld = SelectObject(hdc, penGraph);
double x_current = x_start;
double step = (x_end - x_start)/rectClient.right;
double y_start = cos_e(x_start, epsilon) + cos_e(x_start, epsilon);
MoveToEx(hdc, 0, int(-y_start/step) + rectClient.bottom/2, NULL);
while(x_current < x_end)
{
x_current += step;
double y_next = cos_e(x_current, epsilon) + cos_e(x_current, epsilon);
LineTo(hdc, int(x_current/step) + rectClient.right/2, int(-y_next/step) + rectClient.bottom/2);
}
SelectObject(hdc, gdiOld);
}
void OnPaint(HWND hwnd)
{
PAINTSTRUCT ps;
RECT rectClient;
HDC hdc = BeginPaint(hwnd,ps);
GetClientRect(hwnd, rectClient);
DrawAxis(hdc, rectClient);
DrawGraph(hdc, rectClient);
ValidateRect(hwnd,NULL);
EndPaint(hwnd,ps);
}
LONG WINAPI WndProc(HWND hwnd, UINT Message, WPARAM wparam, LPARAM lparam)
{
switch (Message)
{
case WM_PAINT:
OnPaint(hwnd);
break;
case WM_MOUSEMOVE:
SetCapture(hwnd);
SetCursor(LoadCursor(NULL,IDC_ARROW));
ReleaseCapture();
break;
case WM_WINDOWPOSCHANGED:
UpdateWindow(hwnd);
break;
case WM_DESTROY: PostQuitMessage(0); break;
default: return DefWindowProc(hwnd, Message, wparam, lparam);
}
UpdateWindow(hwnd);
return 0;
}
Функция :рис 1.1
(рис 1.1) Построение графика функции Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.