- •Содержание
- •Управление памятью: хорошо, плохо и ужасно
- •Сегментированная память
- •Промежуточные решения
- •И, наконец, 32 бита
- •Выделение памяти
- •Библиотечные функции C
- •Фундаментальное выделение памяти в Windows 95
- •Перемещаемая память
- •Удаляемая память
- •Другие функции и флаги
- •Хорошо ли это?
- •Функции работы с "кучей"
- •Файловый ввод/вывод
- •Старый путь
- •Отличия Windows 95
- •Ввод/вывод с использованием файлов, проецируемых в память
- •Режимы многозадачности
- •Многозадачность в DOS
- •Невытесняющая многозадачность
- •Решения, использующие многопоточность
- •Многопоточная архитектура
- •Коллизии, возникающие при использовании потоков
- •Преимущества Windows
- •Новая программа! Усовершенствованная программа! Многопоточная!
- •Многопоточность в Windows 95
- •И снова случайные прямоугольники
- •Задание на конкурсе программистов
- •Решение с использованием многопоточности
- •О пользе использования функции Sleep
- •Синхронизация потоков
- •Критический раздел
- •Объект Mutex
- •Программа BIGJOB1
- •Объект Event
- •Локальная память потока
- •Печать, буферизация и функции печати
- •Контекст принтера
- •Формирование параметров для функции CreateDC
- •Измененная программа DEVCAPS
- •Вызов функции PrinterProperties
- •Проверка возможности работы с битовыми блоками (BitBlt)
- •Программа FORMFEED
- •Печать графики и текста
- •Каркас программы печати
- •Прерывание печати с помощью процедуры Abort
- •Реализация процедуры прерывания
- •Добавление диалогового окна печати
- •Добавление печати к программе POPPAD
- •Обработка кодов ошибок
- •Техника разбиения на полосы
- •Разбиение на полосы
- •Реализация разбиения страницы на полосы
- •Принтер и шрифты
- •Глава 16 Буфер обмена
- •Простое использование буфера обмена
- •Стандартные форматы данных буфера обмена
- •Передача текста в буфер обмена
- •Получение текста из буфера обмена
- •Открытие и закрытие буфера обмена
- •Использование буфера обмена с битовыми образами
- •Метафайл и картина метафайла
- •Более сложное использование буфера обмена
- •Использование нескольких элементов данных
- •Отложенное исполнение
- •Нестандартные форматы данных
- •Соответствующая программа просмотра буфера обмена
- •Цепочка программ просмотра буфера обмена
- •Функции и сообщения программы просмотра буфера обмена
- •Простая программа просмотра буфера обмена
- •Основные концепции
- •Приложение, раздел и элемент
- •Типы диалогов
- •Символьные строки и атомы
- •Программа сервер DDE
- •Программа DDEPOP1
- •Сообщение WM_DDE_INITIATE
- •Оконная процедура ServerProc
- •Функция PostDataMessage программы DDEPOP1
- •Сообщение WM_DDE_ADVISE
- •Обновление элементов данных
- •Сообщение WM_DDE_UNADVISE
- •Сообщение WM_DDE_TERMINATE
- •Программа-клиент DDE
- •Инициирование диалога DDE
- •Сообщение WM_DDE_DATA
- •Сообщение WM_DDE_TERMINATE
- •Управляющая библиотека DDE
- •Концептуальные различия
- •Реализация DDE с помощью DDEML
- •Элементы MDI
- •Windows 95 и MDI
- •Пример программы
- •Три меню
- •Инициализация программы
- •Создание дочерних окон
- •Дополнительная информация об обработке сообщений в главном окне
- •Дочерние окна документов
- •Освобождение захваченных ресурсов
- •Сила оконной процедуры
- •Основы библиотек
- •Библиотека: одно слово, множество значений
- •Пример простой DLL
- •Разделяемая память в DLL
- •Библиотека STRLIB
- •Точка входа/выхода библиотеки
- •Программа STRPROG
- •Работа программы STRPROG
- •Разделение данных между экземплярами программы STRPROG
- •Некоторые ограничения библиотек
- •Динамическое связывание без импорта
- •Библиотеки, содержащие только ресурсы
- •Глава 20 Что такое OLE?
- •Основы OLE
- •Связь с библиотеками OLE
- •Расшифровка кода результата
- •Интерфейсы модели составного объекта (COM-интерфейсы)
- •Услуги интерфейса IUnknown
- •Является ли OLE спецификацией клиент/сервер?
- •Сервер закрытого компонента
- •IMALLOC.DLL
- •Теперь о макросах
- •Услуги, предоставляемые интерфейсом IUnknown
- •Клиент закрытого компонента
- •Сервер открытого компонента
- •Назначение реестра
- •Способы генерации и использования идентификаторов CLSID
- •Компонент фабрика классов
- •Управление временем жизни сервера
- •Клиент открытого компонента
- •Заключение
136
получения данных.) Значение FALSE означает, что клиент хочет получить данные в сообщении
WM_DDE_DATA.
•Полю fAckReq (необходимо подтверждение, acknowledgment requested) присваивается значение, содержащееся в аналогичном поле структуры DDEADVISE. Это очень интересное значение. Значение TRUE извещает сервер о необходимости отправить синхронное сообщение WM_DDE_DATA, где полю fAckReq структуры DDEDATA присвоить значение TRUE. Это означает, что клиенту требуется подтвердить получение сообщения WM_DDE_DATA сообщением WM_DDE_ACK. Значение TRUE не означает, что клиенту требуется от сервера сообщение WM_DDE_ACK; оно означает, что сервер требует от клиента отправить ему сообщение WM_DDE_ACK, когда он позднее отправит клиенту синхронное сообщение WM_DDE_DATA.
•Полю lPopPrev присваивается значение, соответствующее текущему населению штата. ServerProc использует это поле для определения необходимости извещения клиента об изменении численности населения штата.
Процедура ServerProc заканчивает работу со структурой DDEADVISE и освобождает блок памяти, как это описано в документации о сообщении WM_DDE_ADVISE. Теперь ServerProc должна подтвердить получение сообщения WM_DDE_ADVISE путем отправки позитивного синхронного сообщения WM_DDE_ACK. При этом полю fAck структуры DDEACK присваивается значение TRUE. Если вызов функции PostMessage неудачен, то ServerProc удаляет атом.
Если формат данных — не CF_TEXT, или если не удалось подобрать совпадающего имени штата, то ServerProc посылает негативное синхронное сообщение WM_DDE_ACK. В этом случае, если вызов функции PostMessage неудачен, то ServerProc и удаляет атом, и освобождает блок памяти структуры DDEADVISE.
Теоретически, обработка сообщения WM_DDE_ADVISE на этом завершается. Однако, клиент просил, чтобы его известили о любых изменениях элемента данных. Если предположить, что клиенту не известно ни одного значения элемента данных, то необходимо, чтобы ServerProc отправила клиенту синхронное сообщение WM_DDE_DATA.
Это делается с помощью функции PostDataMessage, но при этом третьему параметру присваивается значение поля fDeferUpd структуры POPADVISE, четвертому параметру — значение поля fAckReq структуры POPADVISE, и последнему параметру — значение FALSE (означающее, что синхронное сообщение WM_DDE_DATA послано в ответ на сообщение WM_DDE_ADVISE, а не в ответ на сообщение WM_DDE_REQUEST).
Настало время вернуться к функции PostDataMessage. Обратите внимание на начало функции, если параметру fDeferUpd присваивается значение TRUE, то функция не выделяет память для описателя hDdeData, а просто устанавливает его в NULL.
Если параметр fAckReq равен TRUE, то функция PostDataMessage, после отправки синхронного сообщения WM_DDE_DATA, ждет от клиента сообщения WM_DDE_ACK. Это делается при помощи вызова функции PeekMessage. Далее функция PostDataMessage удаляет атом в сообщении WM_DDE_ACK. Если сообщение WM_DDE_ACK не приходит в течение трех секунд, или если сообщение содержит негативное подтверждение, то функция PostDataMessage освобождает блок данных, содержащий структуру DDEDATA.
Если вы думаете, что вам удастся избежать части этой работы, если предположить, что клиент никогда не пошлет сообщения WM_DDE_ADVISE с полями "отсроченное обновление" и "необходимо подтверждение" структуры POPADVISE, установленными в TRUE, то оставьте эти мысли. Именно это делает Microsoft Excel, устанавливая теплую связь с подтверждением получения сообщений WM_DDE_DATA.
Обновление элементов данных
После обработки сообщения WM_DDE_ADVISE, серверу требуется известить клиента о том, что элемент данных был изменен. То, как это реализовано, зависит от сервера. В программе DDEPOP1 для того, чтобы каждые пять секунд пересчитывать численность населения, используется таймер. Пересчет происходит при обработке в WndProc сообщения WM_TIMER.
Затем WndProc вызывает функцию EnumChildWindows с функцией TimerEnumProc (расположенной в файле DDEPOP1.С после процедуры ServerProc). Функция TimerEnumProc посылает всем дочерним окнам асинхронные сообщения WM_TIMER. Все эти окна будут использовать оконную процедуру ServerProc.
ServerProc обрабатывает сообщение WM_TIMER, просматривая все имена штатов и проверяя, присвоено ли полю fAdvise структуры POPADVISE значение TRUE и изменилась ли численность населения. Если да, то для отправки клиенту синхронного сообщения WM_DDE_DATA вызывается функция PostDataMessage.
Сообщение WM_DDE_UNADVISE
Сообщение WM_DDE_UNADVISE требует от сервера прекратить отправку синхронных сообщений WM_DDE_DATA при изменении элемента данных. Младшим словом параметра lParam этого сообщения является