- •История Windows
- •Windows 1.0
- •Windows 1.3
- •Windows 2.0
- •Windows 3.0
- •Windows 3.1
- •Windows for Workgroups версии 3.11
- •Windows NT
- •Windows 95
- •Windows NT Workstation 4.0 и Windows NT Server 4.0
- •Windows NT 4.0 Server Enterprise Edition
- •Windows 98
- •Windows 98 Second Edition (SE)
- •Windows 2000
- •Windows 98 Millenium Edition (ME)
- •Windows XP
- •Общая архитектура WINDOWS приложения.
- •Каркас приложения
- •Регистрация класса окна
- •Создание окна.
- •Отображение окна.
- •Цикл обработки очереди сообщений.
- •WndProc
- •Обработка сообщений типового приложения.
- •Контрольные вопросы
- •Сообщения
- •Типы сообщений
- •Обработка клавиатурных сообщений
- •Обработка сообщений от мыши
- •Сообщения таймера
- •Контрольные вопросы
- •Организация ввода
- •Разупорядоченный ввод
- •Разделение потоками виртуальных очередей ввода
- •Локальное состояние ввода
- •Ввод с клавиатуры и фокус
- •Управление курсором мыши
- •Контрольные вопросы
- •Окна
- •Окна Windows
- •Иерархия окон
- •Оконная процедура, стандартные оконные процедуры
- •Стиль класса окна
- •Стили окон, окна основных стилей
- •Перекрывающиеся окна
- •Временные окна
- •Дочерние окна
- •Сообщения управления окнами
- •Окна с полосами прокрутки
- •Системные метрики
- •Определение размера окна
- •Определение расположения окна
- •Контрольные вопросы
- •Графический интерфейс устройств(GDI).
- •Создание (получение) контекста устройств.
- •Сохранение контекста устройства.
- •Прямые (отрезки) и кривые
- •Закрашенные области
- •Битовые шаблоны (растровые шаблоны, растровые образы)
- •Текст и шрифты
- •Режимы масштабирования и преобразования
- •Метафайл
- •Регионы
- •Путь
- •Палитры
- •Контрольные вопросы
- •Объекты ядра
- •Что такое объект ядра
- •Учет пользователей объектов ядра
- •Защита
- •Таблица описателей объектов ядра
- •Создание объекта ядра
- •Закрытие объекта ядра
- •Синхронизация объектов
- •Именованные объекты
- •Дублирование описателей объектов
- •Изменение флагов описателя
- •Синхронизация потоков
- •Критическая секция
- •Мьютексы
- •Семафоры
- •События
- •Ожидаемые таймеры
- •Контрольные вопросы
- •Ресурсы Windows приложения
- •Файлы ресурсов приложения
- •Значки (пиктограммы)
- •Курсоры
- •Битовые образы
- •Символьные строки
- •Ресурсы, определяемые пользователем
- •Таблица акселераторов
- •Меню
- •Диалоговые окна
- •Контрольные вопросы
- •Элементы управления
- •Дочерние окна управления
- •Создание дочерних окон
- •Сообщения родительского окна дочерним окнам
- •Дочерние окна и фокус ввода
- •Дочерние окна управления и цвет
- •Сообщения дочерних окон родительскому окну
- •Кнопки различных стилей (класс BUTTON)
- •Нажимаемые кнопки
- •Флажки-переключатели
- •Переключатели
- •Окна групп
- •Кнопки, определяемые пользователем
- •Статические поля (класс static)
- •Текстовые редакторы (класс edit)
- •Списки разных стилей (класс listbox)
- •Комбинированные списки (класс combobox)
- •Полосы прокрутки (класс scrollbar)
- •Контрольные вопросы
- •Расширенные элементы управления
- •Основы общих элементов управления
- •Инициализация библиотеки элементов общего пользования
- •Создание элементов управления общего пользования
- •Посылка сообщений общим элементам управления
- •Уведомляющие сообщения от общих элементов управления
- •Контрольные вопросы
- •Стандартные диалоговые окна.
- •Окна сообщений
- •Диалоговые окна общего пользования
- •Контрольные вопросы
- •Динамически подключаемые библиотеки
- •Создание DLL
- •Проецирование DLL на адресное пространство процесса
- •Функция входа/выхода
- •Функция DllMain и стандартная библиотека С
- •Функция LibEntry
- •Функция LibMain
- •Функция WEP
- •Экспорт функций и переменных из DLL
- •Импорт функций и переменных из DLL
- •Заголовочный файл DLL
- •Разделы в ЕХЕ- и DLL-файлах
- •Контрольные вопросы
- •Файлы, проецируемые в память
- •Контрольные вопросы
- •Классы, определяющие архитектуру приложения
- •Классы приложения и поддержки потоков
- •Классы приложения и потоков
- •Классы фреймов окон
- •Получение информации о приложении
- •Соглашения об именах MFC
- •Включаемые файлы
- •Функция WinMain
- •Класс CWinApp
- •Класс CWnd
- •Класс CFrameWnd
- •Создание главного окна SDI-приложения
- •Примечание
- •Создание главного окна SDI-приложения
- •Создание дочерних окон
- •Ограничение размеров окна
- •Ограничение доступа к окну
- •Создание многодокументных приложений
- •Класс CMDIChildWnd
- •MDI — пример приложения
- •Категории сообщений
- •Карта сообщений
- •Компоненты карты сообщений
- •Класс CCmdTarget
- •Стандартный маршрут команды
- •Команды обновления и класс CCmdlll
- •Функции для работы с сообщениями
- •Основные положения
- •Класс CDocTemplate
- •Класс CSingleDocTemplate
- •Роль фреймов в архитектуре "документ/представление"
- •Документ и его представления
- •Документы
- •Класс CDocument
- •Класс CArchive
- •Представления
- •Класс CView
- •Панели элементов управления
- •Класс CStatusBar
- •Класс CStatusBarCtrl
- •Класс CDialogBar
- •ControlBars — пример приложения
- •НЕКОТОРЫЕ КЛАССЫ MFC
- •Класс CObject - основной класс MFC
- •Конструкторы класса
- •Оператор присваивания
- •Диагностика
- •Проверка целостности объектов класса
- •Получение дампа объекта класса
- •Сохранение и восстановление состояния объекта
- •Метод IsSerializable
- •Виртуальный метод Serialize
- •Информация о классе
- •Виртуальный метод GetRuntimeClass
- •Метод IsKindOf
- •Класс CPoint - точка на плоскости
- •Класс CSize - относительные координаты
- •Класс CString - текстовые строки
- •Конструктор класса
- •Коллекции
- •Массивы - шаблон CArray
- •Списки - шаблон CList
- •Словари - шаблон CMap
- •Класс CTime - дата и время
- •Файловая система - класс CFile
- •Открытие и создание файлов
- •Идентификатор открытого файла
- •Закрытие файлов
- •Чтение и запись файлов
- •Метод Flush
- •Операции с файлами
- •Блокировка
- •Позиционирование
- •Характеристики открытого файла
- •Файловая система - классы CMemFile и CStdioFile
- •Модификация класса CMemFile
- •Файловая система - класс CStdioFile
- •Запись и восстановление объектов
- •Запись в архивный файл
- •Чтение из архивного файла
- •Исключения - класс CException
- •Класс CException
- •Класс CMemoryException
- •Класс CFileException
- •Приложение Except
- •Класс CArchiveException
- •Класс CNotSupportedException
- •Класс CResourceException
- •Класс CUserException


Экспорт функций и переменных из DLL
Создавая DLL, Вы создаете набор функций и хотите, чтобы они были доступны другим ЕХЕ - или DLL-модулям. Если DLL-функция доступна для вызова из других программ, то говорят, что это экспортируемая (exported) функция.
•Кроме функций, Win32 позволяет экспортировать и глобальные переменные.
Вот как экспортировать из DLL функцию Add и глобальную целочисленную переменную g_nUsageCount
__declspec(dllexport) |
int |
Add(int |
nLeft, |
int |
nRight) |
{ |
return(nLeft + nRight); |
|
|
|
|
|
|
} |
|
|
|
|
|
|
__declspec(dllexport) |
int g_nUsageCount = 0; |
|
|
|
|
|
Конструкцию __dedspec(dllexport) компилятор C/C++ распознает как новое ключевое слово. Компилируя функцию Add и g_nUsageCount, он встраивает в конечный OBJ-файл дополнительную информацию, необходимую компоновщику при сборке DLL из OBJ-файлов.
Обнаружив такую информацию, компоновщик создает LIB-файл со списком иден-
тификаторов, экспортируемых из DLL. Этот LIB-файл нужен при сборке любого ЕХЕ - файла, вызывающего функции из данной DLL. Кроме того, компоновщик вставляет в
конечный файл DLL и таблицу экспортируемых идентификаторов (exported symbols).
Каждый элемент в этой таблице содержит имя экспортируемой функции или переменной, а также адрес этой функции или переменной внутри DLL-файла. Все списки сортируются по алфавиту.




Импорт функций и переменных из DLL
Чтобы ЕХЕ - файл мог вызывать функции или получать доступ к переменным из DLL, нужно сообщить компилятору, что они находятся именно в DLL. Следующий фрагмент кода показывает, как импортировать функцию Add и переменную g_nUsageCount,
экспортируемые DLL-модулем:
_declspec(dllimport) int Add(int nLeft, int nRight); _declspec(dlliinport) int g_nUsageCount;
Как и _dedspec(dllexport), _dedspec(dllimport) — новое ключевое слово, распознаваемое компилятором C/C++. Оно сообщает компилятору, что функция Add и переменная g_nUsageCount находятся в DLL, доступ к которой ЕХЕ - файл должен получить при загрузке.
•Это заставит компилятор сгенерировать специальный код для импортируемых идентификаторов (imported symbols).
•Еще компилятор встроит специальную информацию в конечный объектный файл.
Она используется при компоновке ЕХЕ - файла, подсказывая компоновщику, какие функции следует искать в LIB-файлах. Собирая ЕХЕ - файл, компоновщик отыскивает импортируемые функции и переменные. Затем, определив, какой LIB-файл содержит эти идентификаторы, добавляет в таблицу импорта новые элементы. Каждый элемент содержит имя соответствующего DLL-файла, а также имя самого идентификатора. Таблица импорта вносится в конечный ЕХЕ - файл при его записи на жесткий диск.
При запуске ЕХЕ - файла загрузчик операционной системы просматривает таблицу импорта, содержащуюся в этом файле, и пытается найти и спроецировать на адресное пространство нового процесса все необходимые DLL. Затем он сохраняет адреса идентификаторов, используемых ЕХЕ - файлом, в особой таблице.
Импортируя идентификатор, ключевое слово _declspec(dllimport) использовать не обязательно. Вместо него можно взять стандартное ключевое слово extern. Но компилятор генерирует более эффективный код, если ему заранее известно, что идентификатор будет импортирован из DLL.
Поток получает адрес экспортируемой из DLL функции или переменной вызовом
GetProcAddress:
FARPROC GetProcAddress(HINSTANCE hinstDll, LPCSTR IpszProc);
•Параметр hinstDll— описатель DLL. Это значение можно получить с помощью
LoadLibrary или LoadLibraryEx. Параметр IpszProc разрешается указывать в двух формах. Во-первых, как адрес строки с нулевым символом в конце, содержащей
имя интересующей Вас функции:
Ipfn = GetProcAddress(hinstDll, "SomeFuncInDll");
Вторая форма параметра IpszProc позволяет указывать порядковый номер нужной функции:
Ipfn = GetProcAddress(hinstDll, MAKEINTRESOURCE(2));
Здесь подразумевается, что нам известен порядковый номер (2) функции SomeFuncInDll, присвоенный ей в данной DLL.
Оба способа дают адрес содержащейся в DLL функции SomeFuncInDll. Если функция не найдена, GetProcAddress возвращает NULL. Однако и тот, и другой способ не без недостатков.
•Первый медленнее, так как системе приходится проводить поиск и сравнивать строки.
•Во втором, если Вы передаете порядковый номер, не присвоенный ни одной из экспортируемых функций, GetProcAddress может вернуть значение, отличное от NULL. (Это относится и к 16-разрядной Windows.)
Витоге Ваша программа, ничего не “подозревая”, получит неправильный адрес.


Заголовочный файл DLL
При создании DLL создается и ее заголовочный файл, содержащий прототипы всех экспортируемых из DLL функций и переменных. Он понадобится Вам при компиляции ЕХЕ-файлов. Часто его включают и при компиляции исходных файлов самой DLL.
|
Чтобы один и тот же заголовочный файл можно было использовать при компиляции |
|||||||
исходных файлов как ЕХЕ, так и DLL-модулей, он должен выглядеть так: |
|
|
||||||
// |
MYLIBAPI |
определена |
в |
файле |
реализаций MyLib.C как |
_declspec(dllexport) |
||
// |
Поэтому |
при включении |
заголовочного файла в MyLib.C, |
функции |
будут |
|||
// экспортироваться, а не импортироваться. |
|
|
|
|||||
#ifndef |
MYLIBAPI |
|
|
|
|
|
||
#define |
MYLIBAPI _declspec(dllimport) |
|
|
|
||||
|
#endif |
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////// |
|
|
||||||
MYLIBAPI |
|
int |
Add(int |
nLeft, |
int |
riRight); |
||
MYLIBAPI int g_nUsageCount; |
|
|
|
|
|
|||
Этот заголовочный файл надо включать в самое начало исходных файлов Вашей DLL следующим образом:
// Мы должны определить MYLIBAPI как _declspec(dllexport) до включения
// файла MyLib.H. Тогда MyLib.H, "увидев", что мы уже определили //MYLIBAPI, не станет (пере)определять ее как _declspec(dlliinport).
#define MYLIBAPI __declspec(dllexport) #include "MyLib.H"
///////////////////////////////////////////////////////////////////
int Add(int nLeft, int nRight) { return(nLeft + nRight);
}
MYLIBAPI int g_nUsageCount;
Поскольку MYLIBAPI определена как _declspec(dllexport) явно, то при компиляции исходного кода Вашей программы компилятор узнает, что функции экспортируются. А
это позволяет не повторять _declspec(dllexport) перед каждой процедурой или переменной.
Заголовочный файл нужно включить в исходный код, импортирующий из DLL идентификаторы. MYLIBAPI будет определена как _declspec(dllimport), и компилятор “поймет”, какие идентификаторы содержатся в DLL.




Совместное использование дaнных несколькими проекциями ЕХЕ или DLL
Как уже известно, система создает отдельные экземпляры любых глобальных и
статических переменных, содержащихся в образе ЕХЕили DLL-файла для каждой его проекции. Иначе говоря, если в ЕХЕ есть глобальная переменная и Вы запускаете 2 или более копии приложения, каждый процесс получает свою копию переменной, т. е. она не разделяется
несколькими экземплярами ЕХЕ.
Например, в Win32 нет простого способа, позволяющего определить, запущено ли несколько копий приложения. А если бы у Вас была переменная, доступная всем копиям приложения, она могла бы отражать число запущенных копий. Тогда при запуске нового экземпляра приложения его поток просто проверил бы значение глобальной переменной (обновленное другой копией приложения) и, будь оно больше 1, сообщил бы пользователю, что запустить можно лишь одну копию, после чего этот экземпляр приложения благополучно бы и завершился.


Разделы в ЕХЕ- и DLL-файлах
Любой образ ЕХЕили DLL-файла состоит из группы разделов (sections). По соглашению имя каждого стандартного раздела начинается с точки.
Например, при компиляции программы исполняемый код помещается в раздел .text, неинициализированные данные — в раздел .bss, а инициализированные — в раздел .data.
С каждым разделом связана комбинация следующих атрибутов:
•READ – разрешает чтение из раздела
•WRITE – разрешает запись в раздел
•EXECUTE – содержимое раздела можно исполнять
•SHARED – раздел доступен нескольким экземплярам приложения
(!!!)Вот некоторые из часто встречающихся разделов:
1. .text – код приложения из DLL
2. .bss – неинициализированные данные
3. .rdata – неизменяемые данные периода выполнения
4. .rsrc - ресурсы
5. .edata – таблица экспортируемых имен
6. .data – инициализированные данные
7. .xdata – таблица для обработки исключений
