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

свои операции. Чтобы лучше разобраться в этом механизме, вернемся к примеру с
чтением и обработкой файловых данных. Допустим, один поток отвечает за считывание данных из файла в буфер. После того как данные считаны, Вы запускаете девять других потоков. Каждый из них обрабатывает данные по-своему. Предположим, в файле находится документ, созданный в каком-нибудь текстовом процессоре. Тогда пусть первый поток подсчитывает символы, второй — слова, третий — страницы, четвертый, скажем, проверяет орфографию, пятый печатает документ и т. п. Отметьте — и это крайне важно, — что у всех потоков есть общая черта: ни один из них ничего не записывает в файл. Данные для них — ресурс, открытый только для чтения. Ясно, что при возникновении события все ожидающие его потоки должны возобновить свое выполнение. Вот Вам и один из случаев применения событий со сбросом вручную.
Когда объект «событие со сбросом вручную» переходит в свободное состояние, система разрешает исполнение всех ожидавших его потоков. Поток переводит такой объект «событие» в свободное состояние вызовом SetEvent
BOOL SetEvent(HANDLE hEvent)
Эта функция принимает описатель объекта «событие» и меняет состояние объекта на свободное. Если операция прошла успешно, функция возвращает TRUE. После перевода объекта в свободное состояние он пребывает в нем, пока какой-нибудь поток явным образом (т. е «вручную») не сбросит событие, вызвав:
BOOL ResetEvent(HANDLE hEvent)
Эта функция принимает описатель объекта «событие» и переводит объект в занятое состояние. Если операция прошла успешно, функция возвращает TRUE.
Как поток, считывающий данные из файла, узнает, что пора считывать следующий блок? Известно, что это должно произойти по окончании работы прочих потоков с текущей порцией данных. Значит, и эти потоки должны как-то сигнализировать об окончании своих операций. Лучше всего создать в каждом из них собственный объект «событие», а описатели этих объектов поместить в массив; тогда поток, отвечающий за чтение данных, сможет воспользоваться функцией WaitForMultipleObjects и сообщить ей, что он собирается ждать освобождения всех девяти объектов.
Поскольку на практике нередко после вызова SetEvent объект «событие» освобождается и тут же следует вызов ResetEvent, в Win32 предусмотрена дополнительная функция, способная самостоятельно выполнять все три операции:
BOOL PulseEvent(HANDLE hEvent),
После возврата управления функцией PulseEvent событие остается в занятом состоянии. Если функция выполнена успешно, возвращается TRUE.
Ожидаемые таймеры

Это объекты ядра, самостоятельно переходящие в свободное состояние в определенное время и/или через регулярные промежутки времени. Чтобы создать ожидаемый таймер, достаточно вызвать функцию CreateWaitable Timer.
HANDLE CreateWaitableTimer(LPSECURITY_ATTRIBUTES Ipsa, BOOL
DManualReset, LPCTSTR IpszTimerName)
Разумеется, любой процесс может получить свой («процессо-зависимый») описатель существующего объекта «ожидаемый таймер», вызвав OpenWaitableTimer.
HANDLE OpenWaitableTimer(DWORD dwDesiredAccess, |
BOOL |
blnheritHandle, LPCTSTR IpszTimerName); |
|
Получив описатель ожидаемого таймера, процесс может настроить этот таймер вызовом:
BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER «pDueTime, LONG IPeriod,
PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID IpArgToCompletionRoutine, BOOL fResume);
Таймер переходит в сигнальное состояние, когда истекает его «таймаут». Отменить «тиканье таймера» можно функцией CancelWaitableTimer
BOOL CancelWaitableTimer(HANDLE hTimer)
Эта очень простая функция принимает описатель таймера и отменяет его, после чего тот уже никогда не сработает, — если только Вы не переустановите его повторным вызовом SetWaitableTimer. Кстати, если Вам понадобится перенастроить таймер, то вызывать CancelWaitableTimer перед повторным обращением к SetWaitableTimer не требуется; каждый вызов SetWaitableTimer автоматически отменяет предыдущие настройки перед установкой новых.
Примечательно, что можно указать callback-функцию при установке таймера. Она будет выполняться, когда срабатывает таймер.
Любой Windows-программист непременно поинтересуется различиями ожидаемых таймеров и таймеров User (устанавливаемых через функцию SetTimer). Так вот, главное отличие в том, что ожидаемые таймеры реализованы в ядре, а значит,

не столь тяжеловесны, как таймеры User. Кроме того, это означает, что ожидаемые таймеры — объекты защищенные.
Сводная таблица объектов, используемых для синхронизации потоков
В следующей таблице 8 приведены краткие сведения о различных объектах ядра применительно к синхронизации потоков.
Объект |
Находится в занятом |
Переходит в свободное |
Побочный эффект |
|
состоянии, когда |
состояние, когда |
успешного |
|
|
|
ожидания |
Процесс |
процесс еще активен поток |
процесс завершается (ExitProcess, |
Нет |
Поток |
еще активен |
TerminateProcess) |
Нет |
|
|
поток завершается (ExitThread, |
|
|
|
TerminateThread) |
|
Объект |
Находится в занятом |
Переходит в свободное |
Побочный эффект |
|
состоянии, когда: |
состояние, когда: |
успешного |
|
|
|
ожидания |
Задание |
время, выделенное заданию, |
время, выделенное заданию, |
Нет |
|
еще не истекло |
истекло |
|
Файл |
выдан запрос на ввод-вывод |
завершено выполнение запроса |
Нет |
|
|
на ввод-вывод |
|
Консольный |
ввода нет |
ввод есть |
Нет |
ВВОД |
|
|
|
Уведомление об |
в файловой системе нет |
файловая система обнаруживает |
Сбрасывается в |
изменении файла |
изменений |
изменения |
исходное |
|
|
|
состояние |
Событие с |
вызывается ResetEvent, |
вызывается SetEvent или |
Сбрасывается в |
автосбросом |
PulseEvent или ожидание |
PulseEvent |
исходное |
|
успешно завершилось |
|
состояние |
Событие со |
вызывается ResetEvent или |
вызывается SetEvent или |
Нет |
сбросом вручную |
PulseEvent |
PulseEvent |
|
Ожидаемый |
вызывается CancelWaitable- |
наступает время срабатывания |
Сбрасывается в |
таймер с |
Тiтеr или ожидание успешно |
(SetWaitableTimer) |
исходное |
автосбросом |
завершилось |
|
состояние |
Ожидаемый |
вызывается |
наступает время срабатывания |
Нет |
таймер со сбросом |
CancelWaitableTimer |
(SetWaitableTimef) |
|
вручную |
|
|
|
Семафор |
ожидание успешно |
счетчик > 0 (ReleaseSemaphore) |
Счетчик |
|
завершилось |
|
уменьшается на 1 |
Мьютекс |
ожидание успешно |
поток освобождает мьютекс |
Передается потоку |
|
завершилось |
(ReleaseMutex) |
во владение |
Критическая |
ожидание успешно |
поток освобождает критическую |
Передается потоку |
секция |
завершилось ( |
секцию (LeaveCriticalSection) |
во владение |
(пользовательского |
(Try)EnterCriticalSection) |
|
|
режима) |
|
|
|