- •Содержание
- •Часть 1. Общие сведения о технологии программирования 5
- •Часть 2. Windows программирование 24
- •Введение
- •Часть 1. Общие сведения о технологии программирования
- •1. Задачи технологии программирования
- •1.1. Базовые определения
- •1.2. Невозможность доказательства отсутствия программных ошибок
- •1.3. Надежность программного средства
- •1.4. Технология программирования как способ создания надежных программных средств
- •1.5. Этапы развития технологии программирования
- •1.6. Технология программирования и информатизация общества
- •2. Общие принципы разработки программных средств
- •2.1. Специфика разработки программных средств
- •2.2. Основные подходы при создании пс
- •2.3. Жизненный цикл программного средства
- •2.4. Понятие качества программного средства
- •2.5. Обеспечение надежности – основной критерий разработки программных средств
- •2.5.1. Методы борьбы со сложностью
- •2.5.2. Обеспечение точности перевода
- •2.5.3. Преодоление барьера между пользователем и разработчиком
- •2.5.4. Контроль принимаемых решений
- •3. Архитектура программного средства
- •3.1. Понятие архитектуры программного средства
- •3.2. Основные классы архитектур программных средств
- •3.3. Архитектурные функции
- •4. Тестирование и отладка программного средства
- •4.1. Основные понятия
- •4.2. Принципы и виды отладки программного средства
- •4.3. Заповеди отладки программного средства
- •4.4. Автономная отладка программного средства
- •4.5. Комплексная отладка программного средства.
- •Часть 2. Windows программирование
- •5. Основные характеристики Windows платформ
- •5.1. Краткая история Windows
- •5.2. Отличия и общие свойства Windows платформ
- •5.2.1. Общие свойства Windows платформ
- •5.2.2. Отличия Win32 платформ
- •5.2.3. Окна и сообщения
- •5.2.4. Приложения, потоки и окна
- •5.2.5. Классы окон
- •5.2.6. Венгерская нотация
- •5.2.7. Типы сообщений
- •5.2.8. Сообщения и многозадачность
- •5.2.9. Очереди сообщений
- •5.2.10. Процессы и потоки
- •5.2.11. Потоки и сообщения
- •5.2.12. Оконная функция – функция обратного вызова
- •5.2.13. Синхронные и асинхронные сообщения
- •5.2.14. Функции Windows
- •5.2.15. Другие api
- •6. Структура Windows приложений
- •6.1. Файлы заголовков
- •6.2. Глабальные переменные
- •6.3. Точка входа в приложение
- •6.4. Необходимые переменные
- •6.5. Регистрация класса окна
- •6.6. Создание главного окна
- •6.7. Отображение главного окна
- •6.8. Цикл обработки сообщений
- •6.9. Функция окна
- •7. Обработка сообщений в оконной функции
- •7.1. Создание окна wm_create
- •7.2. Определение размера окна wm_size
- •7.3. Отображение содержимого окна wm_paint
- •7.3.1. Случаи генерации сообщения wm_paint
- •7.3.2. Особенность сообщения wm_paint
- •7.3.3. Правила обработки wm_paint
- •7.3.4. Отрисовка вне wm_paint
- •7.3.5. Определение возможностей контекста устройства
- •7.3.6. Системные метрики
- •7.4. Определение расположения окна wm_move
- •7.5. Использование оконных полос прокрутки
- •7.5.1. Диапазон и положение полос прокрутки
- •7.5.2. Сообщения полос прокрутки
- •7.6. Клавиатурный ввод
- •7.6.1. Фокус ввода и активное окно
- •7.6.2. Генерация клавиатурных сообщений
- •7.6.3. Аппаратные сообщения
- •7.6.3.1. Системные аппаратные сообщения
- •7.6.3.2. Несистемные аппаратные сообщения
- •7.6.3.3. Битовые поля параметра lParam
- •7.6.3.4. Виртуальные коды клавиш
- •7.6.4. Символьные сообщения
- •7.6.5. Обработка сообщения wm_char
- •7.6.6. Определение состояния управляющих клавиш
- •7.6.7. Наборы символов
- •7.7. Системный таймер
- •7.7.1. Использование таймера. Первый способ
- •7.7.2. Использование таймера. Второй способ
- •7.8. Удаление окна, сообщение wm_destroy
- •8. Ресурсы приложения и их использование
- •8.1. Меню приложения
- •8.1.1. Виды меню
- •8.1.2. Возможные состояния пунктов меню
- •8.1.3. Сообщения от пунктов меню
- •8.1.4. Создание главного меню приложения
- •8.1.5. Функции для работы с меню
- •8.2. Стандартные элементы управления
- •8.2.1. Создание стандартных элементов управления
- •8.2.2. Разрушение элементов управления
- •8.2.3. Функции для работы с элементами управления
- •8.2.4. Сообщения дочерних окон
- •8.2.5. Сообщения родительского окна дочерним окнам
- •8.2.6. Расширенное управление дочерними окнами
- •8.2.7. Оконные процедуры элементов управления
- •8.2.8. Элемент управления кнопка
- •8.2.8.1. Стили кнопок
- •8.2.8.2. Сообщения от кнопок, получаемые родительским окном
- •8.2.8.3. Сообщения от родительского окна к кнопке
- •8.2.8.4. Кнопки-переключатели
- •8.2.8.5. Сообщение от переключателей
- •8.2.8.6. Сообщение от родительского окна к переключателям
- •8.2.9. Структура drawitemstruct
- •8.2.10. Стандартный элемент управления окно ввода
- •8.2.10.1. Стили окна редактирования
- •8.2.10.2. Сообщения от редактора к родительскому окну
- •8.2.10.3. Сообщения от родительского окна к редактору
- •8.2.11. Стандартный элемент управления статический текст
- •8.2.11.1. Стили элемент управления static
- •8.2.11.2. Сообщения от статического элемента управления
- •8.2.11.3. Сообщения от родительского окна к static
- •8.2.12. Стандартный элемент управления список
- •8.2.12.1. Стили элемента управления список
- •8.2.12.2. Сообщения от списка к родительскому окну
- •8.2.12.3. Сообщения от родительского окна к списку
- •8.2.13. Стандартный элемент управления список с вводом
- •8.2.13.1. Стили элемента управления combobox
- •8.2.13.2. Сообщения от combobox к родительскому окну
- •8.2.13.3. Сообщения от родительского окна к combobox
- •9. Создание и использование диалоговых окон
- •9.1. Этапы создания диалога
- •9.1.1. Создание шаблона диалога
- •9.1.2. Функция диалога
- •9.1.2.1. Сходства между диалоговой функцией и оконной процедурой
- •9.1.2.2. Различия между диалоговой функцией и оконной процедурой
- •9.2. Типы диалоговых панелей
- •9.3. Создание модального диалога
- •9.4. Закрытие модального диалога
- •9.5. Окна сообщений.
- •9.6. Немодальные диалоги
- •9.7. Диалоговые окна общего пользования
- •10. Управление файлами
- •10.1. Доступ к файловой системе
- •10.2. Потоковый ввод/вывод
- •10.3. Функции ядра Windows для работы с файлами
- •10.4. Специализированные функции для работы с файлами
- •11. Печать документов
- •11.1. Последовательность печати документа
- •11.2. Контекст устройства принтера
- •11.3. Диалог отмены печати
- •11.4. Запуск процесса печати
- •11.5. Печать страницы документа
- •11.6. Завершение печати документа
- •12. Процессы и потоки
- •12.1. Диспетчеризация потоков
- •12.2. Проблемы многопоточной технологии
- •12.3. Создание рабочего потока
- •12.4. Организация взаимодействия потоков
- •12.4.1. Рабочий поток – процесс
- •12.4.2. Процесс – рабочий поток
- •12.5. Общая схема взаимодействия потоков
- •13. Приложение "Тестер файлов"
- •13.1. Функция WinMain()
- •13.2. Функция главного окна
- •13.3. Вспомогательные функции
- •13.4. Функция рабочего потока
- •Литература к первой части
- •Литература ко второй части
9.6. Немодальные диалоги
Создание немодальной диалоговой панели не останавливает выполнение приложения. Более того, немодальные диалоговые окна всегда остаются над поверхностью окна владельца, даже если это окно владелец получает фокус ввода. Немодальные окна используются значительно реже модальных диалогов в случаях, когда пользователю необходимо одновременно работать как с окном диалога, так и с основным окном приложения.
Перечислим характерные отличия немодальных диалогов.
1. При использовании немодальной диалоговой панели все сообщения для нее поступают в очередь сообщений приложения. Следовательно, очередь сообщений теперь содержит как сообщения для главного окна, так и для немодального диалога. Для обеспечения корректной реакции диалогового окна на события клавиатуры необходимо изменить цикл обработки сообщений, чтобы он выглядел следующим образом:
while(GetMessage(&msg, NULL, 0, 0)) { if(!IsDialogMessage(hDlgModaless,&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
Если сообщение предназначено для немодального диалога с дескриптором hDlgModaless, то функция IsDialogMessage() отправляет это сообщение оконной процедуре окна диалога и возвращает TRUE, в противном случае – она возвращает FALSE. Следовательно, функции цикла обработки сообщений TranslateMessage() и DispatchMessage() будут вызываться только, если текущее сообщение msg не предназначено для окна диалога.
2. Дескриптор немодального диалогового окна должен быть объявлен как глобальная переменная, поскольку будет использоваться в разных функциях приложения.
3. Немодальные диалоговые окна создаются (но не отображаются!) с помощью функции CreateDialog()
hDlgModaless = CreateDialog(HINSTANCE hInst, LPCTSTR lpTempl, HWND hWndParent, DLGPROC lpDlgFunc)
Параметры функций CreateDialog() и DialogBox() совпадают, однако CreateDialog() возвращает дескриптор окна и не вызывает блокировку родительского окна hWndParent.
4. Для отображения немодальной диалоговой панели используется уже знакомая вам пара функций ShowWindow() и UpdateWindow().
5. Закрытие немодального диалога производится вызовом функции DestroyWindow(), а не EndDialog(). Обработчик нажатий кнопок оконной процедуры диалоговой панели может выглядеть следующим образом:
if (nID == IDOK || nID == IDCANCEL) { DestroyWindow(hDlgModaless); hDlgModaless = NULL; return TRUE; }
6. Обнуление дескриптора hDlgModaless – это программистский прием при работе с немодальным диалогом. Дело в том, что дескриптор может использоваться в разных частях приложения. Следовательно, нужен надежный критерий для проверки существования немодального окна диалога в каждый конкретный момент времени. Нулевой дескриптор и означает отсутствие диалога на экране.
Отмеченные особенности позволяют провести разрушение немодального диалога вызовом функции DestroyWindow() в любом месте приложения, а не только в оконной процедуре диалоговой панели.
9.7. Диалоговые окна общего пользования
В Win32 API реализован ряд часто употребляемых диалоговых окон, что освобождает разработчика от необходимости их повторной реализации для каждого своего приложения. К этим диалоговым окнам, которые носят название общего использования, относятся следующие диалоги.
Назначение диалога |
Вызывающая функция |
Получить имя открываемого файла |
BOOL GetOpenFileName (OPENFILENAME* pOfn) |
Получить имя для сохранения файла |
BOOL GetSaveFileName (OPENFILENAME* pOfn) |
Выбрать цвет |
BOOL ChooseColor (CHOOSECOLOR* pColor) |
Выбрать шрифт |
BOOL ChooseFont (CHOOSEFONT* pCfont) |
Получить параметры для печати документа |
BOOL PrintDlg (PRINTDLG* pPD) |
Получить параметры для настройки страницы при печати |
BOOL PageSetupDlg (PAGESETUPDLG* pPs) |
Получить текст для поиска |
HWND FindText (FINDREPLACE* pFr) |
Получить текст для замены |
HWND ReplaceText (FINDREPLACE* pFr) |
Вызывающие функции двух последних диалогов возвращают дескриптор окна, а не BOOL переменную, как все остальные. Легко догадаться, что эти последние диалоги являются немодальными.
Общие диалоговые окна можно использовать двумя способами.
1. Приложения могут использовать эти диалоги в их стандартном виде, вызывая соответствующую функцию общего диалога как обычную Win32 функцию.
2. Расширенный способ позволяет настраивать общие диалоговые окна, в соответствии с целями приложения, например, заменяя специальным образом шаблоны диалоговых панелей.
В заключение приведем пример программного кода, который дает возможность пользователю выбрать имя файла для сохранения некоторой информации. В этом фрагменте hWnd - дескриптор главного окна, g_hInst - дескриптор копии приложения, ofn - структура OPENFILENAME, поля которой используются для настройки диалоговой панели.
TCHAR szFullPath[MAX_PATH]; TCHAR szFileName[MAX_PATH]; *szFullPath = 0; *szFileName = 0; OPENFILENAME ofn; // проводим “обнуление” всей структуры ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd; ofn.hInstance = g_hInst; // фильтр для отображения типов файлов ofn.lpstrFilter = "Текстовые файлы\0*.txt\0 Все файлы\0*.*\0\0"; ofn.nFilterIndex= 1; ofn.lpstrFile = szFullPath; ofn.nMaxFile = sizeof(szFullPath); ofn.lpstrFileTitle= szFileName; ofn.nMaxFileTitle = sizeof(szFileName); // используем текущий катаог ofn.lpstrInitialDir=NULL; // определяем заголовок диалога ofn.lpstrTitle = "Сохранить в файле"; // настраиваем флаги диалога ofn.Flags = OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT| OFN_HIDEREADONLY |OFN_EXPLORER; // отображаем диалог if (GetSaveFileName(&ofn)) { // в этой точке имеем: // ofn.lpstrFile - полный путь файла // ofn.lpstrFileTitle - имя выбранного файла // делаем запись содержимого файла }