Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

помогите исправить и доработать код. Построить функцию y=|sin(3x)|.

85K
09 октября 2016 года
Eugene Pashkevich
7 / / 09.10.2016
// Подключение используемых заголовочных файлов:
#include <windows.h> /* Содержит декларации для всех функций в Windows API, все общие макросы и все типы данных. Он определяет очень большое количество специфических функций окна */
#include <iostream> /* Содержит классы, функции и переменные для организации ввода-вывода */
#include <cmath> /* Выполняет простые математические операции */
#include <commdlg.h> /* Поддерживает реализацию общих диалоговых окон (для GetSaveFileName) */
#include <shlobj.h> /* Поддерживает работу с путём каталога к папке или файлу (для SHGetFolderPath) */

Листинг 2
// Начало функции WinMain:
/* Спецификатор WINAPI обозначает тип вызова функции; hInstance - дескриптор экземпляра выполняющейся программы (идентификатор приложения);
hPrevInstance - дескриптор предыдущего экземпляра программы, если таковой имеется, в Win32 не имеет смысла;
lpCmdLine - это указатель на строку, содержащую командную строку, запустившую программу;
nCmdShow - определяет внешний вид окна при его создании. */
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
}

Листинг 3
WNDCLASS wc = {0}; // Создание объекта класса окна и обнуление полей
// Инициализация членов структуры окна
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; // Задание стиля окна
wc.lpfnWndProc = WindowProc; // Задание функции обработки сообщений
wc.hInstance = hInstance; // Задание дескриптора экземпляра приложения
wc.hCursor = LoadCursor (NULL, IDC_ARROW); // Задание курсора окна
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Задание пиктограммы приложения
wc.lpszMenuName = L"hMenu"; // Инициализация указателя на имя ресурса меню
wc.lpszClassName= L"CMyWnd"; // Инициализация указателя на имя класса (установка имени класса окна)
wc.hbrBackground= static_cast<HBRUSH>(GetStockObject(GRAY_BRUSH)); // Задание кисти цвета фона окна
RegisterClass (&wc); // Регистрация класса окна в операционной системе
Листинг 4
/* Создание экземпляра класса окна при помощи функции CreateWindow и инициализация дескриптора hWnd возвращаемым функцией значением.
Параметры функции:
L"CMyWnd" - имя класса окна; L"WinMain sample" - заголовок окна; WS_OVERLAPPEDWINDOW - стиль окна (перекрываемое);
CW_USEDEFAULT - позиция левого верхнего угла на экране по умолчанию по X;
0 - позиция левого верхнего угла на экране по умолчанию по Y;
320 - размер окна (ширина); 240 - размер окна (высота); NULL - нет родительского окна; NULL - нет меню;
hInstance - дескриптор экземпляра программы; NULL - никаких данных для создания окна: */
HWND hWnd = CreateWindow (L"CMyWnd", L"WinMain sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 320, 240, NULL, NULL, hInstance, NULL);

Листинг 5
// Создание Меню
czCreateMenu(hWnd);

Листинг 6
/* Функция получает дескриптор контекста устройства для клиентской области указанного в параметрах окна (задает область для рисования): */
dc = GetDC (hWnd);
/* Функция отображает окно, причем в соответствии с параметром nCmdShow: */
ShowWindow (hWnd, nCmdShow);

Листинг 7
/* Функция SetTimer создает таймер с указанным значением времени простоя, когда время истечет, передается сообщение */
SetTimer (hWnd, 1, USER_TIMER_MINIMUM, NULL);

Листинг 8
/* Структура сообщений Windows. Т.е. создание объекта типа MSG (создаем экземпляр структуры), который будет содержать информацию о сообщении из очереди потока сообщений: */
MSG msg;
/* Организация цикла сообщений (message loop), или так называемой подкачки сообщений (message pump).
Функция GetMessage возвращает TRUE (1), если получено любое сообщение кроме WM_QUIT для завершения программы (в этом случае возвращается FALSE (0)).
При возникновении ошибки возвращается значение -1.
Цикл будет выполняться бесконечно, пока не появится сообщение завершения программы или не возникнет ошибка: */
while (GetMessage(&msg,NULL,0,0) > 0)
{
TranslateMessage (&msg); /* Преобразует сообщения от нажатой клавиатуры в символьный вид */
DispatchMessage (&msg); /* Функция заставляет ОС Windows осуществить диспетчеризацию сообщения, т.е. вызвать функцию WindowProc() для обработки сообщения */
}
return msg.wParam; // Возврат в операционную систему

Листинг 9
// Идентификатор контекста отображения (дескриптор контекста устройства вывода, в данном случае дисплея):
HDC dc;
// Логическая переменная для проверки было ли уже произведено сохранение:
static BOOL bFirstSave = TRUE;

Листинг 10
// Прототипы используемых функций
LRESULT CALLBACK WindowProc (HWND, UINT, WPARAM, LPARAM); /* Обрабатывает события окна */
void czCreateMenu(HWND hWwnd); /* Создает меню главного окна */
void SaveScreen(HWND hWND); /* Создает диалог для сохранения изображения (получает путь) */
bool save (HWND hWnd, OPENFILENAME openFile); /* Непосредственно выполняет сохранение растрового изображения */

Листинг 11
// Функция создания меню:
void czCreateMenu(HWND hwnd)
{
HMENU MainMenu = CreateMenu(); // Функция создает меню (пока пустое)
HMENU hPopupMenu1 = CreatePopupMenu(); // Функция создает подменю - раскрывающееся меню (пока пустое)
HMENU hPopupMenu2 = CreatePopupMenu(); // Функция создает подменю - раскрывающееся меню (пока пустое)
HMENU hPopupMenu2_1 = CreatePopupMenu(); // Функция создает подменю - раскрывающееся меню (пока пустое)
HMENU hPopupMenu3 = CreatePopupMenu(); // Функция создает подменю - раскрывающееся меню (пока пустое)
AppendMenu(MainMenu, MF_STRING | MF_POPUP, (UINT)hPopupMenu1, L"&File"); // Функция добавляет "выпадающее" меню "Файл" в главную строку меню
{
AppendMenu(hPopupMenu1, MF_STRING | MF_CHECKED, 101, L"New"); // Функция добавляет пункт "Новый" в "выпадающее" меню "Файл"
AppendMenu(hPopupMenu1, MF_SEPARATOR, 0, L""); // Функция добавляет разделитель в "выпадающее" меню "Файл"
AppendMenu(hPopupMenu1, MF_STRING, 102, L"Save"); // Функция добавляет пункт "Сохранить" в "выпадающее" меню "Файл"
AppendMenu(hPopupMenu1, MF_STRING, 103, L"Save as..."); // Функция добавляет пункт "Сохранить как..." в "выпадающее" меню "Файл"
AppendMenu(hPopupMenu1, MF_SEPARATOR, 0, L""); // Функция добавляет разделитель в "выпадающее" меню "Файл"
AppendMenu(hPopupMenu1, MF_STRING, 104, L"Exit"); // Функция добавляет пункт "Выход" в "выпадающее" меню "Файл"
}
AppendMenu(MainMenu, MF_STRING | MF_POPUP, (UINT)hPopupMenu2, L"&View"); // Функция добавляет "выпадающее" меню "Вид" в главную строку меню
{
AppendMenu(hPopupMenu2, MF_STRING | MF_POPUP, (UINT)hPopupMenu2_1, L"&Color"); // Функция добавляет "выпадающее" меню "Цвет" в "выпадающее" меню "Вид"
{
AppendMenu(hPopupMenu2_1, MF_STRING, 201, L"Black"); // Функция добавляет пункт "Черный" в "выпадающее" меню "Цвет"
AppendMenu(hPopupMenu2_1, MF_STRING, 202, L"Blue"); // Функция добавляет пункт "Синий" в "выпадающее" меню "Цвет"
AppendMenu(hPopupMenu2_1, MF_STRING, 203, L"Green"); // Функция добавляет пункт "Зеленый" в "выпадающее" меню "Цвет"
AppendMenu(hPopupMenu2_1, MF_STRING, 204, L"Red"); // Функция добавляет пункт "Красный" в "выпадающее" меню "Цвет"
}
}
AppendMenu(MainMenu, MF_STRING, 300, L"&Reset"); // Функция добавляет пункт "Сброс" в главную строку меню
AppendMenu(MainMenu, MF_STRING | MF_POPUP, (UINT)hPopupMenu3, L"&Help"); // Функция добавляет "выпадающее" меню "Справка" в главную строку меню
{
AppendMenu(hPopupMenu3, MF_STRING, 401, L"&About"); // Функция добавляет пункт "О программе" в "выпадающее" меню "Справка"
}
SetMenu(hwnd, MainMenu); // Функция назначает новое меню для заданного окна
}

Листинг 12
#define WIN32_LEAN_AND_MEAN /* Ускоряет сборку за счет уменьшения размера заголовочных файлов, исключая наименее распространенные функции */
// Создание идентификаторов для событий выбора пунктов меню:
#define IDM_NEW 101 // Выбрано меню "New"
#define IDM_SAVE_AS 103 // Выбрано меню "Save as"
#define IDM_EXIT 104 // Выбрано меню "Exit"
#define IDM_BLACK 201 // Выбрано меню "Black"
#define IDM_BLUE 202 // Выбрано меню "Blue"
#define IDM_GREEN 203 // Выбрано меню "Green"
#define IDM_RED 204 // Выбрано меню "Red"
#define IDM_RESET 300 // Выбрано меню "Reset"
#define IDM_ABOUT 401 // Выбрано меню "About"

Листинг 13
// Функция обработки сообщений - Message processing function
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent; // Создание переменных для хранения параметров сообщения
static bool Move = true; // Логическая глобальная переменная, которая показывает должен ли перерисовываться график с изменением положения
static int Phase=0, Width, Height; // Переменные для аргумента периодической функции, длины и ширины области построения графика
HPEN hPen; // Объявляем кисть
switch (message) // Использование переключателя для обработки различных событий окна
{
case WM_LBUTTONDOWN: // Сообщение - нажата левая кнопка мыши
case WM_RBUTTONDOWN: // Сообщение - нажата правая кнопка мыши
Move = !Move; // Включить/выключить перемещение графика
// Нет break, т.е. следующая ветка выполняется
case WM_TIMER: // Сообщение - истекло время таймера
if (Move) // Если Move==TRUE (если движение разрешено), то выполняется следующий оператор
Phase++; // Увеличение аргумента (фазы) функции на единицу
// Нет break, т.е. следующая ветка выполняется, если Move==TRUE
else // Если Move!=TRUE (если движение запрещено), то выполняется следующий оператор
break; // Выполнение переключателя прерывается
case WM_PAINT: // Сообщение – требуется окрасить (перерисовать) часть окна приложения
Rectangle (dc, -1, -1, Width+1, Height+1); // Прорисовка прямоугольника в клиентской области
MoveToEx (dc, 0, Height * (0.5 + 0.3*sin(0.1*Phase)), NULL); // Функция устанавливает текущую позицию пера, равную (x,y) для указанного контекста отображения dc
for (int i=0; i<Width; i++) // Цикл для рисования графика (изменение по оси X)
LineTo (dc, i, Height * (0.5 + 0.3*sin(0.1*(i+Phase))) ); // Функция рисует линию из текущей позиции пера в точку с координатами, перечисленными в параметрах функции
break; // Выполнение переключателя прерывается
case WM_SIZE: // Сообщение – изменился размер окна
Width = LOWORD(lParam), Height = HIWORD(lParam); // Изменение значений ширины и высоты окна в соответствии с параметрами сообщения
break; // Выполнение переключателя прерывается
case WM_KEYDOWN: // Сообщение - нажата несистемная клавиша (без + Alt). Посылается окну с фокусом клавиатуры
if (wParam != VK_ESCAPE) // Проверка – нажата ли клавиша «Esc»
break; // Выполнение переключателя прерывается
// else no break – в противном случае прерывания переключателя нет, т.е. переход к завершению работы окна
case WM_DESTROY: // Сообщение – окно должно быть разрушено (завершить работу приложения). После этого сообщения окно удаляется с экрана
PostQuitMessage (0); // Функция направляет сообщение WM_QUIT в функцию WinMain (обычно в ответ на сообщение WM_DESTROY). Указывает системе, что процесс, сделавший запрос необходимо прекратить
break; // Выполнение переключателя прерывается
case WM_COMMAND: // Сообщение – выбран пункт меню или элемент управления (кнопка); нажата «горячая» клавиша
break; // Выполнение переключателя прерывается
}
return DefWindowProc (hWnd, message, wParam, lParam); // Смотри комментарии выше
}


Листинг 14
wmId = LOWORD(wParam); // Выделение из 32-битового целочисленного значения младшего слова и запись в переменную
wmEvent = HIWORD(wParam); // Выделение из 32-битового целочисленного значения старшего слова и запись в переменную
// Новый переключатель для определения какой пункт меня выбран (кнопок нет, поэтому подобные события отсутствуют):
switch (wmId) // Параметром переключателя служит код-идентификатор, указанный при создании пункта меню
{
case IDM_SAVE_AS: // Сообщение - выбран пункт меню «Сохранить как…»
SaveScreen (hWnd); // Вызов функции сохранения изображения клиентской области
break; // Выполнение переключателя прерывается
case IDM_EXIT: // Сообщение - выбран пункт меню «Выход»
DestroyWindow(hWnd); // Функция уничтожает окно. Она посылает сообщения WM_DESTROY и WM_NCDESTROY окну, чтобы разрушить его и удалить фокус клавиатуры из него. Функция также уничтожает меню, очищает очередь сообщений, разрушает таймеры и т.д.
break; // Выполнение переключателя прерывается
case IDM_BLACK: // Сообщение - выбран пункт меню «Черный»
hPen=CreatePen(PS_SOLID, 1, RGB(0,0,0)); // Создание пера с определенным стилем, шириной и цветом
SelectObject(dc, hPen); // Функция производит выбор объекта в контекст устройства
break; // Выполнение переключателя прерывается
case IDM_BLUE: // Сообщение - выбран пункт меню «Синий»
hPen=CreatePen(PS_SOLID, 1, RGB(0,0,255)); // Создание пера с определенным стилем, шириной и цветом
SelectObject(dc, hPen); // Функция производит выбор объекта в контекст устройства
break; // Выполнение переключателя прерывается
case IDM_GREEN: // Сообщение - выбран пункт меню «Зеленый»
hPen=CreatePen(PS_SOLID, 1, RGB(0,255,0)); // Создание пера с определенным стилем, шириной и цветом
SelectObject(dc, hPen); // Функция производит выбор объекта в контекст устройства
break; // Выполнение переключателя прерывается
case IDM_RED: // Сообщение - выбран пункт меню «Красный»
hPen=CreatePen(PS_SOLID, 1, RGB(255,0,0)); // Создание пера с определенным стилем, шириной и цветом
SelectObject(dc, hPen); // Функция производит выбор объекта в контекст устройства
break; // Выполнение переключателя прерывается
case IDM_NEW: // Сообщение - выбран пункт меню «Новый»
case IDM_RESET: // Сообщение - выбран пункт меню «Сброс»
Phase=0; // Сброс значения аргумента периодической функции в нуль
break; // Выполнение переключателя прерывается
case IDM_about : // Сообщение - выбран пункт меню «О программе»
MessageBox(hWnd,L"PlotDrawer v.1.0. Copyright © M. Gorozheev Ph.D., 2015",L"About MessageBox", MB_OK | MB_ICONWARNING); /* Функция отображает модальное диалоговое окно, которое содержит набор кнопок и краткое сообщение конкретных приложений (в данном случае – информацию о программе). Окно возвращает целое значение, указывающее, какая кнопка нажата пользователем */
break; // Выполнение переключателя прерывается
default: // Эта «ветка» выполняется, если нет ни одного совпадения сообщения с метками case
return DefWindowProc(hWnd, message, wParam, lParam); /* Функция обеспечивает стандартную обработку сообщений, которые явно не обрабатываются в функции WindowProc данного приложения. Эта функция гарантирует, что каждое сообщение обрабатывается. Она вызывается с теми же параметрами, что были получены функцией WindowProc */
}

Листинг 15
// Функция создает диалог для сохранения изображения (получает путь)
void SaveScreen(HWND hWnd)
{
OPENFILENAME openFile; // Создание структуры. В нее записывается информация о выборе пользователя после закрытия диалогового окна
TCHAR szPath[MAX_PATH]; // Символьный массив для хранения пути к файлу
TCHAR szFile[MAX_PATH]; // Символьный массив для хранения имени файла
// Инициализация структуры OPENFILENAME:
ZeroMemory( &openFile, sizeof(OPENFILENAME) ); // Функция ZeroMemory заполняет блок памяти нулями
openFile.lStructSize = sizeof(OPENFILENAME); // lStructSize определяет длину структуры (байт); инициализируем оператором sizeof
szFile[0] = '
85K
09 октября 2016 года
Eugene Pashkevich
7 / / 09.10.2016
Листинг 16
// Функция, непосредственно сохраняющая изображение клиентской области окна в файл
bool save (HWND hWnd, OPENFILENAME openFile)
{
// Создание структуры с атрибутами файла:
HDC hdcScreen;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP bmpScreen;
// Получить дескриптор контекста устройства дисплея для клиентской области окна:
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd);
// Создание совместимого DC, который используется в BitBlt из окна DC:
hdcMemDC = CreateCompatibleDC(hdcWindow);
if(!hdcMemDC) // Если создать DC не получилось, выводится модальное окно с сообщением об ошибке
{
MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
goto done; // Переход к завершающему коду (освобождению памяти)
}
// Получить клиентскую область для расчета размера:
RECT rcClient; // Создание прямоугольника для хранения координат рабочей области окна
GetClientRect(hWnd, &rcClient); // Получение координат рабочей области окна

// Создать совместимый bitmap (точечный рисунок) из окна DC
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
if(!hbmScreen) // Если создать bitmap не получилось, выводится модальное окно с сообщением об ошибке
{
MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
goto done; // Переход к завершающему коду (освобождению памяти)
}
// Выбор совместимого bitmap (растрового изображения) в памяти совместимого DC:
SelectObject(hdcMemDC,hbmScreen);
/* Копирование блока битов в память совместимого DC. Функция BitBlt используется для копирования отдельных битов из области источника изображения в область-получатель. Если копирование не удалось, выводится модальное окно с сообщением об ошибке: */
if(!BitBlt(hdcMemDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, hdcWindow, 0, 0, SRCCOPY))
{
MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
goto done; // Переход к завершающему коду (освобождению памяти)
}
// Получить BITMAP (точечный рисунок) из HBITMAP:
GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmpScreen.bmWidth;
bi.biHeight = bmpScreen.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
// Начиная с 32-битной Windows, GlobalAlloc и LocalAlloc реализованы как «функции-обертки», которые вызывают HeapAlloc,
// используя дескриптор, ссылающийся на кучу, выделяемую процессу по умолчанию. Таким образом, GlobalAlloc и LocalAlloc
// имеют большую нагрузку, чем HeapAlloc:
HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);
char *lpbitmap = (char *)GlobalLock(hDIB);
// Получаем "биты" из растрового изображения и копируем их в буфер, на который указывает lpbitmap:
GetDIBits(hdcWindow, hbmScreen, 0, (UINT)bmpScreen.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
// Создается файл. Именно здесь происходит сохранение захваченного изображения клиентской области:
HANDLE hFile = CreateFile(openFile.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
// Добавление размера заголовков к размеру растрового изображения, чтобы получить общий размер файла:
DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
// Смещение, определяющее, где фактически начинаются биты растрового изображения:
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
// Размер файла:
bmfHeader.bfSize = dwSizeofDIB;
// Компонент bfType всегда должен равняться BM для растровых изображений:
bmfHeader.bfType = 0x4D42; //Тип BM
DWORD dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
// Разблокировка и освободить DIB (Device Independent Bitmap, растровое изображение) из кучи (памяти):
GlobalUnlock(hDIB);
GlobalFree(hDIB);
CloseHandle(hFile); // Закрыть дескриптор для файла, который был создан
// После метки производится освобождение памяти (удаление объектов) и выход из функции:
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL,hdcScreen);
ReleaseDC(hWnd,hdcWindow);
return TRUE;
}
252
10 октября 2016 года
koderAlex
1.4K / / 07.09.2005
кнопочки "вставить форматированный код" и "прикрепить файл" вам видны ?
85K
10 октября 2016 года
Eugene Pashkevich
7 / / 09.10.2016
Код:
Листинг программного кода

Листинг 1
// Подключение используемых заголовочных файлов:
#include <windows.h>        /* Содержит декларации для всех функций в Windows API, все общие макросы и все типы данных. Он определяет очень большое количество специфических функций окна */
#include <iostream>     /* Содержит классы, функции и переменные для организации ввода-вывода */
#include <cmath>        /* Выполняет простые математические операции */
#include <commdlg.h>        /* Поддерживает реализацию общих диалоговых окон (для GetSaveFileName) */
#include <shlobj.h>     /* Поддерживает работу с путём каталога к папке или файлу (для SHGetFolderPath) */

Листинг 2
// Начало функции WinMain:
/* Спецификатор WINAPI обозначает тип вызова функции; hInstance - дескриптор экземпляра выполняющейся программы (идентификатор приложения);
hPrevInstance - дескриптор предыдущего экземпляра программы, если таковой имеется, в Win32 не имеет смысла;
lpCmdLine - это указатель на строку, содержащую командную строку, запустившую программу;
nCmdShow - определяет внешний вид окна при его создании. */

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
}

Листинг 3
    WNDCLASS wc     = {0};  // Создание объекта класса окна и обнуление полей
    // Инициализация членов структуры окна
    wc.style        = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;   // Задание стиля окна
    wc.lpfnWndProc  = WindowProc;               // Задание функции обработки сообщений
    wc.hInstance    = hInstance;                // Задание дескриптора экземпляра приложения
    wc.hCursor      = LoadCursor (NULL, IDC_ARROW);     // Задание курсора окна
    wc.hIcon        = LoadIcon(NULL, IDI_APPLICATION);  // Задание пиктограммы приложения
    wc.lpszMenuName = L"hMenu";     // Инициализация указателя на имя ресурса меню
    wc.lpszClassName= L"CMyWnd";    // Инициализация указателя на имя класса (установка имени класса окна)
    wc.hbrBackground= static_cast<HBRUSH>(GetStockObject(GRAY_BRUSH)); // Задание кисти цвета фона окна
    RegisterClass (&wc);        // Регистрация класса окна в операционной системе
Листинг 4
    /* Создание экземпляра класса окна при помощи функции CreateWindow и инициализация дескриптора hWnd возвращаемым функцией значением.
    Параметры функции:
    L"CMyWnd" - имя класса окна; L"WinMain sample" - заголовок окна; WS_OVERLAPPEDWINDOW - стиль окна (перекрываемое);
    CW_USEDEFAULT - позиция левого верхнего угла на экране по умолчанию по X;
    0 - позиция левого верхнего угла на экране по умолчанию по Y;
    320 - размер окна (ширина); 240 - размер окна (высота); NULL - нет родительского окна; NULL - нет меню;
    hInstance - дескриптор экземпляра программы; NULL - никаких данных для создания окна: */

    HWND hWnd = CreateWindow (L"CMyWnd", L"WinMain sample", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 320, 240, NULL, NULL, hInstance, NULL);

Листинг 5
    // Создание Меню
    czCreateMenu(hWnd);

Листинг 6
    /* Функция получает дескриптор контекста устройства для клиентской области указанного в параметрах окна (задает область для рисования): */
    dc = GetDC (hWnd);
    /* Функция отображает окно, причем в соответствии с параметром nCmdShow: */
    ShowWindow (hWnd, nCmdShow);

Листинг 7
    /* Функция SetTimer создает таймер с указанным значением времени простоя, когда время истечет, передается сообщение */
    SetTimer (hWnd, 1, USER_TIMER_MINIMUM, NULL);

Листинг 8
    /* Структура сообщений Windows. Т.е. создание объекта типа MSG (создаем экземпляр структуры), который будет содержать информацию о сообщении из очереди потока сообщений: */
    MSG msg;
    /* Организация цикла сообщений (message loop), или так называемой подкачки сообщений (message pump).
    Функция GetMessage возвращает TRUE (1), если получено любое сообщение кроме WM_QUIT для завершения программы (в этом случае возвращается FALSE (0)).
    При возникновении ошибки возвращается значение -1.
    Цикл будет выполняться бесконечно, пока не появится сообщение завершения программы или не возникнет ошибка: */

    while (GetMessage(&msg,NULL,0,0) > 0)
    {
        TranslateMessage (&msg);    /* Преобразует сообщения от нажатой клавиатуры в символьный вид */
        DispatchMessage (&msg); /* Функция заставляет ОС Windows осуществить диспетчеризацию сообщения, т.е. вызвать функцию WindowProc() для обработки сообщения */
    }
    return msg.wParam;  // Возврат в операционную систему

Листинг 9
// Идентификатор контекста отображения (дескриптор контекста устройства вывода, в данном случае дисплея):
HDC dc;
// Логическая переменная для проверки было ли уже произведено сохранение:
static BOOL bFirstSave = TRUE;

Листинг 10
// Прототипы используемых функций
LRESULT CALLBACK WindowProc (HWND, UINT, WPARAM, LPARAM); /* Обрабатывает события окна */
void czCreateMenu(HWND hWwnd);          /* Создает меню главного окна */
void SaveScreen(HWND hWND);             /* Создает диалог для сохранения изображения (получает путь) */
bool save (HWND hWnd, OPENFILENAME openFile);   /* Непосредственно выполняет сохранение растрового изображения */

Листинг 11
// Функция создания меню:
void czCreateMenu(HWND hwnd)
{
    HMENU MainMenu = CreateMenu();          // Функция создает меню (пока пустое)
    HMENU hPopupMenu1 = CreatePopupMenu();      // Функция создает подменю - раскрывающееся меню (пока пустое)
    HMENU hPopupMenu2 = CreatePopupMenu();      // Функция создает подменю - раскрывающееся меню (пока пустое)
    HMENU hPopupMenu2_1 = CreatePopupMenu();        // Функция создает подменю - раскрывающееся меню (пока пустое)
    HMENU hPopupMenu3 = CreatePopupMenu();      // Функция создает подменю - раскрывающееся меню (пока пустое)
    AppendMenu(MainMenu, MF_STRING | MF_POPUP, (UINT)hPopupMenu1, L"&File"); // Функция добавляет "выпадающее" меню "Файл" в главную строку меню
    {
        AppendMenu(hPopupMenu1, MF_STRING | MF_CHECKED, 101, L"New");   // Функция добавляет пункт "Новый" в "выпадающее" меню "Файл"
        AppendMenu(hPopupMenu1, MF_SEPARATOR, 0, L"");          // Функция добавляет разделитель в "выпадающее" меню "Файл"
        AppendMenu(hPopupMenu1, MF_STRING, 102, L"Save");       // Функция добавляет пункт "Сохранить" в "выпадающее" меню "Файл"
        AppendMenu(hPopupMenu1, MF_STRING, 103, L"Save as..."); // Функция добавляет пункт "Сохранить как..." в "выпадающее" меню "Файл"
        AppendMenu(hPopupMenu1, MF_SEPARATOR, 0, L"");          // Функция добавляет разделитель в "выпадающее" меню "Файл"
        AppendMenu(hPopupMenu1, MF_STRING, 104, L"Exit");       // Функция добавляет пункт "Выход" в "выпадающее" меню "Файл"
    }
    AppendMenu(MainMenu, MF_STRING | MF_POPUP, (UINT)hPopupMenu2, L"&View");    // Функция добавляет "выпадающее" меню "Вид" в главную строку меню
    {
        AppendMenu(hPopupMenu2, MF_STRING | MF_POPUP, (UINT)hPopupMenu2_1, L"&Color"); // Функция добавляет "выпадающее" меню "Цвет" в "выпадающее" меню "Вид"
        {
            AppendMenu(hPopupMenu2_1, MF_STRING, 201, L"Black");    // Функция добавляет пункт "Черный" в "выпадающее" меню "Цвет"
            AppendMenu(hPopupMenu2_1, MF_STRING, 202, L"Blue"); // Функция добавляет пункт "Синий" в "выпадающее" меню "Цвет"
            AppendMenu(hPopupMenu2_1, MF_STRING, 203, L"Green");    // Функция добавляет пункт "Зеленый" в "выпадающее" меню "Цвет"
            AppendMenu(hPopupMenu2_1, MF_STRING, 204, L"Red");  // Функция добавляет пункт "Красный" в "выпадающее" меню "Цвет"
        }
    }
    AppendMenu(MainMenu, MF_STRING, 300, L"&Reset");                // Функция добавляет пункт "Сброс" в главную строку меню
    AppendMenu(MainMenu, MF_STRING | MF_POPUP, (UINT)hPopupMenu3, L"&Help");    // Функция добавляет "выпадающее" меню "Справка" в главную строку меню
    {
        AppendMenu(hPopupMenu3, MF_STRING, 401, L"&About");         // Функция добавляет пункт "О программе" в "выпадающее" меню "Справка"
    }
    SetMenu(hwnd, MainMenu);                                // Функция назначает новое меню для заданного окна
}

Листинг 12
#define WIN32_LEAN_AND_MEAN /* Ускоряет сборку за счет уменьшения размера заголовочных файлов, исключая наименее распространенные функции */
// Создание идентификаторов для событий выбора пунктов меню:
#define IDM_NEW 101 // Выбрано меню "New"
#define IDM_SAVE_AS 103 // Выбрано меню "Save as"
#define IDM_EXIT    104 // Выбрано меню "Exit"
#define IDM_BLACK   201 // Выбрано меню "Black"
#define IDM_BLUE    202 // Выбрано меню "Blue"
#define IDM_GREEN   203 // Выбрано меню "Green"
#define IDM_RED     204 // Выбрано меню "Red"
#define IDM_RESET   300 // Выбрано меню "Reset"
#define IDM_ABOUT   401 // Выбрано меню "About"

Листинг 13
// Функция обработки сообщений - Message processing function
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;              // Создание переменных для хранения параметров сообщения
    static bool Move = true;            // Логическая глобальная переменная, которая показывает должен ли перерисовываться график с изменением положения
    static int Phase=0, Width, Height;  // Переменные для аргумента периодической функции, длины и ширины области построения графика
    HPEN hPen;                  // Объявляем кисть
    switch (message)                // Использование переключателя для обработки различных событий окна
    {
        case WM_LBUTTONDOWN:            // Сообщение - нажата левая кнопка мыши
        case WM_RBUTTONDOWN:            // Сообщение - нажата правая кнопка мыши
            Move = !Move;           // Включить/выключить перемещение графика
            // Нет break, т.е. следующая ветка выполняется
        case WM_TIMER:          // Сообщение - истекло время таймера
            if (Move)           // Если Move==TRUE (если движение разрешено), то выполняется следующий оператор
                Phase++;        // Увеличение аргумента (фазы) функции на единицу
                // Нет break, т.е. следующая ветка выполняется, если Move==TRUE
            else                // Если Move!=TRUE (если движение запрещено), то выполняется следующий оператор
                break;          // Выполнение переключателя прерывается
        case WM_PAINT:          // Сообщение – требуется окрасить (перерисовать) часть окна приложения
            Rectangle (dc, -1, -1, Width+1, Height+1);              // Прорисовка прямоугольника в клиентской области
            MoveToEx (dc, 0, Height * (0.5 + 0.3*sin(0.1*Phase)), NULL);        // Функция устанавливает текущую позицию пера, равную (x,y) для указанного контекста отображения dc
            for (int i=0; i<Width; i++)                         // Цикл для рисования графика (изменение по оси X)
                LineTo (dc, i, Height * (0.5 + 0.3*sin(0.1*(i+Phase))) );   // Функция рисует линию из текущей позиции пера в точку с координатами, перечисленными в параметрах функции
            break;                                      // Выполнение переключателя прерывается
        case WM_SIZE:                                       // Сообщение – изменился размер окна
            Width = LOWORD(lParam), Height = HIWORD(lParam);    // Изменение значений ширины и высоты окна в соответствии с параметрами сообщения
            break;                              // Выполнение переключателя прерывается
        case WM_KEYDOWN:            // Сообщение - нажата несистемная клавиша (без + Alt). Посылается окну с фокусом клавиатуры
            if (wParam != VK_ESCAPE)    // Проверка – нажата ли клавиша «Esc»
                break;          // Выполнение переключателя прерывается
            // else no break – в противном случае прерывания переключателя нет, т.е. переход к завершению работы окна
        case WM_DESTROY:            // Сообщение – окно должно быть разрушено (завершить работу приложения). После этого сообщения окно удаляется с экрана
            PostQuitMessage (0);        // Функция направляет сообщение WM_QUIT в функцию WinMain (обычно в ответ на сообщение WM_DESTROY). Указывает системе, что процесс, сделавший запрос необходимо прекратить
            break;              // Выполнение переключателя прерывается
        case WM_COMMAND:            // Сообщение – выбран пункт меню или элемент управления (кнопка); нажата «горячая» клавиша
            break;              // Выполнение переключателя прерывается
    }
    return DefWindowProc (hWnd, message, wParam, lParam);       // Смотри комментарии выше
}


Листинг 14
            wmId    = LOWORD(wParam);   // Выделение из 32-битового целочисленного значения младшего слова и запись в переменную
            wmEvent = HIWORD(wParam);   // Выделение из 32-битового целочисленного значения старшего слова и запись в переменную
            // Новый переключатель для определения какой пункт меня выбран (кнопок нет, поэтому подобные события отсутствуют):
            switch (wmId)           // Параметром переключателя служит код-идентификатор, указанный при создании пункта меню
            {
                case IDM_SAVE_AS:       // Сообщение - выбран пункт меню «Сохранить как…»
                    SaveScreen (hWnd);  // Вызов функции сохранения изображения клиентской области
                    break;          // Выполнение переключателя прерывается
                case IDM_EXIT:      // Сообщение - выбран пункт меню «Выход»
                    DestroyWindow(hWnd);    // Функция уничтожает окно. Она посылает сообщения WM_DESTROY и WM_NCDESTROY окну, чтобы разрушить его и удалить фокус клавиатуры из него. Функция также уничтожает меню, очищает очередь сообщений, разрушает таймеры и т.д.
                    break;          // Выполнение переключателя прерывается
                case IDM_BLACK:     // Сообщение - выбран пункт меню «Черный»
                    hPen=CreatePen(PS_SOLID, 1, RGB(0,0,0));    // Создание пера с определенным стилем, шириной и цветом
                    SelectObject(dc, hPen);         // Функция производит выбор объекта в контекст устройства
                    break;                      // Выполнение переключателя прерывается
                case IDM_BLUE:                  // Сообщение - выбран пункт меню «Синий»
                    hPen=CreatePen(PS_SOLID, 1, RGB(0,0,255));  // Создание пера с определенным стилем, шириной и цветом
                    SelectObject(dc, hPen);             // Функция производит выбор объекта в контекст устройства
                    break;                          // Выполнение переключателя прерывается
                case IDM_GREEN:                     // Сообщение - выбран пункт меню «Зеленый»
                    hPen=CreatePen(PS_SOLID, 1, RGB(0,255,0));  // Создание пера с определенным стилем, шириной и цветом
                    SelectObject(dc, hPen);             // Функция производит выбор объекта в контекст устройства
                    break;                          // Выполнение переключателя прерывается
                case IDM_RED:                           // Сообщение - выбран пункт меню «Красный»
                    hPen=CreatePen(PS_SOLID, 1, RGB(255,0,0));  // Создание пера с определенным стилем, шириной и цветом
                    SelectObject(dc, hPen);             // Функция производит выбор объекта в контекст устройства
                    break;                          // Выполнение переключателя прерывается
                case IDM_NEW:                           // Сообщение - выбран пункт меню «Новый»
                case IDM_RESET:                     // Сообщение - выбран пункт меню «Сброс»
                    Phase=0;                        // Сброс значения аргумента периодической функции в нуль
                    break;                          // Выполнение переключателя прерывается
                case IDM_ABOUT:                     // Сообщение - выбран пункт меню «О программе»
                    MessageBox(hWnd,L"PlotDrawer v.1.0. Copyright © M. Gorozheev Ph.D., 2015",L"About MessageBox", MB_OK | MB_ICONWARNING);    /* Функция отображает модальное диалоговое окно, которое содержит набор кнопок и краткое сообщение конкретных приложений (в данном случае – информацию о программе). Окно возвращает целое значение, указывающее, какая кнопка нажата пользователем */
                    break;          // Выполнение переключателя прерывается
                default:            // Эта «ветка» выполняется, если нет ни одного совпадения сообщения с метками case
                    return DefWindowProc(hWnd, message, wParam, lParam);    /* Функция обеспечивает стандартную обработку сообщений, которые явно не обрабатываются в функции WindowProc данного приложения. Эта функция гарантирует, что каждое сообщение обрабатывается. Она вызывается с теми же параметрами, что были получены функцией WindowProc */
            }

Листинг 15
// Функция создает диалог для сохранения изображения (получает путь)
void SaveScreen(HWND hWnd)
{
    OPENFILENAME openFile;  // Создание структуры. В нее записывается информация о выборе пользователя после закрытия диалогового окна
    TCHAR szPath[MAX_PATH]; // Символьный массив для хранения пути к файлу
    TCHAR szFile[MAX_PATH]; // Символьный массив для хранения имени файла
    // Инициализация структуры OPENFILENAME:
    ZeroMemory( &openFile, sizeof(OPENFILENAME) ); // Функция ZeroMemory заполняет блок памяти нулями
    openFile.lStructSize = sizeof(OPENFILENAME);   // lStructSize определяет длину структуры (байт); инициализируем оператором sizeof
    szFile[0] = '';                 // Делаем строку пустой, т.е. символ конца строки идет первым в массиве
    openFile.hwndOwner = hWnd;              // hwndOwner - дескриптор окна, которое владеет блоком диалога
    openFile.lpstrFile = szFile;            // Указатель на буфер с именем файла. Когда функция GetOpenFileName или GetSaveFileName возвращает значение, этот буфер содержит идентификатор диска, путь, имя и расширение выбранного файла
    openFile.nMaxFile = sizeof(szFile)/sizeof(*szFile);    // Размер буфера, в символах (TCHAR), указанного членом lpstrFile
    openFile.lpstrFilter = L"Bitmap Files (*.bmp)*.bmp"; // Указатель на буфер, содержащий пары строк фильтров с нулевым символом в конце. Последняя строка в буфере должна быть завершена двумя символами ПУСТО (NULL)
    openFile.lpstrDefExt = L"*.bmp";    // Указатель на буфер, который содержит заданное по умолчанию расширение
    // При первом сохранении документа пользователем путь по умолчанию приходится на папку «Мои рисунки»:
    if ( TRUE == bFirstSave )       // Если логическая переменная равняется истине, то использовать путь по умолчанию
    {
        /* Функция SHGetFolderPath возвращает полный путь к указанному специальному каталогу по его идентификатору. Макрос SUCCEEDED предусматривает унифицированную проверку на успешное завершение при любом значении состояния: */
        if ( SUCCEEDED( SHGetFolderPath( NULL, CSIDL_MYPICTURES, NULL, 0, szPath ) ) )
        {
        // Инициализация lpstrInitialDir значением (путем), который функция SHGetFolderPath записала в szPath.
        // Из-за этого функция GetSaveFileName представляет папку «Мои рисунки» в качестве начального каталога для диалогового окна:
            openFile.lpstrInitialDir = szPath;
        }
    }
    // Отображается окно стандартного диалога сохранения файла с путем по умолчанию в каталог «Мои рисунки» или выбранное пользователем
    // ранее местоположение. Функция GetSaveFileName создает диалоговое окно «Сохранить», а оператор if проверяет наличие ошибок:
    if ( GetSaveFileName( &openFile ) == TRUE ) // Смотри выше
    {
        // Пользователь нажал кнопку «Сохранить».
        // Происходит сохранение файла:
        UpdateWindow (hWnd);    // Перерисовка главного окна в связи с появлением диалогового (иначе изображение перекрывалось бы)
        save(hWnd, openFile);   // Вызов функции, которая непосредственно сохраняет изображение клиентской области окна в файл
        bFirstSave = FALSE;     // Логическая переменная «Первое_Сохранение» становится равной FALSE
    }
    else    // Если не нажата кнопка «Сохранить»
    {
        // Пользователь прервал диалог сохранения файла, или возникла ошибка
    }
}

Листинг 16
// Функция, непосредственно сохраняющая изображение клиентской области окна в файл
bool save (HWND hWnd, OPENFILENAME openFile)
{
    // Создание структуры с атрибутами файла:
    HDC hdcScreen;
    HDC hdcWindow;
    HDC hdcMemDC = NULL;
    HBITMAP hbmScreen = NULL;
    BITMAP bmpScreen;
    // Получить дескриптор контекста устройства дисплея для клиентской области окна:
    hdcScreen = GetDC(NULL);
    hdcWindow = GetDC(hWnd);
    // Создание совместимого DC, который используется в BitBlt из окна DC:
    hdcMemDC = CreateCompatibleDC(hdcWindow);
    if(!hdcMemDC)           // Если создать DC не получилось, выводится модальное окно с сообщением об ошибке
    {
        MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
        goto done;      // Переход к завершающему коду (освобождению памяти)
    }
    // Получить клиентскую область для расчета размера:
    RECT rcClient;              // Создание прямоугольника для хранения координат рабочей области окна
    GetClientRect(hWnd, &rcClient);     // Получение координат рабочей области окна
   
    // Создать совместимый bitmap (точечный рисунок) из окна DC
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top);
    if(!hbmScreen)      // Если создать bitmap не получилось, выводится модальное окно с сообщением об ошибке
    {
        MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK);
        goto done;      // Переход к завершающему коду (освобождению памяти)
    }
    // Выбор совместимого bitmap (растрового изображения) в памяти совместимого DC:
    SelectObject(hdcMemDC,hbmScreen);
    /* Копирование блока битов в память совместимого DC. Функция BitBlt используется для копирования отдельных битов из области источника изображения в область-получатель. Если копирование не удалось, выводится модальное окно с сообщением об ошибке: */
    if(!BitBlt(hdcMemDC, 0, 0, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, hdcWindow, 0, 0, SRCCOPY))
    {
        MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK);
        goto done;      // Переход к завершающему коду (освобождению памяти)
    }
    // Получить BITMAP (точечный рисунок) из HBITMAP:
    GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);
    BITMAPFILEHEADER   bmfHeader;
    BITMAPINFOHEADER   bi;
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmpScreen.bmWidth;
    bi.biHeight = bmpScreen.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = 32;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;
    DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmpScreen.bmHeight;
    // Начиная с 32-битной Windows, GlobalAlloc и LocalAlloc реализованы как «функции-обертки», которые вызывают HeapAlloc,
    // используя дескриптор, ссылающийся на кучу, выделяемую процессу по умолчанию. Таким образом, GlobalAlloc и LocalAlloc
    // имеют большую нагрузку, чем HeapAlloc:
    HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);
    char *lpbitmap = (char *)GlobalLock(hDIB);
    // Получаем "биты" из растрового изображения и копируем их в буфер, на который указывает lpbitmap:
    GetDIBits(hdcWindow, hbmScreen, 0, (UINT)bmpScreen.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
    // Создается файл. Именно здесь происходит сохранение захваченного изображения клиентской области:
    HANDLE hFile = CreateFile(openFile.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    // Добавление размера заголовков к размеру растрового изображения, чтобы получить общий размер файла:
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    // Смещение, определяющее, где фактически начинаются биты растрового изображения:
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
    // Размер файла:
    bmfHeader.bfSize = dwSizeofDIB;
    // Компонент bfType всегда должен равняться BM для растровых изображений:
    bmfHeader.bfType = 0x4D42;      //Тип BM
    DWORD dwBytesWritten = 0;
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
    // Разблокировка и освободить DIB (Device Independent Bitmap, растровое изображение) из кучи (памяти):
    GlobalUnlock(hDIB);
    GlobalFree(hDIB);
    CloseHandle(hFile);         // Закрыть дескриптор для файла, который был создан
    // После метки производится освобождение памяти (удаление объектов) и выход из функции:
done:
    DeleteObject(hbmScreen);
    DeleteObject(hdcMemDC);
    ReleaseDC(NULL,hdcScreen);
    ReleaseDC(hWnd,hdcWindow);
    return TRUE;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог