Глава 16. Концепции и средства программирования в Windows

Языки С и C++ являются основными средствами программирования 32-разрядных приложений Windows. Раньше, когда решающим фактором была скорость выполнения программ, основным языком программирования считался ассемблер, но с появлением Windows ситуация коренным образом изменилась. В настоящей главе мы познакомимся с существующими подходами к созданию традиционных 32-разрядных приложений Windows.

Главу условно можно разбить на три части. В первой из них рассматриваются терминология и основные концепции программирования в Windows. Затем, во второй части, речь пойдет об окнах и графических компонентах приложений, таких как значки, шрифты и прочее. В третьей- части мы поговорим о ресурсах Windows и редакторах ресурсов, предоставляемых компилятором Visual C++.

Примечание

Далее в книге под Windows подразумеваются Windows 95, Windows 98 и WindowsNT. Если описываемая возможность реализуется лишь одной из указанных версий, это оговаривается отдельно.

Основные понятия

Приложения Windows могут создаваться как традиционными методами процедурного программирования на языках С и C++, так и с помощью мощных средств объектно-ориентированного программирования, предоставляемых языком C++. В данном параграфе раскрываются основные концепции программирования в Windowsи объясняется используемая терминология.

Среда Windows

Windows, как известно, представляет собой графическую многозадачную операционную систему. Все программы, разработанные для этой среды, должны соответствовать определенным стандартам и требованиям. Это касается прежде всего внешнего вида окна программы и принципов взаимодействия с пользователями. Благодаря стандартам, общим для всех приложений Windows, пользователю не составляет труда разобраться в принципах работы любого приложения.

Чтобы помочь программистам в разработке приложений для Windows, были созданы многочисленные системные функции, позволяющие легко добавлять в создаваемые программы контекстные меню, полосы прокрутки, диалоговые окна, значки и многие другие элементы пользовательского интерфейса. А существующее многообразие шрифтов и простота их инсталляции значительно облегчают работу по форматированию выводимых текстовых данных.

Windows позволяет работать с различными периферийными устройствами, такими как монитор, клавиатура, мышь, принтер и т.д., вне зависимости от типа самих устройств. Это дает возможность запускать одни и те же приложения на компьютерах с разной аппаратной конфигурацией.

Преимущества Windows

Можно долго перечислять все открывающиеся перед пользователями преимущества среды Windows по сравнению с устаревшей операционной системой MS-DOS. Среди наиболее важных следует указать стандартизированный графический интерфейс пользователя, многозадачность, совершенные средства управления памятью, аппаратную независимость и возможность широкого применения библиотек динамической компоновки (DLL).

Графический интерфейс пользователя

Первое, что бросается в глаза при знакомстве с приложениями Windows, — это стандартизированный графический интерфейс. Графические стандарты со времени появления Windows 95 не претерпели кардинальных изменений. Для представления дисков, файлов, папок и других системных объектов используются специальные растровые изображения, называемые значками. Окно типичного приложения Win­dows показано на рис. 16.1.


Рис.16.1. Окно типичного Windows-приложения

Название приложения появляется в строке заголовка его окна. Все функции, выполняемые программой, перечислены в меню. Чтобы выполнить команду, достаточно выбрать в меню соответствующий пункт и щелкнуть на нем мышью. В большинстве приложений вызовы команд меню дублируются также комбинациями клавиш.

Как правило, программы имеют сходный внешний вид окон и похожие наборы команд меню. Пользователю достаточно на примере одного приложения изучить основные операции по открытию и манипулированию файлами и данными, чтобы чувствовать себя вполне уверенно с любым другим приложением Windows. В качестве примера к сказанному давайте сравним внешний вид окон MicrosoftExcel и MicrosoftWord, представленных соответственно на рис. 16.2 и рис. 16.3.

Нетрудно заметить, что окна построены по одному и тому же принципу и в строке меню присутствуют стандартные пункты — File, Edit и другие. Эти же пункты меню вы найдете в окне редактора Paint, показанном на рис. 16.1.

Стандартный интерфейс облегчает работу не только пользователям, но и программистам. Для добавления в приложение меню или диалогового окна достаточно воспользоваться одной из стандартных функций Windows. Поскольку за реализацию меню и диалоговых окон отвечает сама система, а не программист, это гарантирует правильность работы интерфейса приложения.


Рис. 16.2. Окно приложения Microsoft Excel


Рис. 16.3. Окно приложения Microsoft Word

Многозадачная среда

Многозадачность Windows состоит в том, что одновременно можно запустить несколько приложений или открыть сразу несколько сеансов работы с одним приложением. На рис. 16.4 показаны окна двух приложений, запущенных одновременно. Каждая программа разместила свое окно поверх рабочего стола Windows. В любой момент времени пользователь может переместить одно из окон в иное место экрана, перейти от одного окна к другому, изменить их размер или произвести обмен данными между приложениями.


Рис. 16.4. Windows позволяет запускать несколько приложений одновременно

Хотя считается, что приложения выполняются одновременно, в действительности это не так. В текущий момент времени только одно приложение может использовать ресурсы процессора. Многозадачность реализуется за счет того, что процессор переключается между выполняющимися заданиями в течение очень коротких промежутков времени. Приоритеты выполнения одновременно запущенных программ также не одинаковы. В текущий момент времени активным, т.е. принимающим данные от пользователя, может быть только одно приложение, хотя инструкции для процессора могут поступать сразу от всех открытых приложений, независимо от их состояния. Задачу определения приоритетов приложений и распределения времени работы процессора берет на себя Windows.

До того как многозадачность в Windows была реализована, приложения получали полный контроль над предоставляемыми им ресурсами компьютера, включая устройства ввода/вывода, память, монитор и центральный процессор. В среде Windows все эта ресурсы динамически распределяются между запущенными приложениями.

Ввод данных посредством очередей

Как вы уже знаете, в среде Windows память компьютера представляет собой совместно используемый ресурс. Таковыми являются и большинство устройств ввода, в частности клавиатура и мышь. Поэтому при разработке Windows-приложений становятся недоступными функции наподобие getchar()языка С, считывающие символы непосредственно с клавиатуры, равно как и потоки ввода/вывода языка C++. В среде Windows приложение не может обращаться напрямую к клавиатуре или мыши и получать данные непосредственно от них. Подобная задача выполняется самой Windows, которая заносит данные в системную очередь. Из очереди введенные данные распределяются между запущенными программами. Это осуществляется путем копирования сообщений из системной очереди в очереди соответствующих приложений. Затем, как только приложение оказывается готовым принять данные, оно считывает сообщения из своей очереди и распределяет их между открытыми окнами.

В Windows данные от устройств ввода поступают в виде сообщений. В каждом сообщении указывается системное время, состояние клавиатуры, код нажатой клавиши, позиция указателя мыши и состояние кнопок мыши, а также идентификатор устройства, пославшего сообщение.

Все сообщения от клавиатуры, мыши и системного таймера имеют одинаковый формат и обрабатываются схожим образом. В случае сообщений клавиатуры передается виртуальный код нажатой клавиши, который идентифицирует клавишу независимо от имеющейся в наличии клавиатуры и генерируется Windows, а также аппаратно-зависимый скан-код, генерируемый самой клавиатурой. Передается также информация о состоянии ряда других клавиш, таких как [NumLock], [Alt], [Shift] и [Ctrl].

Клавиатура и мышь, повторяем, являются совместно используемыми ресурсами. Они посылают сообщения всем приложениям, открытым в данный момент в среде Windows. Система переадресовывает все сообщения клавиатуры текущему активному окну. Сообщения мыши обрабатываются иначе. Они направляются тому приложению, над чьим окном в данный момент находится указатель мыши. О таком окне говорят, что оно получает фокус.

Другую группу составляют сообщения системного таймера. Формат их такой же, как у сообщений клавиатуры и мыши. Windows позволяет приложениям инициали­зировать таймер таким образом, чтобы одно из окон приложения регулярно прини­мало сообщения от таймера. Такие сообщения поступают непосредственно в очередь данного приложения.

Сообщения

В основе Windows лежит механизм генерации и обработки сообщений. С точки зрения приложений, сообщения являются формой уведомления о произошедших событиях, на которые приложение должно (или не должно) каким-то образом реагировать. Пользователь может инициировать событие щелчком или перемещением указателя мыши, изменением размера окна или выбором команды из меню. Другие события могут быть инициализированы самим приложением. Например, в электронной таблице завершение вычислений в ячейках может сопровождаться автоматическим обновлением диаграммы, основанной на данном блоке ячеек. В таком случае при завершении вычислений генерируется сообщение для этого же приложения о необходимости обновления диаграммы.

Сообщения могут генерироваться автоматически самой Windows, например в случае завершения работы системы, когда каждому открытому приложению посылается уведомление о необходимости проверить сохранность данных и закрыть свои окна.

Рассматривая роль сообщений в Windows, необходимо отметить, что именно благодаря подсистеме сообщений становится возможной многозадачность Windows. Подсистема сообщений позволяет ей распределять время работы процессора между всеми открытыми приложениями. Каждый раз, когда Windows посылает сообщение приложению, она на некоторое время открывает этому приложению доступ к процессору. Единственная возможность для приложения получить доступ к процессору — это получить сообщение от Windows. Кроме того, сообщения позволяют приложению прореагировать определенным образом на событие, произошедшее в системе. Это событие могло быть вызвано самим приложением, другим приложением, выполняющимся в это же время в Windows, пользователем или операционной системой. Каждый раз, когда происходит то или иное событие, Windows оповещает о нем все заинтересованные приложения, открытые в настоящий момент.

Управление памятью

Одним из наиболее Важных ресурсов системы является память компьютера. Если в системе одновременно запущено несколько приложений, то они должны иметь возможность координировать свою работу таким образом, чтобы не вызывать конфликтов при распределении системных ресурсов. Так, в результате многократного открытия и закрытия программ память компьютера может оказаться фрагментированной. Windows обладает встроенной подсистемой дефрагментации памяти, организующей перемещение и объединение блоков памяти.

Если же размер кода запускаемого приложения превышает объем свободной памяти, появляется опасность исчерпания памяти компьютера. Windows способна автоматически выгружать из памяти неиспользуемые в данный момент фрагменты приложений и загружать их опять с диска при обращении к ним.

Приложения Windows могут совместно использовать функции, хранящиеся в отдельных исполняемых файлах общего доступа. Такие файлы называются библиотеками динамической компоновки (DLL — dynamic link libraries). Windows содержит встроенный механизм компоновки таких библиотек с программами на этапе выполнения. Для работы самой Windows необходим достаточно большой набор DLL-файлов. С целью упрощения работы с динамическими библиотеками в Windows применяется новый формат исполняемых файлов. Такие файлы содержат информацию, позволяющую системе управлять блоками кода и данных, а также выполнять динамическую компоновку.

Аппаратная независимость

Windows обеспечивает также независимость пользовательской среды от типа используемых аппаратных устройств. Благодаря этому программисты избавляются от необходимости наперед учитывать, какие именно монитор, принтер или устройство вода будут подключены к конкретному компьютеру. Ранее, при написании приложений для MS-DOS, необходимо было снабжать программы драйверами всех устройств, которые могут повстречаться программе на разных компьютерах. Например, дня того чтобы приложение MS-DOS могло выводить данные на принтеры любого типа, программист должен был позаботиться о том, чтобы программа содержала драйверы принтеров всех известных марок и типов. Поэтому при написании программы уйма времени уходила на переписывание практически одинаковых программ драйверов. Скажем, один вариант драйвера принтера LaserJet предназначался для приложения MicrosoftWord for DOS, другой вариант этого же драйвера — для MicrosoftWorks и т.д.

В среде Windows драйверы для определенного устройства создаются и инсталлируются только один раз. Причем они могут устанавливаться сразу при инсталляции Windows, поступать вместе с программными продуктами или добавляться самим пользователем.

Аппаратная независимость приложений в Windows реализуется за счет того, что приложения не обмениваются данными с устройствами напрямую, а используют в качестве посредника Windows. Для приложения нет необходимости знать, какой именно принтер подключен к данному компьютеру. Программа передает команду Windows напечатать прямоугольную область с заливкой, после чего уже операционная система разбирается, как реализовать эту задачу на имеющемся оборудовании. Аппаратная независимость облегчает жизнь не только программистам, но и пользователям, поскольку избавляет их от необходимости выяснять, с какими типами внешних устройств может работать то или иное приложениe.

Аппаратная независимость достигается также за счет определения минимального набора базовых операций, которые должны выполняться любыми устройствами. Этот минимальный набор включает элементарные операции, необходимые для правиль­ного решения любых задач, которые могут быть поставлены перед данным устройством. Какой бы сложности ни была задача, она может быть сведена к последовательности элементарных операций, входящих в набор минимальных требований к устройству. Например, далеко не все графопостроители обладают функцией рисования окружностей. Тем не менее, даже если выведение окружностей не входит в набор функций графопостроителя, вы все равно можете создавать программы, которые могут ставить перед графопостроителем подобную задачу. И поскольку, в соответствии с минимальными требованиями, все графопостроители, инсталлируемые в Windows, должны уметь рисовать линии, Windows автоматически преобразует окружность в набор линий и передаст массив векторов графопостроителю.

Чтобы избежать конфликтов при вводе данных, в Windows также определен минимальный набор кодов клавиш, которые должны распознаваться любым приложением. Стандартный набор кодов в целом соответствует раскладке ПК-совместимой клавиатуры. Если какая-нибудь фирма выпустит клавиатуру с дополнительными клавишами, не входящими в стандартный набор, то она должна позаботиться о специальном программном обеспечении, преобразующем коды этих клавиш в после­довательности стандартных кодов, распознаваемых Windows. Минимальному набору кодов должны соответствовать команды, поступающие не только от клавиатуры, но и от всех других устройств ввода, в том числе от мыши. Таким образом, если какая-нибудь фирма выпустит четырехкнопочную мышь, то это не должно вас беспокоить, поскольку производитель сам позаботится о том, чтобы команды от дополнительных кнопок соответствовали стандартным кодам Windows.

Библиотеки динамической компоновки

Функциональные возможности Windows в большой мере обеспечиваются за счет использования библиотек динамической компоновки (DLL). В частности, благодаря этим библиотекам к ядру операционной системы добавляется графический пользо­вательский интерфейс. DLL-файлы содержат функции, которые подключаются к программе во время ее выполнения (динамически), а не во время компиляции (статически).

Динамическая компоновка программ с внешними файлами, содержащими часто используемые процедуры, не является чем-то уникальным для Windows. Этот принцип широко применяется в языках C/C++, где все стандартные функции предоставляются внешними библиотеками. Компоновщик автоматически копирует из библиотек и вставляет в исполняемый файл такие функции, как getchar () и printf (). Благодаря использованию подобного подхода программист избавляется от необходи­мости переписывать каждый раз базовые функции, чем достигается стандартность выполнения таких операций, как считывание символов, вводимых с клавиатуры, и форматирование данных, выводимых на печать. Программист легко может создать собственную библиотеку часто задействуемых функций, например функций изменения шрифта и выравнивания текста. Предоставление доступа к функциям и методам как к глобальным инструментам среды программирования обеспечивает возможность повторного использования кода — ключевая концепция объектно-ориентированного программирования.

Все библиотеки Windows компонуются динамически. То есть функции из этих библиотек не копируются в исполняемые файлы, а вызываются во время выполнения программы, что позволяет экономить ресурсы памяти. Не важно, сколько приложений одновременно запущено, — в ОЗУ хранится только одна копия библиотеки, используемая всеми приложениями.

Если в программе вызывается стандартная функция Windows, то компилятор должен сгенерировать по месту вызова машинный код, содержащий обращение по адресу, находящемуся в другом сегменте кода. Такое положение представляет собой определенную проблему, поскольку до тех пор, пока программа не будет запущена, невозможно угадать, каким будет адрес библиотечной функции. Решение этой проблемы в Windows называется отложенным связыванием, или динамической компоновкой. Начиная с Windows 3.0 и Microsoft С 6.0, компоновщик позволяет обращаться к функциям, адреса которых не известны в момент компоновки. Окончательная компоновка функции происходит лишь после того, как программа запускается и загружается в память.

В компиляторах C/C++ используются специальные импортируемые библиотеки, назначение которых состоит в подготовке приложений к динамической компоновке в среде Windows. Например, в библиотеке USER32.LIB перечислены все стандартные функции Windows, к которым можно обращаться в программах. В записях этой библиотеки определяются модули Windows, где хранятся соответствующие функции, а также, в большинстве случаев, порядковый номер функции в этом модуле.

Например, многие приложения Windows вызывают функцию PostMessage (). Во время компиляции программы компоновщик получает из файла USER32.LIB информацию о модуле и номере функции PostMessage() и встраивает эти данные в код программы. При запуске программы Windows считывает имеющуюся информацию и связывает программу с реальным кодом функции PostMessage ().

Формат исполняемых файлов

Для Windows был разработан новый формат исполняемых файлов. В частности, изменения коснулись заголовка файла, который теперь может содержать информацию об импортируемых функциях библиотек динамической компоновки. Чаще всего используются функции модулей KERNEL, USER и GDI, содержащих множество подпрограмм, связанных с различными рутинными операциями, в том числе с обработкой сообщений. Функции, хранящиеся в DLL-модулях, еще называют экспортируемыми. В соответствии с новым форматом исполняемых файлов, экспортируемые функции определяются по имени модуля и порядковому номеру функции в нем. Все DLL-файлы содержат таблицу точек входа, в которой перечислены адреса всех экспортируемых функций,

С точки зрения приложений, эти же функции называются импортируемыми. Импорт функций осуществляется посредством рассмотренного выше механизма отложенного связывания и всевозможных таблиц компоновки. Обычно приложения Windows включают не менее одной экспортируемой функции, называемой оконной процедурой и отвечающей за прием сообщений.

Другая особенность нового формата исполняемых файлов состоит в том, что с каждым сегментом кода и данных любого приложения и библиотеки связывается дополнительная информация. Обычно сегменты кода помечаются специальными флагами как перемещаемые и выгружаемые, а сегменты данных — как перемещаемые. В соответствии с установленными флагами, Windows может автоматически перемещать загруженные сегменты в памяти и даже временно выгружать их на диск, если для выполнения других программ в многозадачной среде требуется дополнительная память. Впоследствии, когда выгруженные сегменты вновь понадобятся для выполнения программы, Windows автоматически загрузит их обратно. Другой интересной особенностью является загрузка по вызову. При использовании данного механизма сегмент кода загружается в память только при условии, что в программе встречается вызов функции, находящейся в этом сегменте. Благодаря такого рода средствам в Windows можно работать с несколькими приложениями одновременно, даже если свободной памяти хватает лишь для одного приложения.

Базовые концепции программирования

Особенность создания приложений в среде Windows заключается в том, что здесь применяются специальные методики программирования и используется своя терминология. Последнюю можно разделить на две большие категории: терминология, связанная с пользовательским интерфейсом (меню, диалоговые окна, значки и т.д.), и терминология, относящаяся непосредственно к программированию (сообщения, вызовы функций и т.д.). Чтобы вы могли эффективно общаться и легко понимать друг друга, необходимо внимательно изучить все описанные ниже термины и понятия.

Что представляет собой окно

Окно — это специальная прямоугольная область экрана. Все элементы окна, его размер и внешний вид контролируются открывающей его программой. Каждый щелчок пользователя на каком-нибудь элементе окна вызывает ответные действия приложения. Многозадачность в Windows заключается, в частности, в возможности одновременно открывать окна сразу нескольких приложений или нескольких окон одного приложения. Активизируя с помощью мыши или клавиатуры то или иное окно, пользователь дает системе понять, что последующие команды и данные следует направлять именно этому окну.

Компоненты окна

Стандартный внешний вид окон всех приложений Windows и предсказуемость работы различных их компонентов позволяют пользователям чувствовать себя уверенно с новыми приложениями и легко разбираться в принципах их работы. Основные компоненты любого окна показаны на рис. 16.5.


Рис. 16.5. Стандартное окно приложения Windows

Рамка

Обычно каждое окно заключается в небольшую рамку. Новичку может показать­ся, что функции рамки сводятся только к отделению окна от остальных частей экрана. Но в действительности это не так. Как правило, рамка является и средством масштабирования. Размер окна приложения можно изменить, если поместить указатель мыши на рамку и перетащить его, удерживая нажатой левую кнопку мыши.

Строка заголовка

Имя приложения, которому принадлежит открытое окно, отображается в строке заголовка в верхней части окна. Строка заголовка является обязательным элементом всех окон приложений и позволяет пользователю легко определить, какому приложению принадлежит какое окно, если в системе запущено сразу несколько приложений. Строка заголовка активного окна выделяется альтернативным цветом, чтобы его легко можно было отличить от неактивных окон.

Значок приложения

Другим обязательным элементом любого окна является расположенный в его верхнем левом углу значок приложения. Этот значок обычно представляет собой маленький логотип приложения. Щелчок на значке приводит к открытию системного меню.

Системное меню

Системное меню открывается при щелчке мышью на значке приложения. В нем представлены стандартные команды управления окном: Restore(Восстановить), Move(Переместить), Size(Размер), Minimize(Свернуть), Maximize(Развернуть) и Close(Закрыть).

Кнопка свертывания

В правом верхнем углу большинства окон приложений имеется три кнопки. Крайняя левая кнопка предназначена для свертывания окна в кнопку на панели задач.

Кнопка развертывания/восстановления

Средняя кнопка в правом верхнем углу либо разворачивает окно на весь экран, либо восстанавливает прежние его размеры, если окно уже развернуто.

Кнопка закрытия

Крайняя правая кнопка в углу предназначена для закрытия приложения. После закрытия окна активным автоматически становится окно следующего приложения.

Вертикальная полоса прокрутки

В некоторых случаях окно приложения может содержать вертикальную полосу прокрутки, которая располагается по правому краю окна. В верхней и нижней частях полосы находятся кнопки со стрелками, направленными соответственно вверх и вниз. Вдоль самой полосы располагается бегунок. Положение бегунка показывает, какая часть окна или документа отображается в данный момент на экране. Перемещая бегунок, можно выбрать нужную часть многостраничного документа. Щелчок мышью на кнопке со стрелкой приведет к смещению содержимого окна на одну строку вверх или вниз, а щелчок на свободном пространстве выше или ниже бегунка — на одну экранную страницу вверх или вниз.

Горизонтальная полоса прокрутки

Окно может также быть оснащено горизонтальной полосой прокрутки, которая размещается по нижнему краю окна и работает аналогично вертикальной полосе прокрутки. Горизонтальная полоса предназначена для выведения на экран частей документов, состоящих из большого числа столбцов. Щелчок мышью на кнопках со стрелками приводит к смещению содержимого окна на один столбец влево или вправо. Щелчок на областях между стрелками и бегунком смещает изображение на одну экранную страницу влево или вправо.

Строка меню

В окнах большинства приложений сразу под строкой заголовка находится строка меню, содержащая наборы команд и опций программы. Обычно для выбора команд меню используется мышь, хотя эти действия можно выполнить и с помощью клавиатуры. Каждому элементу меню, как правило, соответствует клавиша быстрого вызова, выделенная подчеркиванием в названии элемента. Чтобы выбрать данный элемент, нужно нажать соответствующую клавишу в сочетании с клавишей [Alt]. Так, комбинация клавиш [Alt+F] открывает меню File.

Рабочая область

Рабочая область обычно занимает большую часть окна. Именно в эту область программа выводит результаты своей работы.

Классы окон

Чтобы два окна одной и той же программы выглядели и работали совершенно одинаково, они оба должны базироваться на общем классе окна. В приложениях, написанных на С, где используются традиционные вызовы функций, класс окна регистрируется программой в процессе инициализации. При создании окна класс указывается в качестве параметра функции CreateWindow (). Зарегистрированный новый класс становится доступным для всех программ, запущенных в данный момент в системе. В случае использования библиотеки MFC вся работа по регистрации классов окон выполняется автоматически, что существенно облегчает работу программиста.

Благодаря тому, что окна приложения создаются на основе общего базового класса, значительно сокращается объем информации, которую при этом следует указывать. Поскольку класс окна содержит в себе описания элементов, общих для всех окон данного класса, нет необходимости повторять эти описания при создании каждого нового окна. К тому же все окна одного класса используют одну оконную процедуру, что также позволяет избежать дублирования кода.

Графические объекты, используемые в окнах

Примерами графических объектов, с которыми можно обращаться как с единым целым и которые выступают элементами пользовательского интерфейса, являются строка меню, полосы прокрутки, кнопки и т.д. Наиболее широко используемые графические объекты Windows описаны ниже.

Значки

Значками называются маленькие графические изображения, выполняющие опознавательную функцию. Так, значки приложений на панели задач позволяют легко определить, какие программы в настоящий момент запущены, даже если названия программ не отображаются целиком. Значки могут быть очень полезны в самих приложениях, поскольку с их помощью можно привлекать внимание пользователей к сообщениям об ошибках и различным предупреждениям. В Windows входит набор стандартных значков, в частности стилизованные знак вопроса и восклицательный знак, а также ряд других. С помощью встроенного в компилятор Visual C++ редактора ресурсов вы можете создавать собственные значки.

Указатели мыши

Указатели мыши также являются графическими объектами, используемыми для отслеживания перемещения мыши. Вид указателя может меняться в зависимости от выполняемого задания и состояния системы. Например, стандартный указатель-стрелка меняет свой вид на изображение песочных часов в том случае, если система занята. С помощью встроенного в компилятор Visual C++ редактора ресурсов вы можете создавать собственные указатели мыши.

Текстовые курсоры

Курсоры предназначены для указания места, куда следует осуществлять ввод текстовых данных. Отличительной особенностью курсоров является их мерцание. Поведение курсоров напоминает работу курсоров в MS-DOS. В большинстве тексто­вых редакторов и в полях диалоговых окон в качестве курсора применяется 1-образ-ный указатель мыши. Причем в Windows нет (в отличие от значков и указателей) коллекции готовых курсоров.

Окна сообщений

Окна сообщений представляют собой разновидность диалоговых окон, содержа­щих строку заголовка, значок и текст сообщения. На рис. 16.6 показано стандартное окно сообщения, которое появляется при закрытии окна программы Notepad в том случае, если в нем содержатся несохраненные данные.


Рис. 16.6. Типичное окно сообщения

В приложении указывается текст заголовка окна, текст сообщения, какой из стандартных значков Windows использовать (если это необходимо) и какой набор кнопок выводить. В частности, можно вызывать окна с такими комбинациями кнопок: Abort/Retry/Ignore, ОК, Yes/No, Yes/No/Cancel, ОК/Cancel и Retry/CancelОбычно в окнах сообщений отображаются такие стандартные значки, как IconHand, IconQuestion, IconExclamation, IconAsterisk и некоторые другие.

Диалоговые окна

Диалоговые окна содержат наборы различных элементов управления и предназначены для предоставления пользователю возможности устанавливать опции и параметры программы, которой принадлежит данное окно. Внешний вид диалогового окна разрабатывается с помощью редактора ресурсов компилятора Visual C++.

Шрифты

Шрифт в Windows — это графический ресурс, содержащий набор символов определенного типа. Существует набор функций, с помощью которых можно манипулировать начертанием символов для получения форматированного текста. В приложениях можно использовать различные стандартные шрифты, включая System, Courier и TimesNewRoman, а также пользовательские шрифты. Встроенные функции позволяют на базе основного шрифта получать полужирное начертание, курсив, подчеркнутый текст, изменять размер шрифта. Причем внешний вид шрифта не зависит от типа устройства, на которое выводится текст. Благодаря внедрению технологии TrueType было достигнуто, начиная с Windows 3.1, соответствие между внешним видом шрифта на экране и шрифта, выводимого при печати.

Точечные рисунки

Точечные рисунки представляют собой точную копию части экрана, снятую попиксельно. Тот факт, что изображение является точным образом экрана, устраняет необходимость в каких бы то ни было дополнительных преобразованиях, что существенно сокращает время вывода изображения на экран. В Windows точечные рисунки наиболее широко применяются для двух целей, Во-первых, они служат изображения­ми всевозможных кнопок и значков, например стрелок полос прокрутки и кнопок панелей инструментов. Другой областью применения точечных рисунков являются кисти, с помощью которых рисуются и заполняются цветом различные геометрические фигуры на экране.

Точечные рисунки можно создавать и модифицировать с помощью встроенного редактора ресурсов.

Перья

Перья предназначены для рисования геометрических фигур и различных конту­ров и характеризуются тремя основными параметрами: ширина линии, стиль (точечный, штрихпунктирный, непрерывный) и цвет. Существует два готовых пера: одно для рисования черных линий, другое — для рисования белых. С помощью специальных функций вы можете создавать собственные перья.

Кисти

Кисти предназначены для заливки объектов цветом, выбранным из заданной палитры. Минимальный размер кисти — 8x8 пикселей. Кисть также характеризуется тремя параметрами: размером, шаблоном заливки и цветом. Заливка может быть сплошной, штриховой, диагональной или представлять собой узор, заданный пользователем.

Принципы обработки сообщений

Как вы уже знаете, ни одно приложение в Windows не, отображает свои данные непосредственно на экране. Точно так же ни одно приложение не обрабатывает напрямую прерывания устройств и не выводит данные непосредственно на печать. Вместо этого приложение вызывает встроенные функции Windows и ожидает от системы соответствующих сообщений.

Подсистема сообщений в Windows — это средство распределения информации в многозадачной среде. С точки зрения приложения, сообщение — это уведомление о некотором произошедшем событии, на которое оно, приложение, должно ответить определенным образом. Такое событие может быть инициировано пользователем, скажем путем нажатия клавиши или перемещения мыши, изменением размера окна или выбором команды из меню. Но события могут порождаться и самим приложением.

Особенность этого процесса состоит в том, что приложение должно быть полностью ориентировано на прием и обработку сообщений. Программа должна быть готова в любой момент принять сообщение, определить его тип, выполнить соответствующую обработку и вновь перейти в режим ожидания до поступления следующего сообщения.

Приложения Windows существенно отличаются от приложений, написанных для MS-DOS. Windows открывает приложениям доступ к сотням встроенных функций, которые можно вызывать напрямую или косвенно, посредством библиотек тина MFC. Эти функции содержатся в ряде модулей, таких как KERNEL, GDI и USER. Функции модуля KERNEL отвечают за управление памятью, загрузку и выполнение приложений, а также за распределение системных ресурсов. Модуль GDI содержит функции создания и отображения графических объектов. Модуль USER отвечает за выполнение всех других функций, обеспечивающих взаимодействие приложений с пользователями и средой Windows.

Ниже мы более детально проанализируем работу подсистемы сообщений, изучим формат сообщений и источники их появления, а также разберем некоторые механизмы организации взаимодействия между приложениями и Windows посредством сообщений.

Формат сообщений

Сообщения используются для информирования приложения о том, что в системе произошло то или иное событие. На практике сообщение направляется не столько самому приложению, сколько определенному окну, открытому этим приложением.

Реально в Windowsсуществует только один механизм обработки сообщений — системная очередь сообщений. Но каждое выполняющееся приложение организовывает и свою очередь. Функции модуля USER, в частности, ответственны за передачу сообщений из системной очереди в очередь конкретного приложения. В последней накапливаются сообщения, адресованные любому окну, открытому данным приложением.

Независимо от типа все сообщения характеризуются четырьмя параметрами: дескриптором окна, которому адресуется данное сообщение, типом сообщения и еще двумя 32-разрядными параметрами.

Примечание

Речь идет о параметрах сообщений в 32-разрядных версиях Windows. Для Windows 3.x характерны другие параметры.

Дескрипторы широко используются в приложениях Windows. Напомним, что дескриптором называется уникальный номер, который присваивается всем системным объектам, таким как окна, элементы управления, меню, значки, перья и кисти, а также областям памяти, устройствам вывода и т.д.

Поскольку Windows позволяет одновременно открывать несколько копий одного приложения, операционная система должна иметь возможность отслеживать каждую копию в отдельности. Это достигается путем присвоения каждому экземпляру программы дескриптора.

Дескрипторы обычно служат в качестве индексов системной таблицы объектов. Благодаря тому что доступ к объектам осуществляется по индексам таблицы, а не по их непосредственным адресам в памяти, Windows может динамически перераспределять ресурсы за счет обновления адресов в таблице. Например, если Windows связaла некоторый ресурс приложения с 16-й строкой таблицы, то независимо от того, куда Windows переместит впоследствии этот ресурс, его текущий адрес всегда будет представлен в 16-й строке.

Вторым параметром, передаваемым с каждым сообщением, является его тип. Тип сообщения задается идентификатором, который определен в одном из файлов заголовков Windows. Для работы с идентификаторами сообщений в программу включается файл WINDOWS.H. Как правило, идентификаторы начинаются с двухсимвольного префикса, за которым следует символ подчеркивания. Так, оконные сообщения начинаются с префикса m_: wm_create, wm_paint, wm_close, wm_copy, wm_paste. Сообщения кнопок имеют префикс ВМ_, полей — ЕМ_, списков — LB_. В приложении можно также создать и зарегистрировать собственный тип сообщения, предназначенного для частных целей.

Последние два параметра сообщения несут дополнительную информацию. Их содержание может изменяться в зависимости от типа сообщения. Например, посредством этих параметров может передаваться информация о том, какая клавиша была нажата, где находился указатель мыши или бегунок полосы прокрутки и т.д.

Генерирование сообщений

Именно реализация концепции обмена сообщениями позволяет Windows быть многозадачной средой. Работа Windows основана на передаче, приеме и обработке сообщений. Существует четыре основных источника, от которых приложение может получить сообщение: пользователь, Windows, само приложение, другие приложения.

Сообщения пользователей включают информацию о вводе текста, перемещении и нажатии кнопок мыши, выборе команд меню, перемещении бегунка полосы прокрутки и т.д. Большую часть времени приложение занято обработкой именно таких сообщений. Получение сообщения от пользователя означает, что человек, запустивший программу, хочет изменить ход ее выполнения.

Системные сообщения посылаются программе при изменении ее состояния. Например, щелчок на значке приложения означает, что пользователь хочет сделать данное приложение активным. В этом случае Windows сообщает приложению, что на экране открывается его окно, размер и положение окна изменяются и т.д. В зависимости от текущего состояния приложения сообщение от Windows может быть принято и обработано либо проигнорировано.

В следующей главе мы поговорим о том, как создаются простейшие приложения Windows. Вы поймете, что, по сути, приложение разбивается на ряд процедур, каждая из которых отвечает за обработку определенного типа сообщений для определенного окна. Например, одна из процедур может отвечать за изменение размеров окна. Причем совсем не обязательно, чтобы это происходило только по команде пользователя, — решение об изменении может принимать и сама программа.

Сообщения четвертого типа в настоящее время применяются достаточно редко. Примером межзадачного обмена сообщениями может служить протокол DDE (DynamicDataExchange— динамический обмен данными).

Обработка сообщений

Традиционные приложения Windows, написанные на C/C++, содержат специальные процедуры для обработки всех типов сообщений, которые могут быть посланы программе. Разные окна программы могут по-разному реагировать на одни и те же сообщения. Это достигается за счет того, что обработчики сообщений пишутся отдельно для каждого окна, но Windowsзнает, какому именно окну адресовано сообщение. Таким образом, приложения содержат процедуры обработки не только сообщений разных типов, но и сообщений для разных окон.

Цикл обработки сообщений

Основным компонентом любого приложения Windowsявляется цикл обработки сообщений. В процедурном приложении местонахождение этого цикла нетрудно определить. В программах, написанных с использованием библиотеки MFC, цикл обработки сообщений скрыт в классе cwinApp.

Если говорить в целом, работа приложения организуется следующим образом. Приложение сначала создает и открывает свои окна, затем запускается цикл обработки сообщений и, в конце концов, при получении сообщения типа WM_CLOSE, работа программы завершается. Цикл обработки сообщений ответственен за передачу поступающих от Windowsсообщений соответствующим оконным процедурам.

На последовательность обработки сообщений влияют два фактора: очередь, в которой находится сообщение, и приоритет его самого. Сообщения могут поступать из двух очередей: системной и очереди приложения. Но даже если сообщение поступило от самого приложения, оно все равно будет помещено в системную очередь. Когда подойдет черед сообщения, оно будет направлено в очередь соответствующего приложения. Такая организация работы системной очереди позволяет Windows контролировать прохождение всех сообщений и ограничивает ответственность приложений обработкой только тех сообщений, которые относятся непосредственно к ним.

Сообщения обычно помещаются в очередь по принципу FIFO (firstin, firstout— первым поступил, первым обслужен). Такие сообщения называются синхронными. Но иногда Windowsвставляет сообщение сразу в голову очереди. Сообщения такого типа, изменяющие нормальный ход выполнения программы, называются асинхронными.

Существует несколько видов асинхронных сообщений, среди них — сообщения о перерисовке, сообщения таймера и сообщения о завершении программы. Например, сообщение таймера может запускать некоторое действие в определенный момент времени независимо от того, какие сообщения сейчас находятся в очереди; оно имеет наивысший приоритет и передается раньше всех других сообщений.

У вас может возникнуть вопрос, как Windows выходит из положения в том случае, если сообщения поступают одновременно нескольким приложениям. Эта проблема решается одним из двух способов. Первый состоит в задании приоритетов. Когда загружается некоторое приложение, для него автоматически устанавливается нулевой приоритет. В процессе работы приложения его приоритет может быть изменен. Любые конфликты разрешаются в пользу того приложения, чей приоритет выше.

Изменять приоритет приложения, заданный по умолчанию, обычно не рекомендуется. Тем более что в распоряжении Windows есть еще один метод, определяющий очередность передачи сообщений группе приложений с одинаковым приоритетом. Если Windows видит, что у приложения образовался длинный список необработанных сообщений, то она автоматически приостанавливает передачу этому приложению новых сообщений, хотя продолжает передавать сообщения другим, более свободным приложениям.

Вызов системных функций

Как известно, Windows содержит сотни встроенных функций, таких как DispatchMessage() , PostMessage(), RegisterWindowMessage(), SetActiveWindow() и т.д. При создании приложений на C++ с использованием библиотеки MFCбольшинство этих функций инкапсулируются в базовых классах и выполняются автоматически.

Соглашение о вызове функций

В Windows3.x описания функций включали спецификатор PASCAL, который в 32-разрядных версиях Windowsне используется. Параметры функций здесь передаются посредством системных стеков и считываются в обычном для C/C++ режиме — в направлений Справа налево. После завершения функции вызвавшая ее процедура должна модифицировать указатель стека с учетом количества байтов, занимаемых параметрами функции.

Файл WINDOWS.H

Файл заголовков WINDOWS.H открывает доступ к тысячам описаний констант, структур, типов данных и прототипов функций. Он включается в большинство приложений Windowsи содержит директивы включения множества других файлов заголовков. (Одна из причин, почему приложения Windows компилируются так долго, состоит не только в относительно больших размерах самих программ, но и в том, что к ним подключаются большие файлы заголовков.) В случае использования библиотеки MFCфайл WINDOWS.H подключается к программе косвенно, Через файл AFXWIN.H.

Обычно в директивах #define, встречающихся в файлах заголовков, за текстовым идентификатором следует числовая константа. Например:

#define WM_CREATE 0x0001

Для VisualC++ данная запись означает, что на этапе компиляции идентификатор сообщения WM_CREATE следует заменить шестнадцатеричной константой 0x0001. Некоторые директивы #define могут выглядеть довольно необычно:

#define NEAR near

#define FAR far

Данные команды позволяют использовать в приложении ключевые слова near и far, набираемые как в верхнем, так и в нижнем регистре, что дает программе ряд преимуществ. Не стоит забывать, что проще изменить объявления в файле заголовков, чем отыскивать и менять ключевые слова по всей программе.

Этапы создания приложения

Разработку приложений Windowsможно разбить на несколько общих этапов. Перечислим их.

Создание ресурсов приложений средствами VisualC++

Компилятор VisualC++ содержит ряд встроенных редакторов ресурсов. Чтобы открыть список доступных редакторов, в меню Insert нужно выбрать команду Resource. Редакторы ресурсов позволяют быстро создавать и изменять собственные значки, указатели мыши, точечные рисунки, диалоговые окна и многое другое.

Каждый ресурс представляет собой блок данных, который добавляется в исполняемый файл приложения. Но если разобраться в технических деталях, то окажется, что эти данные размещаются не в сегменте данных программы. Когда программа загружается в память для выполнения, ресурсы остаются на диске. В качестве примера приведем ситуацию, когда пользователь первый раз вызывает окно About. Прежде чем Windows сможет отобразить это окно, система должна обратиться к жесткому диску и загрузить соответствующие данные из выполняемого файла в память.

Если в приложении планируется использовать такие ресурсы, как диалоговые окна, меню и значки, то каждый из них предварительно должен быть описан в файле сценария ресурсов. Этот файл создается, модифицируется и дополняется с помощью редакторов ресурсов, о которых говорилось выше. Посредством компилятора ресурсов файл сценария преобразуется в файл скомпилированных ресурсов, данные из которого вставляются затем в исполняемый файл приложения. Такой метод обработки ресурсов позволяет приложениям хранить информацию обо всех своих ресурсах непосредственно в исполняемом файле.

Файлы проектов

Файлы проектов служат средством контроля за ходом компиляции ресурсов и программного кода приложения. Они позволяют отслеживать взаимосвязь программы и исходных файлов, учитывать время создания файлов.

В файлах проектов содержится информация о компиляции и компоновке текущего приложения с учетом подключаемых библиотек, аппаратной платформы и системной среды. В большинстве случаев с целью сокращения времени создания нового проекта можно выбрать один из готовых шаблонов, предлагаемых компилятором VisualC++.

С помощью файлов проектов можно также организовать ступенчатую компиляцию и компоновку, когда перекомпиляции подвергаются только те части программы, которые были модифицированы. Это позволяет существенно сократить время построения исполняемого файла.

Редакторы ресурсов

В VisualC++ встроен целый набор редакторов ресурсов, каждый из которых ориентирован на определенный тип ресурсов. В следующих параграфах вы узнаете, как с их помощью создавать значки, указатели мыши, меню и диалоговые окна.

Значки, указатели мыши и точечные рисунки

Хотя ресурсы данного типа разрабатываются с помощью разных редакторов, в основу их создания положен один принцип, так как все они относятся к растровым изображениям. Отличие состоит лишь в том, что редакторы значков и указателей мыши позволяют создавать аппаратно-независимые изображения — в том смысле, что их внешний вид не будет зависеть от разрешения монитора.

Так, значок может иметь четыре описания: одно — для черно-белого монитора, другое — для CGA-системы, третье — для EGA, четвертое — для VGA. Обращение к значку во всех случаях производится одинаково — по имени. При этом Windowsавтоматически выбирает то описание, которое-в наибольшей степени соответствует реальному типу монитора, установленного на данном компьютере. Окно редактора в процессе создания нового значка показано на рис. 16.8.


Рис. 16.8. Окно разработки нового значка

В центре окна находится область редактирования, где можно создать значок, указатель мыши или точечный рисунок. Изначально размер этой области составляет 32x32 ячейки. В левой части окна находится область просмотра. Здесь пользователь может увидеть, как изображение будет выглядеть в системе.

Создание пользовательских значков и указателей мыши

Создать собственный значок или указатель мыши очень просто. Перейдите в меню Insertи выберите команду Resource. Теперь выберите из списка необходимый вам тип ресурса (Icon, Cursor), в результате чего откроется пустая область редактирования.

Редактор предоставляет в ваше распоряжение панель инструментов рисования и палитру цветов. Чтобы сделать нужный цвет активным, достаточно щелкнуть мышью на образце этого цвета в палитре. Нарисовав изображение, сохраните его, выбрав в меню File команду Save или Save As.

На рис. 16.9 приведено окно редактора ресурсов, в котором только что был создан новый указатель. Большое изображение в центре показывает точечную структуру рисунка, тогда как маленькое изображение слева отображает рисунок в том виде, в каком он в действительности будет представлен на экране.


Рис. 16.9. Окно создания указателя мыши

Когда вы первый раз выберете в меню File команду Save, редактор предложит вам ввести имя файла. Если вы создавали значок, то система по умолчанию предложит для файла расширение ICO. Расширение CUR используется для указателей мыши.

С Помощью кнопки SetHotspot вы можете выбрать в создаваемом указателе мыши активную точку, по положению которой определяются координаты указателя на экране. Щелкните на кнопке SetHotspot, наведите появившийся указатель в виде маленького перекрестия на тот пиксель изображения, который вы хотите сделать активной точкой, и просто щелкните мышью. Слева от кнопки отобразятся выбранные координаты. Любой указатель мыши может иметь только одну активную точку.

Меню

Одним из важнейших элементов приложений Windows является меню, которое представляет простой и понятный способ группировки команд и опций программы. Для выбора команды достаточно щелкнуть на требуемом элементе меню. Некоторые команды приводят к последующему появлению диалоговых окон, содержащих дополнительные наборы опций и команд.

Меню, создаваемое в этом параграфе, будет использовано в следующей главе при разработке готового приложения.

Что такое меню

Меню — это список команд и опций программы. Выбрать элемент меню можно с помощью мыши или различных сочетаний клавиш. В ответ на это Windowsпошлет щриложению сообщение с указанием того, какой элемент был задействован.

Создание меню

Разработать меню приложения можно с помощью соответствующего редактора ресурсов, который позволяет проектировать меню в визуальной форме. Альтернативный вариант — использование текстового редактора, в котором набирается описание меню на языке описания ресурсов.

Редактор ресурсов может читать описания меню из файла сценария ресурсов (расширение RC) или файла скомпилированных ресурсов (расширение RES). Первый файл содержит описания ресурсов в текстовом формате. Если имеется файл заголовков с объявлениями констант, используемых в описании меню, этот файл можно включить в файл ресурсов. Например, встречающаяся ниже константа idm_about может быть определена в файле заголовков равной числу 40.

Меню piemenu, разработанное с помощью редактора ресурсов, показано на рис. 16.10.


Рис. 16.10. Создание нового меню

В описание меню можно включать всевозможные стили и атрибуты. Например, можно задать маркировку выбранных элементов специальными метками, указать, что определенный пункт меню изначально недоступен (выделен серым цветом) или является простой линией-разделителем и т.д.

Компиляция ресурса меню

На основании RC-файла компилятор ресурсов скомпилирует описание меню в файл ресурсов с расширением RES. Этот файл будет использован компоновщиком для связывания ресурсов с исполняемым файлом приложения.

Описание простейшего меню не сложно понять. Вот как выглядит файл сценария ресурса:

PIEMENU MENU DISCARDABLE BEGIN

POPUP "Pie_Chart_Data"
BEGIN 

MENUITEM "About...",IDM_ABOUT
        MENUITEM "Input...",IDM_INPUT

MENUITEM "Exit...",  IDM_EXIT
END
END

Изучая этот листинг, вы заметите ряд ключевых слов, используемых в описаниях меню: menu (означает новый ресурс меню), popup (подменю) и menuitem(команда меню). Вместо операторов beginи endможно использовать фигурные скобки ({}). Нетрудно также понять, какие команды будут представлены в нашем меню: About..., Input... и Exit. Троеточие после названия команды означает, что ее выбор приведет к открытию диалогового окна.

После того как Windows получит от вас все сведения о том, каким вы хотели бы видеть меню своего приложения, она автоматически создаст его в соответствии со своими стандартами и правилами. Таким образом обеспечивается стандартность интерфейсов всех приложений Windows.

Ключевые слова редактора ресурсов

Вернемся еще раз к описанию меню piemenu, представленном выше. За именем меню следует ключевое слово menu. В данном примере описывается ниспадающее меню pie_Char_Data, которое открывается щелчком на соответствующем пункте в строке меню. Элементы в строке располагаются в порядке их описания. Если элементы не помещаются в одной строке, то автоматически добавляется новая. В текущий момент времени на экране может быть раскрыто только одно подменю.

Для того чтобы связать с элементом меню клавишу быстрого вызова, в его описании перед соответствующей буквой ставится символ амперсанда (&). В нашем случае такие клавиши не задаются, но если бы мы, к примеру, написали & About. . ., то данную команду можно было бы выбрать путем нажатия клавиш [Alt+A].

При выборе подменю Windowsотображает список находящихся в нем команд, которые были указаны в описании меню с помощью ключевого слова menuitem. Справа от названия команды идет ее идентификатор или константа, содержащиеся в одном из включаемых файлов заголовков. idm— это общепринятый (но не обязательный) префикс идентификаторов команд меню.

Горячие клавиши

В большинстве приложений для быстрого вызова команд меню используются определенные сочетания клавиш. Представим себе меню, в котором содержится 12 команд, задающих различный цвет фона окна. Пользователю можно предоставить возможность изменять цвет обычным способом, т.е. посредством меню, или — как альтернативный путь — нажатием различных комбинаций клавиш, скажем от [F1] до [F12].

Диалоговые окна

Меню предоставляет пользователям простейший способ взаимодействия с программой. Более совершенным методом передачи данных в программу является использование диалоговых окон. В диалоговом окне пользователь может выбирать опции из списка, устанавливать различные флажки, вводить в поля текст и числовые значения и многое другое. Диалоговые окна не только служат ключевым средством ввода данных в программу, но и существенно облегчают программирование, так как многие операции с элементами управления диалоговых окон в Windows автоматизированы.

Чтобы открыть диалоговое окно, достаточно, как правило, выбрать соответствующую команду меню. Подобные команды обозначаются символами троеточия после их названия. Так, в предыдущем примере таковыми были About... и Input....


Рис. 16.12. Заготовка диалогового окна

Ниже приведено описание диалогового окна из файла ресурсов.

PIEDLGBOX DIALOG DISCARDABLE 93,37,195,159

STYLE DS_MODALFRAME I WS_POPOP I WS_VISIBLE | WS_CAPTION I WS_SYSMENU

CAPTION "Pie Chart Data"

FONT 8, "MS Sans Serif"

BEGIN

GROOPBOX "Chart Title:",100, 5, 3, 182, 30,WSJTABSTOP
GROUPBOX "PieWedge Sizes:",101,3, 34,187,95,WSJTABSTOP
LTEXT "Title:", -1,10,21, 30, 8

EDITTEXT DMJTITLE, 40, 18,140, 12

LTEXT "Wedge #1:", -I,10,50,40,8, NOT WS_GROUP
LTEXT "Wedge #2:", -1,10,65,40,8, NOT WS_GROUP
LTEXT "Wedge #3:", -1,10,80,40,8, NOT WS_GROUP
LTEXT "Wedge #4:", -1,10,95,40,8, NOT WS_GROUP
LTEXT "Wedge #5:", -1,10,110, 40,8, NOT WS_GROUP
LTEXT "Wedge #6:", -1,106,50, 40,8, NOT WS_GROUP
LTEXT "Wedge #7:", -1,106,65,40,8, NOT WS_GROUP
LTEXT "Wedge #8:", -1,106,80, 40,8, NOT WS_GROUP
LTEXT "Wedge #9:", -1,106,95,40,8, NOT WS_GRODP
LTEXT "Wedge 110:",-1,102, 110, 45,8, NOT WS_GROUP

EDITTEXT DM_P1, 55,45,30,12
EDITTEXT DM_P2, 55,60, 30, 12
EDITTEXT DM_P3, 55,75,30,12
EDITTEXT DM_P4, 55,90,30,12
EDITTEXT DM_P5, 55,105, 30,12
EDITTEXT DM_P6, 150, 44,30, 12

EDITTEXT DM_P7, 150, 61,30,12 
EDITTEXT DM_P8, 150, 76,30,12
EDITTEXT DM_P9,. 149,91, 30, 12      

EDITTEXT DM_P10, 149,106,30,12
PUSHBUTTON "ОК", IDOK, 39,135, 24,14

PUSHBUTTON "Cancel", IDCANCEL, 122,136,34,14
END

Описания диалоговых окон обычно создаются редактором ресурсов автоматически. Причем редактор может читать описания окон как в текстовом (RC-файл), так и в скомпилированном (RES-файл) виде.

Принципы работы диалоговых окон

Диалоговое окно представляет собой дочернее окно программы, которое появ­ляется при выборе пользователем соответствующей команды из меню. Диалоговые окна разделяются на два основных типа: модальные и немодальные. В большей мере распространены первые. В случае открытия модального диалогового окна все другие окна и команды приложения становятся недоступными до тех пор, пока пользователь не закончит работу с этим окном, обычно щелчком на кнопке ОК или Cancel. При нажатии кнопки ОК запускается процедура обработки новых данных, введенных пользователем, тогда как нажатие кнопки Cancel возвращает программу к исходному состоянию, а все введенные данные отменяются. В Windows с кнопками ОК и Cancel связаны стандартные идентификаторы idok и idcancel со значениями 1 и 2 соответственно.

Немодальные диалоговые окна больше напоминают обычные окна приложений. Пользователь может свободно переходить между таким диалоговым окном и его родителем. Немодальные диалоговые окна используют в том случае, когда необходимо параллельно работать с несколькими окнами. Примером подобного окна может служить палитра цветов в редакторе растровых изображений.

Разработка диалоговых окон

Существует два способа создания диалогового окна. Если вы нашли описание окна в каком-нибудь листинге, приведенном в книге, то проще всего с помощью текстового редактора ввести это описание в том виде, в каком оно есть, после чего сохранить его в файле сценария ресурсов с расширением RC. Затем с помощью компилятора ресурсов преобразуйте данный файл в RES-файл. Если же вы создаете для своего проекта совершенно новое диалоговое окно, следует использовать соответствующий редактор ресурсов.

Чтобы убедиться в целесообразности использования редактора ресурсов, еще раз обратимся к примеру диалогового окна, описание которогЬ мы рассматривали чуть раньше. Сразу возникает множество вопросов: откуда взялись все эти ключевые слова? что означают эти ряды чисел? как по данному описанию можно представить себе внешний вид диалогового окна? С помощью специальных ключевых Слов и параметров нужно задать размер окна, разместить его на экране, установить в нем необходимые элементы управления и сделать еще много других действий. Вместо того чтобы набирать с клавиатуры непонятные строки, гораздо проще визуально создать требуемое диалоговое окно, используя графический интерфейс редактора ресурсов. Редактор автоматически проделает всю работу за вас.

Чтобы вызвать редактор диалоговых окон, выберите в меню Insert команду Resource, а затем в списке Resourcetype— элемент Dialog. Начальный вид окна редактора показан на рис. 16.12.

В данный момент в нашем окне содержится первичный макет создаваемого диалогового окна. На рис. 16.13 показан промежуточный этап его редактирования. Расположение кнопок было изменено, как и размер окна.


Рис. 16.13. Диалоговое окно в процессе редактирования

Размещение элементов управления

Прежде чем приступать к разработке диалогового окна с помощью редактора ресурсов, следует разобраться в многочисленных элементах управления, которые можно использовать в диалоговых окнах (рис. 16.14).

Ниже перечислены все доступные элементы управления и дано их краткое описание.


Рис. 16.14. Панель инструментов редактора диалоговых окон

Чтобы добавить в макет диалогового окна новый элемент управления, нужно выбрать на панели соответствующий инструмент, установить указатель мыши в нужное место окна и, удерживая нажатой левую кнопку мыши, очертить контур элемента управления. Впоследствии такой элемент управления можно будет переместить в другое место, изменить его размер.

Компоновка диалогового окна

Рассмотрим кратко процесс создания простого диалогового окна About. Окно с данным названием является "визитной карточкой" приложения, содержит номер его версии и указывает обладателей авторских прав. Обычно в таком окне имеется единственная кнопка ОК, и его создание не составляет труда. Заготовка диалогового окна показана на рис. 16.15. Остается только добавить соответствующий текст и правильно разместить элементы управления.

В нашем окне About имеются элементы управления только двух типов — надписи и кнопки. Используя мышь, разместите в окне первую надпись и определите для нее подходящий размер. Затем выполните двойной щелчок внутри надписи, чтобы в открывшемся окне свойств задать ее текст (см. рис. 16.16).


Рис. 16.15. В макет диалогового окна добавлена надпись, указывающая, куда нужно ввести соответствующий текст


Рис. 16.16. Окно About после добавления текста надписи

Чтобы удалить ненужную кнопку Cancel, щелкните на ней мышью и нажмите клавишу [Del], после чего разместите кнопку ОК там, где хотите ее видеть. На рис. 16.17 показан окончательный вариант макета создаваемого диалогового окна.


Рис. 16.17. Окончательный вид окна About

Чтобы сохранить новое диалоговое окно, выберите в меню File команду Save. В результате будет создан файл в формате RC. Для просмотра файла сценария ресурсов можно использовать любой текстовый редактор, в том числе редактор компилятора VisualC++. Как будет выглядеть сценарий созданного нами диалогового окна About, показано ниже.

ABOUTDLGBOX DIALOG DISCARDABLE 50,300, 180, 84

STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAP.TION | WS_SYSMENU

CAPTION "About"

FONT 8, "MS Sans Serif"

BEGIN

CTEXT "Microsoft С Pie Chart Program", -1,3, 29,176,10

CTEXT "by William H. Murray and Chris H. Pappas", -1, 3, 16,176,10

PUSHBUTTON "ОК", IDOK, 74,51,32, 14

END

Диалоговому окну присвоено имя aboutdlgbox. Редактор ресурсов автоматиче­ски рассчитал размеры самого окна и всех элементов управления. В описании указано, что данное окно является модальным (ds_modalframe) и всплывающим (HS_POPUP). Далее следуют описания трех используемых в нем элементов управления. Первые два элемента управления представляют собой надписи. В кавычках указан текст надписи, после чего через запятую следуют числовые значения, задающие идентификатор надписи, ее начальные координаты и размер.

Третьим элементом управления является кнопка ОК. Текст в кавычках является надписью на кнопке. Для данной кнопки используется системный идентификатор

IDOK.

Впрочем, вам нет необходимости просматривать все эти описания. Редактор ресурсов автоматически скомпилирует описание ресурсов в файл с расширением RES. Единственный случай, когда, возможно, придется работать со сценариями ресурсов, — это при переписывании их из журнальных публикаций или книг.

Подключение внешних ресурсов

В RC-файл можно также включать ресурсы, содержащиеся во внешних файлах, например значки, указатели мыши, точечные рисунки и т.д. При этом указывается уникальное имя ресурса, ключевое слово, определяющее тип ресурса, и имя файла ресурса. Например:

myicon ICON myicon.ico
mycursor CURSOR mycursor.cur
mybitmap BITMAP mybitmap.bmp

С помощью приведенных строк в файл ресурсов добавляется три новых ресурса: myicon, mycursor и mybitmap. Литералы ICON, CURSOR и BITMAP являются зарезервированными ключевыми словами, определяющими тип ресурса: значок, указатель мыши и точечный рисунок соответственно. Затем следуют непосредственные имена файлов: myicon.ico, mycursor.cur и mybitmap.bmp.