Глубокое системное программирование

Содержание

Слайд 2

Болтов, Юрий Федорович. Операционные системы : учеб. пособие (спец. 230102, 230105)

Болтов, Юрий Федорович. Операционные системы : учеб. пособие (спец. 230102, 230105)

: в 2 ч. / Ю. Ф. Болтов, В. Ю. Баженова ; рец. М. О. Колбанев ; Федер. агентство связи, Гос. образовательное учреждение высш. проф. образования "С.- Петерб. гос. ун-т телекоммуникаций им. проф. М. А. Бонч-Бруевича". - СПб. : СПбГУТ, 2008. Ч. 1. - 107 с. : ил., табл. - Библиогр.: с. 104-105. - (в обл.) : 111.38 р.
Защита информации в OC UNIX : учебное пособие / А. В. Красов [и др.] ; рец. С. Е. Душин ; Федеральное агентство связи, Федеральное государственное образовательное бюджетное учреждение высшего профессионального образования "Санкт-Петербургский государственный университет телекоммуникаций им. проф. М. А. Бонч-Бруевича". - СПб. : СПбГУТ. Ч. 1. - 2012. - 71 с. - 226.31 р.
Защита информации в OC UNIX : учебное пособие / А. В. Красов [и др.] ; рец. С. Е. Душин ; Федеральное агентство связи, Федеральное государственное образовательное бюджетное учреждение высшего профессионального образования "Санкт-Петербургский государственный университет телекоммуникаций им. проф. М. А. Бонч-Бруевича". - СПб. : СПбГУТ. Ч. 2. - 2012. - 70 с. - 226.31 р.
Мартемьянов, Ю. Ф. Операционные системы. Концепции построения и обеспечения безопасности. Учебное пособие для вузов : [Электронный ресурс] / Ю. Ф. Мартемьянов, Ал. В. Яковлев, Ан. В. Яковлев. - М. : Горячая линия–Телеком, 2010. - 332 с. : ил. - URL: http://ibooks.ru/reading.php?productid=334008. - ISBN 978-5-9912-0128-5 : Б. ц.

Основная литература:

Слайд 3

Олифер, Виктор Григорьевич.Сетевые операционные системы / В. Г. Олифер, Н. А.

Олифер, Виктор Григорьевич.Сетевые операционные системы / В. Г. Олифер, Н. А.

Олифер. - СПб. : Питер, 2002. - 544 с. : ил. - ISBN 5-272-00120-6 : 102.00 р., 85.00 р., 76.50 р. - Текст :непосредственный.
Болтов, Юрий Федорович. Операционные системы : учеб. пособие (спец. 230102, 230105) : в 2 ч. / Ю. Ф. Болтов, В. Ю. Баженова ; рец. М. О. Колбанев ; Федер. агентство связи, Гос. образовательное учреждение высш. проф. образования "С.- Петерб. гос. ун-т телекоммуникаций им. проф. М. А. Бонч-Бруевича". - СПб. : СПбГУТ, 2008. Ч. 2. - 83 с. : ил., табл. - Библиогр.: с. 82-83. - (в обл.) : 86.63 р.
Красов, Андрей Владимирович. Защита информации в OC UNIX : метод. указ. к лаб. работам / А. В. Красов, А. Ю. Цветков, И. А. Федянин ; рец. С. Е. Душин ; Федер. агентство связи, Федер. гос. образовательное бюдж. учреждение высш. проф. образования "С.-Петерб. гос. ун-т телекоммуникаций им. проф. М. А. Бонч-Бруевича". - СПб. : СПбГУТ, 2012. - 28 с. : ил. - Библиогр.: с. 28. - (в обл.) : 62.58 р. - Текст : непосредственный.
Таненбаум, Э. Современные операционные системы. 3-е изд. : [Электронный ресурс] / Э. Таненбаум. - Санкт-Петербург : Питер, 2013. - 2120 с. : ил. - URL: http://ibooks.ru/reading.php?productid=344100. - ISBN 978-5-496-00301-8 : Б. ц.
Зубков, С. В. Assembler. Для DOS, Windows и Unix : [Электронный ресурс] / С. В. Зубков. - Москва : ДМК Пресс, 2004. - 640 с. : ил. - URL: http://ibooks.ru/reading.php?productid=26627. - ISBN 5-94074-259-9 : Б. ц.
Операционные системы : учебное пособие. - Москва : ТУСУР. - URL: http://e.lanbook.com/books/element.php?pl1_cid=25&pl1_id=4971. Ч. 2 / Ю. Б. Гриценко. - Москва : ТУСУР, 2009. - 230 с. - Б. ц. Книга из коллекции ТУСУР - Инженерно-технические науки
Операционные системы : учебное пособие. - Москва : ТУСУР. - URL: http://e.lanbook.com/books/element.php?pl1_cid=25&pl1_id=4972. Ч. 1 / Ю. Б. Гриценко. - Москва : ТУСУР, 2009. - 187 с. - Б. ц. Книга из коллекции ТУСУР - Инженерно-технические науки

Дополнительная литература:

Слайд 4

Подготовка к системному программированию Visual Studio Professional 2013 (или Ultimate-версия): http://msdn.microsoft.com/en-US/windows/hardware/gg454513

Подготовка к системному программированию

Visual Studio Professional 2013 (или Ultimate-версия):
http://msdn.microsoft.com/en-US/windows/hardware/gg454513
Windows Software Development

Kit – SDK 8.1:
http://msdn.microsoft.com/en-US/windows/desktop/bg162891
Windows Driver Kit – WDK 8.1:
http://msdn.microsoft.com/en-US/windows/hardware/gg454513
Символьная информация о системных модулях Windows:
http://msdn.microsoft.com/en-US/windows/hardware/gg454513
Утилита Dependency Walker для просмотра зависимостей DLL-библиотек:
http://www.dependencywalker.com/
Набор утилит Sysinternals для глубокого просмотра процессов, дисков, сети и прочего:
http://technet.microsoft.com/en-us/sysinternals/bb545027
Слайд 5

Лакман Макдауэлл Г. Карьера программиста. 6-е изд. — СПб.: Питер, 2016.

Лакман Макдауэлл Г. Карьера программиста. 6-е изд. — СПб.: Питер, 2016.

— 688 с.: ил. — (Серия «Библиотека программиста»).
Внутреннее устройство Windows [Текст] / М. Руссинович, Д. Соломон, А. Ионеску, П. Йосифович. — 7-е изд. — СПб.: Питер, 2018. — 944 с.: ил. — (Серия «Классика computer science»).
Педзольд Ч. Программирование для Windows 95. В 2 т. Т. 1 — СПб.: BHV, 1996.
Шилд Г. Программирование на С и С++ для Windows 95. — Киев: Торгово-издательское бюро BHV, 1996.
Мюррей У., Паппас К. Создание переносимых приложений для Windows. — СПб.: BHV, 1997.
Рихтер Дж. Windows для профессионалов: создание эффективных Win32-приложений с учетом специфики 64-разрядной версии Windows: Пер. с англ. — 4-е изд. — СПб.: Питер; М.: Издательско-торговый дом "Русская редакция", 2003.
Шупак Ю. А. Win32 API. Разработка приложений для Windows. — СПб.: Питер, 2008.
Верма Р. Д. Справочник по функциям Win32 API. — 2-е изд., перераб. и доп. — М.: Горячая линия — Телеком, 2005.
Давыдов В. Г. Visual C++. Разработка Windows-приложений с помощью MFC и API-функций. — СПб.: БХВ-Петербург, 2008.
Саймон Р. Microsoft Windows 2000 API. Энциклопедия программиста. — Киев: Диасофт, 2001.
Вильямс М. Программирование в Windows 2000. Энциклопедия пользовате-ля. — Киев: Диасофт, 2000.
Юань Фень. Программирование графики для Windows. — СПб.: Питер, 2002.
Румянцев П. В. Азбука программирования в Win32 API. — М.: Горячая линия — Телеком, 2001.
Слайд 6

Основы программирования для ОС Windows При разработке приложений в Visual C++

Основы программирования для ОС Windows

При разработке приложений в Visual C++ множество

основных способов разработки программ:
использование интерфейса API Windows;
использование классов Microsoft Foundation Classes;
использование Windows Forms APP;
……………….
Слайд 7

Основы программирования для ОС Windows Способы разработки приложений в среде Visual C++

Основы программирования для ОС Windows

Способы разработки приложений в среде Visual C++

Слайд 8

Основы программирования для ОС Windows Программирование, управляемое событиями Традиционные программы организованы

Основы программирования для ОС Windows

Программирование, управляемое событиями
Традиционные программы организованы иерархическим образом.

Например, в языке С++ наверху пирамиды находится функция main(), которая вызывает подпрограммы.
Однако программа Windows не организована иерархически в чистом виде. Программа содержит функции, но они предназначены для формирования отклика на внешние события.
Поэтому говорят, что программы Windows управляются событиями.
События в приложении Windows представляют собой различные происшествия, в частности:
щелчок кнопкой мыши;
Нажатие клавиши;
Истечение определенного интервала времени;
События могут быть сгенерированы функциями внутри вашей программы или других программ.
Слайд 9

Архитектура, управляемая событиями В основе взаимодействия программы с внешним миром и

Архитектура, управляемая событиями

В основе взаимодействия программы с внешним миром и с

операционной системой лежит концепция сообщений.
С точки зрения приложения, сообщение является уведомлением о том, что произошло некоторое событие, которое может требовать, а может и не требовать выполнения определенных действий. Это событие может быть следствием действий пользователя, например перемещения курсора или щелчка кнопкой мыши, изменения размеров окна или выбора пункта меню. Кроме того, событие может генерироваться приложением, а также операционной системой.
Слайд 10

Архитектура, управляемая событиями Сообщение - это структура данных, содержащая следующие элементы:

Архитектура, управляемая событиями

Сообщение - это структура данных, содержащая следующие элементы:
дескриптор

окна, которому адресовано сообщение;
код (номер) сообщения;
дополнительную информацию, зависящую от кода сообщения.
Сообщения в Windows описываются с помощью структуры MSG:
typedef struct tagMSG {
HWND hwnd; // Идентификатор окна-получателя
UINT message; // Идентификатор сообщения
WPARAM wParam; // Дополнительная информация, смысл
LPARAM lParam; // которой зависит от типа сообщения
DWORD time; // Время посылки сообщения
POINT pt; // Местоположение указателя мыши
} MSG;
Слайд 11

Архитектура, управляемая событиями Сообщения от внешних источников, например от клавиатуры, адресуются

Архитектура, управляемая событиями

Сообщения от внешних источников, например от клавиатуры, адресуются в

каждый конкретный момент времени только одному из работающих приложений, а именно - активному окну. Windows играет роль диспетчера сообщений. Для этого с момента старта операционная система создает в памяти глобальный объект, называемый системной очередью сообщений.
Все сообщения, генерируемые как аппаратурой, так и приложениями, помещаются в эту очередь. Windows периодически опрашивает эту очередь и, если она не пуста, посылает очередное сообщение нужному адресату, определяемому при помощи дескриптора окна.
Сообщения, получаемые приложением, могут поступать асинхронно из разных источников. Например, приложение может работать с системным таймером, посылающим ему сообщения с заданным интервалом, и одновременно оно должно быть готовым в любой момент получить любое сообщение от операционной системы. Чтобы не допустить потери сообщений, Windows одновременно с запуском приложения создает глобальный объект, называемый очередью сообщений приложения.
Слайд 12

Основы программирования для ОС Windows Структура Windows-приложения

Основы программирования для ОС Windows

Структура Windows-приложения

Слайд 13

Основы программирования для ОС Windows Генерация аппаратных событий На аппаратном уровне

Основы программирования для ОС Windows

Генерация аппаратных событий
На аппаратном уровне каждое устройство

ввода Windows управляется прерываниями.
Когда пользователь нажимает клавишу клавиатуры, генерируется аппаратное прерывание. Windows приостанавливает работу и передает управлению фрагменту кода –Interrupt Service Routine –ISR (Программа обработки прерываний).
ISR формирует специальные данные и записывает их в регистры. Затем вызывается специальная внутренняя программа Windows, которая извлекает данные из регистров и помещает запись о событии в аппаратную очередь Windows.
Далее аппаратные события передаются в очередь приложения.
Таким образом, даже при том, что аппаратный ввод является управляемым прерываниями, сообщения события обрабатываются приложением в порядке FIFO.
Слайд 14

Основы программирования для ОС Windows Назначение сообщений Сообщения – это стандартный

Основы программирования для ОС Windows

Назначение сообщений
Сообщения – это стандартный механизм связи

внутри программ

Источники сообщений

События аппаратного ввода генерируются мышью, клавиатурой, таймером и т.д.
События диспетчера окон генерируются Windows в ответ на действия пользователя, выполняющего операции типа перемещения или изменения размеров окна, выбора пунктов меню. Пример сообщения данного типа –WM_PAINT.
Индивидуальные окна могут посылать сообщения другим окнам. Например, для указания текстовому полю об удалении текста посылается сообщение WM_SETTEXT. Текстовое поле также использует данный механизм для сообщения об изменении текста путем посылки программисту сообщения EN_CHANGE.

Слайд 15

Основы программирования для ОС Windows Назначение сообщений Сообщения Windows идентифицируются мнемоническими

Основы программирования для ОС Windows

Назначение сообщений
Сообщения Windows идентифицируются мнемоническими идентификаторами, которые

соответствуют целочисленным константам.
Сообщения, сгенерированные непосредственно Windows, начинаются с символов «WM_» (Windows Message).
Сообщения, сгенерированные специфическими видами средств управления Windows, имеют различные префиксы. Например, сообщения, сгенерированные средствами редактирования имеют префикс «EN_» (Edit Notification).
Все эти константы определены в файле WinUser.h.
#define WM_NULL 0x0000
#define WM_CREATE 0x0001
#define WM_DESTROY 0x0002
#define WM_MOVE 0x0003
#define WM_SIZE 0x0005
Слайд 16

Основы программирования для ОС Windows Назначение сообщений typedef struct tagMSG {

Основы программирования для ОС Windows

Назначение сообщений
typedef struct tagMSG { // msg


HWND hwnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time;
POINT pt;
} MSG;
hwnd - Определяет окно которого процедура окна получает сообщение.
Message - Указывает номер сообщения.
wParam - Определяет дополнительную информацию о сообщении. Точный смысл зависит от значения элемента сообщение.
lParam - Определяет дополнительную информацию о сообщении. Точный смысл зависит от значения элемента сообщение.
time - Указывает время, когда сообщение было создано.
pt -Задает положение курсора в координатах экрана, когда сообщение было создано.
Слайд 17

Основные понятия. Элементы окна Пиктограмма панели заголовка Текст панели заголовка Панель

Основные понятия. Элементы окна

Пиктограмма панели заголовка

Текст панели заголовка

Панель меню

Панель инструментов

Клиентская область

Панель

состояния

Стандартные окна программы Windows

Слайд 18

Интерфейс Windows API Разработчиками ОС Windows была создана библиотека функций, при

Интерфейс Windows API

Разработчиками ОС Windows была создана библиотека функций, при помощи

которых происходит взаимодействие приложения с операционной системой, так называемые функции Программного интерфейса приложений (Application Program Interface).
Для разработки минимальной программы с использованием Win API необходимо написать две функции:
- WinMain(), с которой начинается выполнение программы и происходит её инициализация;
- WndProc(), вызываемая Windows для обработки сообщений приложения.
Слайд 19

Интерфейс Windows API Структура Windows-программы

Интерфейс Windows API

Структура Windows-программы

Слайд 20

Структура Windows-приложения

Структура Windows-приложения

Слайд 21

Каркас Windows-приложения Определить класс окна. Зарегистрировать окно. 3. Создать окно данного

Каркас Windows-приложения

Определить класс окна.
Зарегистрировать окно.
3. Создать окно данного класса.
4. Отобразить

окно.
5. Запустить цикл обработки сообщений.

Структура окна

Слайд 22

Каркас Win32 приложения Основу программы в Win32 составляет функция WinMain, которая

Каркас Win32 приложения

Основу программы в Win32 составляет функция WinMain, которая «заменяет»

собой стандартную функцию main языков C и C++.
Описание этой функции имеет следующий вид:
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{

return Код_вовзрата;
}
В некоторых средах разработки вместо WINAPI пишут APIENTRY
Слайд 23

Каркас Win32 приложения Параметры функции WinMain: HINSTANCE hInstance – идентификатор текущего

Каркас Win32 приложения

Параметры функции WinMain:
HINSTANCE hInstance – идентификатор текущего приложения;
HINSTANCE hPrevInstance

– идентификатор приложения, являющегося родительским для данного приложения;
LPTSTR lpCmdLine – С-строка, содержащая параметры командной строки;
int nCmdShow – код вида начального отображения окна.
Возвращаемое значение функции WinMain: целое число, интерпретируемое как код возврата. Обычно в качестве его значения указывается параметр сообщения закрытия приложения в виде:
(int) msg.wParam
Слайд 24

Каркас Win32 приложения НАЧАЛО Описание класса окна Регистрация класса окна Создание

Каркас Win32 приложения

НАЧАЛО

Описание класса окна

Регистрация класса окна

Создание окна

Отображение окна

Ожидание, прием и

обработка сообщения

Это сообщение
завершения

КОНЕЦ

Да

Слайд 25

Каркас Win32 приложения Для описания класса окна необходимо заполнить структуру типа

Каркас Win32 приложения

Для описания класса окна необходимо заполнить структуру типа WNDCLASSEX

или WNDCLASS (старый вариант).
typedef struct tagWNDCLASSEXW {
UINT cbSize; //Размер структуры
UINT style; //Стиль окна
WNDPROC lpfnWndProc; //Адрес функции обработки сообщений
int cbClsExtra; //Размер дополнительной памяти в байтах под
//структуру класса-окна (инициализируется 0)
int cbWndExtra; //Размер дополнительной памяти в байтах под
//структуру окна (инициализируется 0)
HINSTANCE hInstance; //Код приложения
HICON hIcon; //Код идентификатора иконки приложения
HCURSOR hCursor; //Код идентификатора курсора
HBRUSH hbrBackground; //Код идентификатора кисти фона окна
LPCWSTR lpszMenuName; //Имя ресурса, описывающего меню программы
LPCWSTR lpszClassName; //Имя класса окна
HICON hIconSm; //Код идентификатора иконки класса окна
} WNDCLASSEXW;
Слайд 26

Каркас Win32 приложения После заполнения всех полей данной структуры класса окна

Каркас Win32 приложения

После заполнения всех полей данной структуры класса окна необходимо

зарегистрировать с помощью функции RegisterClassEx() или RegisterClass() (старый вариант).
Прототип функции:
ATOM RegisterClassEx(CONST WNDCLASSEX *lpwcx );
В параметре в функцию передается адрес заполненной структуры типа WNDCLASSEX.
Функция возвращает идентификатор зарегистрированного класса окна в случае успешного выполнения. В случае ошибки функция возвращает 0.
Слайд 27

Каркас Win32 приложения После успешной регистрации класса окна необходимо создать само

Каркас Win32 приложения

После успешной регистрации класса окна необходимо создать само окно.

Это осуществляется с помощью функции CreateWindow.
Прототип функции:
HWND CreateWindow(
LPCTSTR lpClassName, //С-строка содержащая имя класса
LPCTSTR lpWindowName, //C-строка содержащая имя окна
DWORD dwStyle, //Стиль окна
int x, //Позиция x на экране
int y, //Позиция y на экране
int nWidth, //Ширина окна (по оси X)
int nHeight, //Высота окна (по оси Y)
HWND hWndParent, //Дескриптор родительского окна
HMENU hMenu, //Дескриптор главного меню
HINSTANCE hInstance, //Идентификатор приложения
LPVOID lpParam //Параметры сообщения WM_CREATE
);
Слайд 28

Каркас Win32 приложения В случае успешного выполнения функция CreateWindow возвращает дескриптор

Каркас Win32 приложения

В случае успешного выполнения функция CreateWindow возвращает дескриптор созданного

окна. В случае ошибки функция возвращает NULL.
Некоторые стили окна:
Слайд 29

Каркас Win32 приложения После того, как окно успешно создано, его необходимо

Каркас Win32 приложения

После того, как окно успешно создано, его необходимо отобразить

используя функции ShowWindow и UpdateWindow.
Функция отображения окна:
BOOL ShowWindow(HWND hWnd, int nCmdShow);
Некоторые типы команд отображения окна:
SW_HIDE – скрыть окно и активизировать другое окно,
SW_MAXIMIZE – развернуть на весь экран,
SW_MINIMIZE – свернуть окно и активизировать предыдущее окно,
SW_RESTORE – восстановить изначальные размеры окна,
SW_SHOW – активизировать окно и отобразить его.
Функция возвращает истину, если окно было изначально видимо, и ложь – если нет.
Функция обновления окна:
void UpdateWindow(HWND hWnd);
Вызывает обновление (перерисовку) окна.
Слайд 30

Каркас Win32 приложения После создания и отображения окна необходимо организовать цикл

Каркас Win32 приложения

После создания и отображения окна необходимо организовать цикл получения

и обработки сообщений. Для этих целей в Win32 API используются следующие функции:
GetMessage – получение сообщения,
TranslateMessage – преобразует сообщения виртуальных клавиш в символьные сообщения,
DispatchMessage – вызывает обработчик сообщения.
Слайд 31

Каркас Win32 приложения Функция получения сообщения BOOL GetMessage( LPMSG lpMsg, //Указатель

Каркас Win32 приложения

Функция получения сообщения
BOOL GetMessage(
LPMSG lpMsg, //Указатель на структуру MSG
HWND hWnd, //Дескриптор окна

UINT wMsgFilterMin, //Минимальный номер отслеживаемых сообщений
UINT wMsgFilterMax //Максимальный номер отслеживаемых сообщений
);
Если функция получает сообщение отлично от WM_QUIT, то возвращается не нулевое значение (истина).
Слайд 32

Каркас Win32 приложения Функция преобразования сообщения виртуальных клавиш в символьные сообщения

Каркас Win32 приложения

Функция преобразования сообщения виртуальных клавиш в символьные сообщения
BOOL TranslateMessage(const MSG *lpMsg

);
Возвращает значение «истина», если сообщение было успешно преобразовано. Если сообщение не преобразовано, то возвращает значение «ложь»
Данная функция предназначена для создания сообщений WM_CHAR на основе сообщений WM_KEYDOWN и WM_KEYUP.
Слайд 33

Каркас Win32 приложения Функция обработки сообщения LRESULT DispatchMessage(const MSG *lpmsg );

Каркас Win32 приложения

Функция обработки сообщения
LRESULT DispatchMessage(const MSG *lpmsg );
Функция вызывает функцию-обработчик сообщений для

данного окна и возвращает результат обработки.
Значение результата зависит от самой функции-обработчика, и как правило игнорируется.
Слайд 34

Типовая функция WinMain int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR

Типовая функция WinMain

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR

lpCmdLine, int nCmdShow)
{
MSG msg; HWND hwnd;
WNDCLASSEX wcx;
//Заполнение полей структуры wcx
if(!RegisterClassEx(&wcx)) return FALSE;
hwnd = CreateWindow(/*параметры*/);
if(!hwnd) return FALSE;
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
Слайд 35

Функция-обработчик сообщений Прототип функции: LRESULT CALLBACK WndProc( HWND hwnd, //Дескриптор окна

Функция-обработчик сообщений

Прототип функции:
LRESULT CALLBACK WndProc(
HWND hwnd, //Дескриптор окна
UINT message, //Код сообщения
WPARAM wParam, //Первый параметр

сообщения
LPARAM lParam //Второй параметр сообщения
);
Тип WPARAM – unsigned int
Тип LPARAM – long
Слайд 36

Типовой алгоритм функции WndProc LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM

Типовой алгоритм функции WndProc

LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam,

LPARAM lParam)
{
switch(message){
case WM_DESTROY:
PostQuitMessage(0);
break;
case СОБЫТИЕ_1:
//Обработка события 1
break;
case СОБЫТИЕ_2:
//Обработка события 1
break;

default: return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
Слайд 37

Некоторые сообщения

Некоторые сообщения

Слайд 38

Дополнительные функции Функция определения существования окна BOOL IsWindow(HWND hwnd); Функция проверки

Дополнительные функции

Функция определения существования окна
BOOL IsWindow(HWND hwnd);
Функция проверки наличия фокуса ввода

у окна
BOOL IsWindowEnabled(HWND hwnd);
Функция разрешения или запрета фокуса ввода у окна
BOOL EnableWindow(HWND hwnd, BOOL flag);
Функция передачи фокуса управления окну
HWND SetFocus(HWND hwnd);
Функция поиска окна с заданными классом и названием
HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName);
Слайд 39

Дополнительные функции Функция перемещения окна BOOL MoveWindow(HWND hwnd, int x, int

Дополнительные функции

Функция перемещения окна
BOOL MoveWindow(HWND hwnd, int x, int y, int

nWidth, int nHeight,
BOOL bRepaint);
Функция относительного перемещения окна:
BOOL SetWindowPos(HWND hwnd, HWND hwndInsertAfter, int x, int y,
int nWidth, int nHeight, UINT uFlags);
hwndInsertAfter может быть дескриптором существующего окна или одним из следующих значений:
HWND_BOTTOM – помещает окно ниже других окон,
HWND_NOTOPMOST – помещает временное или дочернее окно выше временных или дочерних окон, но ниже перекрывающихся окон,
HWND_TOP – помещает окно выше всех окон,
HWND_TOPMOST – то же, что HWND_NOTOPMOST, но окно сохраняет позицию после потери активности.
Слайд 40

Дополнительные функции Вывод окна на передний план и передача ему управления:

Дополнительные функции

Вывод окна на передний план и передача ему управления:
BOOL SetForegroundWindow(HWND

hwnd);
Функция получения системных метрик:
int GetSystemMetric(int nIndex);
nIndex может принимать следующие значения:
SM_CXMIN – минимальная ширина окна,
SM_CYMIN – минимальная высота окна,
SM_CXSCREEN – ширина окна,
SM_CYSCREEN – высота окна,
SM_CYCAPTOIN – высота заголовка окна,
SM_CYMENU – высота меню окна.
Слайд 41

Дополнительные функции Функция получения параметров окна: BOOL GetWindowRect(HWND hwnd, LPRECT rect);

Дополнительные функции

Функция получения параметров окна:
BOOL GetWindowRect(HWND hwnd, LPRECT rect);
Функция получения параметров

рабочей области окна:
BOOL GetClientRect(HWND hwnd, LPRECT rect);
typedef struct{
LONG left; //Левый край
LONG top; //Верхний край
LONG right; //Правый край
LONG bottom; //Нижний край
} RECT;
Слайд 42

Окно сообщения Вызов окна сообщения осуществляется с помощью функции: int WINAPI

Окно сообщения

Вызов окна сообщения осуществляется с помощью функции:
int WINAPI MessageBox(
HWND hwnd, //Дескриптор

окна
LPCTSTR lpText, //С-строка текста сообщения
LPCTSTR lpCaption, //С-строка заголовка сообщения
UINT uType //Флаги окна сообщения
);
Слайд 43

Окно сообщения

Окно сообщения

Слайд 44

Окно сообщения

Окно сообщения

Слайд 45

Интерфейс Windows API Функция WinMain() выполняет четыре основные функции: - сообщает

Интерфейс Windows API

Функция WinMain() выполняет четыре основные функции:
- сообщает ОС, какого

вида окно требуется программе;
- создает окно программы;
- инициализировать окно программы;
- извлекает сообщения Windows, предназначенные программе.
На псевдокоде функцию WinMain() можно представить следующим образом:
WinMain(список аргументов)
{
Подготовить и зарегистрировать класс окна с нужными характеристиками;
Создать экземпляр зарегистрированного класса;
Пока не произошло необходимое для выхода события
{
Извлечь очередное сообщение из очереди сообщений;
Передать его через Windows оконной функции;
}
Возврат из программы
}
Слайд 46

Интерфейс Windows API Функция WinMain() После того как Windows загружает программу,

Интерфейс Windows API

Функция WinMain()
После того как Windows загружает программу, то она

вызывает функцию WinMain.
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
MyRegisterClass(hInstance);
// Выполнить инициализацию приложения:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32_API));
// Цикл основного сообщения:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
Слайд 47

Интерфейс Windows API Функция WindowProc() Функция WndProc() является «функцией обратного вызова».

Интерфейс Windows API

Функция WindowProc()
Функция WndProc() является «функцией обратного вызова». Такие функции

вызываются операционной системой, а не самой программой.
WindowProc() обрабатывает все сообщения, которые поступают окну программы.
LRESULT CALLBACK WINDOWPROC(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam);
Аргументы функции:
hWnd – дескриптор окна, в котором произошло событие;
message – тип сообщения;
Слайд 48

Интерфейс Windows API LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,

Интерфейс Windows API

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM

lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Разобрать выбор в меню:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: добавьте любой код отрисовки...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
Слайд 49

Интерфейс Windows API Передача сообщений while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }

Интерфейс Windows API

Передача сообщений
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Слайд 50

Интерфейс Windows API case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO:

Интерфейс Windows API

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: добавьте любой код

отрисовки...
GetClientRect(hWnd,&rect);
DrawText(hdc,L"Здравствуй, МИР!",-1,&rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
Слайд 51

Библиотеки динамической компоновки DLL Одной из особенностей Windows-приложений является их способность

Библиотеки динамической компоновки DLL

Одной из особенностей Windows-приложений является их способность подключать

во время работы необходимые функции и ресурсы, которые размещены в так называемых библиотеках динамической компоновки (Dynamic-Link Libraries, DLL).
Все функции Windows содержатся в dll-файлах, например, графические функции размещены в файле gdi32.dll. Преимущество использования библиотек динамической компоновки перед статическими библиотеками проявляется в том, что приложение, состоящее даже из нескольких модулей, использует лишь один экземпляр функции, тогда как из статической библиотеки каждый программный модуль при-соединяет свою копию функции на этапе компоновки. Рассмотрим подробно способы создания динамических библиотек и их использование.
Слайд 52

Создание DLL Создание проекта библиотеки DLL в Visual Studio 1. В

Создание DLL

Создание проекта библиотеки DLL в Visual Studio

1. В строке меню

выберите Файл > Создать > Проект, чтобы открыть диалоговое окно Создание проекта.

2. В верхней части диалогового окна для параметра Язык установите значение C++ , для параметра Платформа — значение Windows, а для параметра Тип проекта — значение Библиотека.
3. В отфильтрованном списке типов проектов щелкните Библиотека динамической компоновки (DLL) , а затем нажмите кнопку Далее.
4. На странице Настроить новый проект введите MathLibrary в поле Имя проекта. Примите заданные по умолчанию Расположение и Имя решения. Для параметра Решение задайте Создать новое решение. Снимите флажок Разместить решение и проект в одном каталоге, если он установлен.
5. Нажмите кнопку Создать, чтобы создать проект.

Слайд 53

После создания решения созданный проект вместе с исходными файлами отобразится в

После создания решения созданный проект вместе с исходными файлами отобразится в

окне обозревателя решений в Visual Studio.

Пока эта библиотека DLL ничего не делает. Затем вы создадите файл заголовка для объявления функций, экспортируемых вашей библиотекой DLL, и добавите определения функций в библиотеку DLL, чтобы сделать ее более полезной.

Слайд 54

Добавление файла заголовка в библиотеку DLL 1. Чтобы создать файл заголовка

Добавление файла заголовка в библиотеку DLL

1. Чтобы создать файл заголовка для

функций, последовательно щелкните Проект > Добавить новый элемент.
2. В диалоговом окне Добавление нового элемента в левой области щелкните Visual C++ . В центральной области выберите Заголовочный файл (.h) . Укажите MathLibrary.h в качестве имени для файла заголовка.
Слайд 55

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

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

в новом окне редактора.
Слайд 56

4. Замените все содержимое этого файла заголовка следующим кодом: // Special

4. Замените все содержимое этого файла заголовка следующим кодом:
// Special

case when index == 0, just return b value
if (index_ > 0)
{
// otherwise, calculate next sequence value
previous_ += current_;
}
std::swap(current_, previous_);
++index_;
return true;
}
// Get the current value in the sequence.
unsigned long long fibonacci_current()
{
return current_;
}
// Get the current index position in the sequence.
unsigned fibonacci_index()
{
return index_;
}

// MathLibrary.cpp : Defines the exported functions for the DLL.
#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier
#include
#include
#include "MathLibrary.h"
// DLL internal state variables:
static unsigned long long previous_; // Previous value, if any
static unsigned long long current_; // Current sequence value
static unsigned index_; // Current seq. position
// Initialize a Fibonacci relation sequence
// such that F(0) = a, F(1) = b.
// This function must be called before any other function.
void fibonacci_init(
const unsigned long long a,
const unsigned long long b)
{
index_ = 0;
current_ = a;
previous_ = b; // see special case when initialized
}
// Produce the next value in the sequence.
// Returns true on success, false on overflow.
bool fibonacci_next()
{
// check to see if we'd overflow result or position
if ((ULLONG_MAX - previous_ < current_) ||
(UINT_MAX == index_))
{
return false;
}

Этот файл заголовка объявляет некоторые функции для создания обобщенной последовательности Фибоначчи, исходя из двух начальных значений. Вызов fibonacci_init(1, 1) создает знакомую последовательность чисел Фибоначчи.

Слайд 57

Добавление реализации в библиотеку DLL В обозревателе решений щелкните узел Файлы

Добавление реализации в библиотеку DLL

В обозревателе решений щелкните узел Файлы решения

правой кнопкой мыши и выберите пункты
Добавить > Новый элемент. Создайте новый CPP-файл с именем MathLibrary.cpp, аналогично добавлению нового файла заголовка на предыдущем шаге.
2. В окне редактора выберите вкладку MathLibrary.cpp, если она уже открыта. Если нет, то в обозревателе решений дважды щелкните файл MathLibrary.cpp в папке Исходные файлы проекта MathLibrary.
3. В редакторе замените содержимое файла MathLibrary.cpp следующим кодом:

// MathLibrary.cpp : Defines the exported functions for the DLL.
#include "pch.h" // use stdafx.h in Visual Studio 2017 and earlier
#include
#include
#include "MathLibrary.h"
// DLL internal state variables:
static unsigned long long previous_; // Previous value, if any
static unsigned long long current_; // Current sequence value
static unsigned index_; // Current seq. position
// Initialize a Fibonacci relation sequence
// such that F(0) = a, F(1) = b.
// This function must be called before any other function.
void fibonacci_init(
const unsigned long long a,
const unsigned long long b)
{
index_ = 0;
current_ = a;
previous_ = b; // see special case when initialized
}

// Produce the next value in the sequence.
// Returns true on success, false on overflow.
bool fibonacci_next()
{
// check to see if we'd overflow result or position
if ((ULLONG_MAX - previous_ < current_) ||
(UINT_MAX == index_))
{
return false;
}
// Special case when index == 0, just return b value
if (index_ > 0)
{
// otherwise, calculate next sequence value
previous_ += current_;
}
std::swap(current_, previous_);
++index_;
return true;
}
// Get the current value in the sequence.
unsigned long long fibonacci_current()
{
return current_;
}
// Get the current index position in the sequence.
unsigned fibonacci_index()
{
return index_;
}

Слайд 58

1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------ 1>pch.cpp 1>dllmain.cpp

1>------ Build started: Project: MathLibrary, Configuration: Debug Win32 ------
1>pch.cpp
1>dllmain.cpp
1>MathLibrary.cpp
1>Generating Code...
1> Creating

library C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.lib and object C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.exp
1>MathLibrary.vcxproj -> C:\Users\username\Source\Repos\MathLibrary\Debug\MathLibrary.dll
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
Слайд 59

Создание клиентского приложения, которое использует библиотеку DLL Библиотека DLL предоставляет эти

Создание клиентского приложения, которое использует библиотеку DLL

Библиотека DLL предоставляет эти сведения

в библиотеке импорта — файле, который содержит сведения о поиске функций и данных вместо фактического кода. Во время выполнения библиотека DLL должна быть доступна клиенту в месте, которое может найти операционная система.

Одним из решений является копирование всех этих файлов в ваш клиентский проект. Для сторонних библиотек DLL, которые вряд ли изменятся во время разработки вашего клиента, этот метод может быть лучшим способом их использования. Однако, когда вы также создаете библиотеку DLL, лучше избегать дублирования. Если вы делаете локальную копию файлов библиотеки DLL, которые находятся в стадии разработки, вы можете случайно изменить файл заголовка только в одной копии или использовать устаревшую библиотеку.

Чтобы избежать рассинхронизации, мы рекомендуем вам установить путь включения в своем клиентском проекте, чтобы добавить файлы заголовков библиотеки DLL напрямую из проекта DLL. Кроме того, укажите путь к библиотеке в своем клиентском проекте, чтобы добавить библиотеки импорта DLL из проекта DLL. Наконец, скопируйте встроенную библиотеку DLL из проекта DLL в выходной каталог своей сборки клиента. Этот шаг позволяет вашему клиентскому приложению использовать тот же код библиотеки DLL, который вы создали.

Слайд 60

Создание клиентского приложения в Visual Studio 1. В строке меню выберите

Создание клиентского приложения в Visual Studio

1. В строке меню выберите Файл

> Создать > Проект, чтобы открыть диалоговое окно Создание проекта.
2. В верхней части диалогового окна для параметра Язык выберите значение C++ , для параметра Платформа — значение Windows, а для параметра Тип проекта — значение Консоль.
3. В отфильтрованном списке типов проектов щелкните Консольное приложение, а затем нажмите кнопку Далее.
4. На странице Настроить новый проект введите MathClient в поле Имя проекта. Примите заданные по умолчанию Расположение и Имя решения. Для параметра Решение задайте Создать новое решение. Снимите флажок Разместить решение и проект в одном каталоге, если он установлен.

5. Нажмите кнопку Создать, чтобы создать клиентский проект.

Слайд 61

Добавление заголовка библиотеки DLL в путь включения 1. Щелкните правой кнопкой

Добавление заголовка библиотеки DLL в путь включения

1. Щелкните правой кнопкой мыши

узел MathClient в обозревателе решений, чтобы открыть диалоговое окно Страницы свойств.
2. В раскрывающемся списке Конфигурация выберите пункт Все конфигурации, если он еще не выбран.
3. В области слева выберите пункт Свойства конфигурации > C/C++ > Общие.
4. На панели свойств щелкните раскрывающийся элемент управления рядом с полем ввода параметра Дополнительные каталоги включаемых файлов, а затем щелкните Правка.
![Редактирование свойства "Дополнительные каталоги включаемых файлов"](media/mathclient-additional-include-directories-property.png "Редактирование свойства "Дополнительные каталоги включаемых файлов"")
5. Дважды щелкните в верхней панели диалогового окна Дополнительные каталоги включаемых файлов, чтобы включить элемент управления "Поле ввода". Или щелкните значок папки, чтобы создать новую запись.
6. В элементе управления "Поле ввода" укажите путь к расположению файла заголовка MathLibrary.h. Чтобы перейти к нужной папке, можно выбрать элемент управления с многоточием ( ... ).

..\..\MathLibrary\MathLibrary

Если библиотеки DLL и клиентские проекты находятся в одном решении, относительный путь может выглядеть следующим образом:

..\MathLibrary

![Добавление расположения заголовка в свойство "Дополнительные каталоги включаемых файлов"](media/mathclient-additional-include-directories.png "Добавление расположения заголовка в свойство "Дополнительные каталоги включаемых файлов"")

7. После ввода пути к файлу заголовка в диалоговом окне Дополнительные каталоги включаемых файлов нажмите кнопку ОК. В диалоговом окне Страницы свойств нажмите кнопку OK, чтобы сохранить изменения.

Слайд 62

Теперь можно добавить файл MathLibrary.h и использовать функции, которые он объявляет,

Теперь можно добавить файл MathLibrary.h и использовать функции, которые он объявляет,

в вашем клиентском приложении. Замените содержимое файла MathClient.cpp, используя следующий код:

// MathClient.cpp : Client app for MathLibrary DLL.
// #include "pch.h" Uncomment for Visual Studio 2017 and earlier
#include
#include "MathLibrary.h"
int main()
{
// Initialize a Fibonacci relation sequence.
fibonacci_init(1, 1);
// Write out the sequence values until overflow.
do {
std::cout << fibonacci_index() << ": "
<< fibonacci_current() << std::endl;
} while (fibonacci_next());
// Report count of values written before overflow.
std::cout << fibonacci_index() + 1 <<
" Fibonacci sequence values fit in an " <<
"unsigned 64-bit integer." << std::endl;
}

Слайд 63

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

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

клиентского приложения. Компоновщик сможет найти и использовать его автоматически. Однако если и библиотека, и клиентское приложение находятся в стадии разработки, это может привести к изменениям в одной копии, которые не будут отображаться в другой. Чтобы избежать этой проблемы, можно задать свойство Дополнительные зависимости, чтобы сообщить системе сборки о том, что проект зависит от MathLibrary.lib. Также можно задать путь Дополнительные каталоги библиотек в проекте, включив в него путь к исходной библиотеке при компоновке.
Слайд 64

Добавление библиотеки импорта DLL в проект 1. Щелкните правой кнопкой мыши

Добавление библиотеки импорта DLL в проект

1. Щелкните правой кнопкой мыши узел

MathClient в обозревателе решений и выберите Свойства, чтобы открыть диалоговое окно Страницы свойств.
2. В раскрывающемся списке Конфигурация выберите пункт Все конфигурации, если он еще не выбран. Это гарантирует, что любые изменения свойств применяются к сборкам отладки и выпуска.
3. В области слева выберите пункт Свойства конфигурации > Компоновщик > Ввод. На панели свойств щелкните раскрывающийся элемент управления рядом с полем ввода параметра Дополнительные зависимости, а затем щелкните Правка.
![Редактирование свойства "Дополнительные зависимости"](media/mathclient-additional-dependencies-property.png "Редактирование свойства "Дополнительные зависимости"")
4. В диалоговом окне Дополнительные зависимости добавьте MathLibrary.lib в список в верхнем элементе управления "Поле ввода".
Слайд 65

5. Нажмите кнопку OK, чтобы вернуться в диалоговое окно Страницы свойств.

5. Нажмите кнопку OK, чтобы вернуться в диалоговое окно Страницы свойств.
6.

В области слева выберите пункт Свойства конфигурации > Компоновщик > Общие. На панели свойств щелкните раскрывающийся элемент управления рядом с полем ввода параметра Дополнительные каталоги библиотек, а затем щелкните Правка.
![Редактирование свойства "Дополнительные каталоги библиотеки"](media/mathclient-additional-library-directories-property.png "Редактирование свойства "Дополнительные каталоги библиотеки"")
7. Дважды щелкните в верхней панели диалогового окна Дополнительные каталоги библиотек, чтобы включить элемент управления "Поле ввода". В элементе управления "Поле ввода" укажите путь к расположению файла MathLibrary.lib. По умолчанию он находится в папке с именем Debug непосредственно в папке решения DLL. При создании сборки выпуска файл помещается в папку с именем Release. Можно использовать макрос $(IntDir), чтобы компоновщик мог найти библиотеку DLL независимо от типа создаваемой сборки. Если вы следовали инструкциям по размещению клиентского проекта в отдельном решении, отличном от проекта DLL, относительный путь должен выглядеть следующим образом:

..\..\MathLibrary\$(IntDir)

8. Как только вы ввели путь к файлу библиотеки, в диалоговом окне Дополнительные каталоги библиотек нажмите кнопку ОК, чтобы вернуться в диалоговое окно Страницы свойств. Нажмите ОК, чтобы сохранить изменения свойств.

Слайд 66

![Ошибка "Библиотека DLL MathLibrary не найдена"](media/mathclient-system-error-mathlibrary-dll-not-found.png "Ошибка "Библиотека DLL MathLibrary не

![Ошибка "Библиотека DLL MathLibrary не найдена"](media/mathclient-system-error-mathlibrary-dll-not-found.png "Ошибка "Библиотека DLL MathLibrary не

найдена"")

Чтобы избежать этой проблемы, можно скопировать библиотеку DLL в каталог, в котором находится исполняемый файл клиента, в процессе сборки. Можно добавить событие после сборки в ваш проект, чтобы добавить команду, которая копирует библиотеку DLL в выходной каталог вашей сборки. Указанная здесь команда копирует библиотеку DLL только в том случае, если она отсутствует или была изменена. Он использует макросы для копирования в расположения отладки или выпуска на основе конфигурации сборки.

Слайд 67

Копирование библиотеки DLL в событие после сборки 1. Щелкните правой кнопкой

Копирование библиотеки DLL в событие после сборки

1. Щелкните правой кнопкой мыши

узел MathClient в обозревателе решений и выберите Свойства, чтобы открыть диалоговое окно Страницы свойств.
2. В раскрывающемся списке Конфигурация выберите пункт Все конфигурации, если он еще не выбран.
3. В области слева выберите Свойства конфигурации > События сборки > Событие после сборки.
4. В области свойств щелкните элемент управления "Поле ввода" в поле Командная строка. Если вы следовали инструкциям по размещению клиентского проекта в отдельном решении, отличном от проекта DLL, введите следующую команду:

xcopy /y /d "..\..\MathLibrary\$(IntDir)MathLibrary.dll" "$(OutDir)"

5. Нажмите кнопку OK, чтобы сохранить изменения в свойствах проекта.

Слайд 68

Теперь в вашем клиентском приложении есть все, что нужно для сборки

Теперь в вашем клиентском приложении есть все, что нужно для сборки

и запуска. Соберите приложение, щелкнув команду Сборка > Собрать решение в меню. Окно Вывод в Visual Studio должно иметь примерно следующий вид в зависимости от используемой версии Visual Studio:

1>------ Build started: Project: MathClient, Configuration: Debug Win32 ------
1>MathClient.cpp
1>MathClient.vcxproj -> C:\Users\username\Source\Repos\MathClient\Debug\MathClient.exe
1>1 File(s) copied
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

Для закрытия командного окна нажмите любую клавишу.

Слайд 69

Использование DLL Практически невозможно создать приложение Windows, в котором не использовались

Использование DLL
Практически невозможно создать приложение Windows, в котором не использовались бы

библиотеки DLL. В DLL содержатся все функции Win32 API и несчетное количество других функций операционных систем Win32.
Вообще говоря, DLL - это просто наборы функций, собранные в библиотеки. Однако, в отличие от своих статических родственников (файлов . lib), библиотеки DLL не присоединены непосредственно к выполняемым файлам с помощью редактора связей. В выполняемый файл занесена только информация об их местонахождении. В момент выполнения программы загружается вся библиотека целиком. Благодаря этому разные процессы могут пользоваться совместно одними и теми же библиотеками, находящимися в памяти. Такой подход позволяет сократить объем памяти, необходимый для нескольких приложений, использующих много общих библиотек, а также контролировать размеры ЕХЕ-файлов.
Однако, если библиотека используется только одним приложением, лучше сделать ее обычной, статической. Конечно, если входящие в ее состав функции будут использоваться только в одной программе, можно просто вставить в нее соответствующий файл с исходным текстом.
Чаще всего проект подключается к DLL статически, или неявно, на этапе компоновки. Загрузкой DLL при выполнении программы управляет операционная система. Однако, DLL можно загрузить и явно, или динамически, в ходе работы приложения.
Слайд 70

Существует два способа использования DLL-библиотек: неявное (implicit linking) и явное (explicit

Существует два способа использования DLL-библиотек: неявное (implicit linking) и явное (explicit

linking) связывание.

Неявное связывание
Неявное связывание (Implicit linking) — самый распространенный в настоящее время способ загрузки DLL-библиотек. Суть его заключается в том, что компоновщик при построении исполняемого exe- файла не включает код функций в тело про-граммы, а создает раздел импорта, где перечисляются символические имена функций и переменных для каждой из DLL-библиотек. Для этого к проекту необходимо подключить соответствующий lib файл. При запуске программы загрузчик операционной системы анализирует раздел импорта, загружает все необходимые DLL-библиотеки и, что важно, проецирует их на адресное пространство загружаемого приложения. Причем, если в загружаемой DLL-библиотеке существует свой раздел импорта, то загружаются и те dll-файлы, которые там указаны. Однако если библиотека один раз уже загружена, то второй раз она не загружается, а строится ссылка на уже существующий экземпляр.

Поиск DLL-библиотек осуществляется по стандартной схеме:
1. В папке, откуда запущено приложение.
2. В текущей папке.
3. В системной папке Windows\system32. 4. В папке Windows.
5. В папках, которые перечислены в переменной окружения PATH.
Если библиотека не найдена, загрузка приложения прекращается и выводится сообщение об ошибке.

Слайд 71

DLL общего использования Созданная нами DLL-библиотека работает с программами, написанными на

DLL общего использования

Созданная нами DLL-библиотека работает с программами, написанными на языке

С++. Если же попытаться использовать ее в программе, написанной на другом языке программирования, мы выясним, что в ней отсутствует функция с именем Triangle. Но имеется функция ? Triangle@@YGHPAUHDC__@@PAUtagPOINT@@@Z.
Дело в том, что по соглашению языка С++ функция идентифицируется не только именем, но и типами формальных параметров, что называется сигнатурой функции. Нетрудно сообразить, что именно эта особенность С++ позволяет определять несколько функций с одним именем, но с разным числом и типом параметров.

В нашей ситуации это является скорее помехой, поскольку вряд ли кому понравит-ся строить такие специфические имена функций.
Однако когда приложение создается в С++, то имя так и строится, поэтому проблем с поиском функций не возникает. Другое дело, если приложение пишется на дру-гом языке, который "ничего не знает" о соглашениях С++.
Одним из выходов в данной ситуации является использование спецификатора ком-поновки для классического языка C, где искажения имени функции не происходит:
extern "язык" прототип функции
Такая конструкция позволяет строить обращение к функции в соответствии со стандартом выбранного языка. Например, в нашем случае функцию можно было бы описать так:
extern "C" __declspec(dllexport) BOOL Triangle(HDC, POINT*);
ПРИМЕЧАНИЕ
К сожалению, имеющиеся в настоящее время компиляторы фирмы Microsoft поддер-живают спецификатор компоновки только для языка С.
Обратите внимание, что в этом случае функция Triangle() использует стандарт-ный для классического С порядок передачи параметров. Если необходимо создать библиотеку функций обратного вызова CALLBACK, необходимо использовать иной подход.
Более приемлемый путь решения данной задачи заключается в использовании def-файла (файла определений с расширением def — от англ. definition). Его можно до-бавить к проекту в меню Project | Add New Item… | Code | Module-Definition File (.def)

Слайд 72

Явная загрузка DLL Неявное связывание, несмотря на свою очевидную простоту, имеет

Явная загрузка DLL

Неявное связывание, несмотря на свою очевидную простоту, имеет и

определенные недостатки. Основным из них является одновременная (с приложением) загрузка и последующее удаление из памяти всех DLL-библиотек, независимо от того, что большая часть из них может и не понадобиться. Однако имеется возможность во время работы приложения загружать только необходимые DLL, освобождая занимаемую ими память, когда потребность в них отпала. Такой способ называют явным связыванием (explicit linking).

Каждое приложение имеет свое адресное пространство, и чтобы получить доступ к функциям и ресурсам, размещенным в DLL-библиотеке, нужно спроецировать библиотеку на адресное пространство приложения. Это можно сделать функцией LoadLibrary():
HMODULE WINAPI LoadLibraryW(LPCWSTR lpLibFileName); аргументом которой является имя DLL-библиотеки.
Функция возвращает дескриптор спроецированного в память dll-файла.
HMODULE— тип возвращаемого значения, это просто другое обозначение дескриптора приложения HINSTANCE.
Функция FreeLibrary() выгружает DLL-библиотеку из памяти:
BOOL WINAPI FreeLibrary(HMODULE hLibModule);
Эта функция принимает дескриптор, полученный при загрузке DLL, и возвращает TRUE при успешном завершении.

Слайд 73

Загрузка ресурсов из DLL Помимо функций из DLL-библиотеки можно загрузить и

Загрузка ресурсов из DLL

Помимо функций из DLL-библиотеки можно загрузить и ресурсы.

Для примера создадим простенькую DLL, содержащую в ресурсе одну иконку, и рассмотрим два способа ее извлечения при явном и неявном связывании.
Создадим проект DLL-библиотеки и импортируем туда иконку IDI_ICON1.

Библиотека динамической компоновки, содержащая ресурсы
#include "stdafx.h" #include "resource.h"
__declspec(dllexport) HICON hIcon;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hIcon = LoadIcon(hModule, MAKEINTRESOURCE(IDI_ICON1));
break;
case DLL_PROCESS_DETACH: DestroyIcon(hIcon); break;
}
return TRUE;
}

Слайд 74

Программный код библиотеки не содержит ни одной функции, а только описание

Программный код библиотеки не содержит ни одной функции, а только описание

глобальной переменной hIcon, объявленной как "экспортируемая":
__declspec(dllexport) HICON hIcon;
Функция DllMain(), которую называют функцией входа/выхода, вызывается операционной системой при загрузке и выгрузке DLL-библиотеки и имеет три параметра:
HModule— дескриптор библиотеки, присваивается при загрузке; ul_reason_for_call— код уведомления;
lpReserved — зарезервировано для дальнейшего применения.
Код уведомления ul_reason_for_call может принимать одно из четырех значений: DLL_PROCESS_ATTACH— при создании нового процесса; DLL_PROCESS_DETACH— при завершении процесса;
DLL_THREAD_ATTACH— при создании нового потока; DLL_THREAD_DETACH— при завершении потока.

Иконку можно загрузить из ресурса библиотеки функцией LoadIcon():
hIcon = LoadIcon(hModule, MAKEINTRESOURCE(IDI_ICON1));
Мы сохраняем в глобальной переменной дескриптор иконки, чтобы при выгрузке библиотеки из памяти по уведомлению DLL_PROCESS_DETACHосвободить память:
DestroyIcon(hIcon);
Поскольку потоков создавать не планируется, то уведомления DLL_THREAD_ATTACH и DLL_THREAD_DETACHобрабатывать не будем.

Слайд 75

Два способа загрузки иконки: 1. Создадим проект демонстрационной задачи. В папку

Два способа загрузки иконки:
1. Создадим проект демонстрационной задачи. В папку этого

проекта скопируем созданные файлы библиотеки DllIcon.dllи DllIcon.lib.
В свойствах проекта добавим имя библиотеки DllIcon.lib. На глобальном уровне опишем импортируемую переменную:
__declspec(dllimport) HICON hIcon;
а в сообщении WM_CREATE переопределим малую иконку класса окна:
SetClassLong(hWnd, GCL_HICONSM, (LONG)hIcon);
Поскольку окно прорисовывается после обработки этого сообщения, мы увидим в заголовке окна новую пиктограмму приложения.
2. Для явной загрузки библиотеки создадим новый проект, нам понадобится лишь dll-файл созданной библиотеки, подключать lib-файл не нужно. В сообщении WM_CREATEнеобходимо получить дескриптор библиотеки:
hDll = LoadLibrary(_T("DllIcon"));

передавая ей в качестве параметра имя DLL-файла. Далее, функцией GetProcAddress()находим дескриптор иконки, уже загруженной в библиотеке, передавая ей дескриптор иконки как текстовую строку.
hIcon = *((HICON*)GetProcAddress(hDll, "hIcon")); Переменная hIconописана как HICON.
После этого мы можем, как и в предыдущем случае, изменить малую иконку класса окна:
SetClassLong(hWnd, GCL_HICONSM, (LONG)hIcon);
Результат работы этого варианта программы будет идентичен предыдущему. lib-файл в проекте нам не нужен, но нужно иметь в виду, что DLL-библиотека должна быть создана с использованием def-файла:
EXPORTS hIcon

Слайд 76

DLL, содержащие только ресурсы Можно использовать DLL-библиотеку, как контейнер для хранения

DLL, содержащие только ресурсы

Можно использовать DLL-библиотеку, как контейнер для хранения ресурсов,

на-пример: курсоров, иконок и пр. В этом случае головная функция DllMain() ничего не делает и будет выглядеть так:
BOOL APIENTRY DllMain( HMODULE, DWORD, LPVOID)
{
return TRUE;
}

#define IDI_ICON1 101

Если создать такую библиотеку, то обработчик сообщения WM_CREATEмог бы выглядеть так:
HMODULE hDll;
HICON hIcon; . . .
case WM_CREATE:
hDll = LoadLibrary(_T("DllIcon"));
hIcon = LoadIcon(hDll, MAKEINTRESOURCE(IDI_ICON1)); SetClassLong(hWnd, GCL_HICONSM, (LONG)hIcon); break;

Слайд 77

Вопросы к главе 1. В чем отличие библиотек динамической компоновки от

Вопросы к главе
1. В чем отличие библиотек динамической компоновки от статических

библиотек? 2. Какие действия выполняет функция DllMain(), коды уведомлений?
3. Объявление экспортируемых переменных и функций. Проблема "искажения" имен, спецификатор компоновки extern "C" и def-файл.
4. Явное и неявное связывание DLL-библиотек. 5. Пути поиска dll-файла.
6. Формат функций LoadLibrary(), GetProcAddress(), FreeLibrary(). 7. Как найти адрес функции и переменной в DLL-библиотеке?
8. Как создать DLL-библиотеку для хранения ресурсов?

Задания для самостоятельной работы
1. Создайте DLL-библиотеку UserString для работы с С-строкой, включив в нее аналоги стандартных функций: strlen(), strcpy(), strcat(), strrev()…
2. Постройте демонстрационную задачу для использования созданной библиотеки при неявном и явном связывании.
3. Создайте библиотеку, содержащую набор ресурсов: иконку, курсор, растровое изображение. Постройте демонстрационную задачу, использующую ресурсы этой DLL-библиотеки.
4. Создайте DLL-библиотеку с галереей рисунков одинакового размера. В число экспортируемых переменных включите название галереи и количество изображений. Окно создаваемого приложения заполните этими рисунками.
5. При помощи утилиты dumpbin просмотрите разделы экспорта и импорта созданных библиотек.

Слайд 78

Вопросы, жалобы, предложения? Подготовил к.т.н. Павлович А.А. Спасибо за внимание!

Вопросы, жалобы, предложения?

Подготовил
к.т.н. Павлович А.А.

Спасибо за внимание!