- •История 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




Функция DllMain и стандартная библиотека С
Вероятно, что при написании DLL Вам понадобится поддержка со стороны стартового кода из стандартной библиотеки С.
Например, в DLL есть глобальная переменная — экземпляр какого-то класса C++. Прежде чем DLL сможет безопасно ее использовать, для переменной нужно вызвать ее конструктор, а это работа для стартового кода.
При сборке DLL компоновщик встраивает в исполняемый файл адрес DLL-функции входа/выхода. Вы задаете этот адрес компоновщику ключом /ENTRY. Если у Вас компоновщик фирмы Microsoft и Вы указали ключ /DLL, компоновщик считает (по умолчанию), что входная функция называется _DllMainCRTStartup. Эта функция содержится в файле стандартной библиотеки и при компоновке статически связывается с Вашей DLL — даже если Вы используете DLL-версию стандартной библиотеки С.
Когда Ваша DLL проецируется на адресное пространство процесса, система на самом деле вызывает именно _DllMainCRTStartup, а не Вашу функцию DllMain.
•Получив уведомление DLL_PROCESS_ATTACH, функция _DllMainCRTStartup
инициализирует стандартную библиотеку и конструирует все глобальные и статические С++ объекты. Закончив, _DllMainCRTStartup вызывает Вашу функцию DllMain.
Как только DLL получает уведомление DLL_PROCESS_DETACH, система вновь вызывает _DllMainCRTStartup, которая теперь обращается к Вашей функции DllMain, и, когда та вернет управление, _DllMainCRTStartup вызовет деструкторы для всех глобальных и статических С++ объектов. Функция _DllMainCRTStartup отвечает и за любую дополнительную инициализацию и очистку, связанную со стандартной библиотекой С (после того, как поступят уведомления DLL_THREAD_ATTACH и DLL_THREAD_DETACH).
Как говорилось выше, реализация в коде Вашей DLL-библиотеки функции DllMain
не обязательно. И если у Вас нет этой функции, стандартная библиотека С использует свою реализацию DllMain:
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID flmpLoad) { return(TRUE);
}
При сборке DLL компоновщик, не найдя в Ваших OBJ-файлах функции DllMain, подключает DllMain из стандартной библиотеки.


Функция LibEntry
До тех пор, пока ни одно из приложений не затребовало функцию из DLLбиблиотеки, сама библиотека находится в файле на диске. В оперативной памяти ее нет. Однако как только приложение затребует функцию из DLL-библиотеки или загрузит
библиотеку в память явным образом, начнется процесс инициализации библиотеки.
В процессе инициализации после загрузки библиотеки в память Windows вызывает функцию LibEntry , которая должна быть определена в каждой DLL-библиотеке. Можно считать, что функция LibEntry является точкой входа библиотеки, получающей управление при загрузке библиотеки в память.
•Задачей функции LibEntry является инициализация локальной области памяти, если она определена для DLL-библиотеки.
(!!!)Перечислим и опишем параметры, передаваемые функции LibEntry при загрузке DLL-
библиотеки в память.
Регистры
DS
DI
CX
ES:SI

Описание
Селектор, указывающий на сегмент данных DLL-библиотеки. Отметим, что хотя сразу после загрузки DLL-библиотека имеет собственный сегмент данных, в нем не определена область локальных данных. Для определения области локальных данных функция LibEntry должна вызвать функцию LocalInit
Идентификатор DLL-библиотеки, присвоенный ей операционной системой Windows после загрузки. По своему назначению аналогичен идентификатору приложения hInstance, передаваемому обычному приложению через соответствующий параметр функции WinMain. Идентификатор DLL-библиотеки используется функциями библиотеки при создании таких, например, объектов, как окна (если окно создается функцией, расположенной в DLLбиблиотеке, при его создании следует использовать не идентификатор приложения hInstance, вызвавшего функцию, а идентификатор DLL-библиотеки)
Требуемый размер локальной области данных, указанный в операторе HEAPSIZE файла определения модуля DLL-библиотеки. При вызове функции инициализации локальной области памяти LocalInit в качестве значения параметра uStartAddr следует использовать нуль, а в качестве значения параметра uEndAddr - содержимое регистра CX
Дальний указатель на строку параметров, которая может быть указана при явной загрузке DLL-библиотеки (позже мы рассмотрим различные способы загрузки DLL-библиотеки). Обычно этот параметр не используется
Не надо определять функцию LibEntry самостоятельно, так как при создании файла DLL-библиотеки редактор связей, входящий в систему разработки, включит уже имеющийся в стандартной библиотеке модуль.
•Этот стандартный модуль выполняет всю необходимую работу по инициализации локальной области памяти DLL-библиотеки (с помощью функции LocalInit) и затем вызывает функцию LibMain, которая будет описана в следующем разделе.


Функция LibMain
Функция LibMain должна присутствовать в каждой стандартной DLL-библиотеке. Эту функцию вам надо определить самостоятельно, причем вы можете воспользоваться языком программирования С.
По своему назначению функция LibMain напоминает функцию WinMain обычного приложения Windows. Функция LibMain получает управление при загрузке DLL-
библиотеки в память. Она имеет параметры, которые можно использовать для инициализации библиотеки.
Приведем прототип функции LibMain :
int FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSegment,
WORD wHeapSize, LPSTR lpszCmdLine);
Параметр hInstance при вызове функции содержит идентификатор DLL-библиотеки. Через параметр wDataSegment передается селектор, соответствующий сегменту данных DLLбиблиотеки. Значение параметра wDataSegment соответствует содержимому регистра DS перед вызовом функции LibEntry. Параметр wHeapSize содержит размер в байтах локальной области данных DLL-библиотеки. Если DLL-библиотека не имеет сегмента данных, в этом параметре находится нулевое значение. Через параметр lpszCmdLine передается указатель на командную строку, которую можно передать DLL-библиотеке при ее явной загрузке в память.
Если инициализация DLL-библиотеки выполнена успешно, функция LibMain
должна возвратить ненулевое значение. Если в процессе инициализации произошла ошибка, следует возвратить нуль. В этом случае функция LibEntry также возвратит нуль. Это приведет к тому, что Windows выгрузит библиотеку из памяти.
Если функция LibMain заказывает блоки памяти из глобальной области данных, следует использовать флаг GMEM_SHARE. Такие блоки памяти будут принадлежать создавшей их DLL-библиотеке. Освобождение заказанных глобальных блоков памяти можно выполнить в функции WEP, получающей управление при выгрузке DLL-библиотеки из памяти.
Приведем пример простейшего варианта функции LibMain:
int FAR PASCAL LibMain(HINSTANCE hInstance, WORD wDataSegment, WORD wHeapSize, LPSTR lpszCmdLine)
{
if(wHeapSize != 0) UnlockData(0); return 1;
}
•Эта функция проверяет размер локальной области данных, и если эта область данных существует, она расфиксируется при помощи макрокоманды UnlockData. После этого возвращается признак успешной инициализации.




Функция WEP
Windows перед выгрузкой вызывает функцию WEP . Эта функция, как и функция
LibMain, вызывается только один раз. Она может быть использована для уничтожения структур данных и освобождения блоков памяти, заказанных при инициализации DLLбиблиотеки.
Приведем прототип функции WEP (при использовании системы разработки Borland Turbo C++ for Windows):
int FAR PASCAL WEP(int bSystemExit);
Параметр bSystemExit может принимать значения WEP_FREE_DLL и WEP_SYSTEM_EXIT
. Этот параметр указывает причину выгрузки DLL-библиотеки из памяти. Если же параметр имеет значение WEP_SYSTEM_EXIT, выгрузка библиотеки происходит из-за завершения работы операционной системы Windows.
•Функция WEP должна всегда возвращать значение 1.
Функция WEP добавляется в DLL-библиотеку транслятором. Вы, однако, можете определить собственную функцию WEP, если перед выгрузкой DLL-библиотеки требуется освободить заказанные ранее блоки памяти.
Приведем пример простейшей функции WEP:
int FAR PASCAL WEP(int bSystemExit)
{
return 1;
}
