Операционная система Windows 95 для программиста
Проектируя операционную систему Windows 95, фирма Microsoft использовала весь опыт, накопленный ей при создании Windowsверсии 3.1 а также Windows NT. В результате операционной системе Microsoft Windows 95 присущи лучшие черты Microsoft Windows версии 3.1 и Microsoft Windows NT.
В составе Microsoft Windows 95 имеется специальная подсистема, обеспечивающая возможность работы со старыми 16-разрядными приложениями, которые были созданы для Microsoft Windows версии 3.1. Пользователи потратили немало денег на приобретение этих приложений, поэтому вопросы совместимости имеют большое значение.
Программистам же предлагается создавать новые, 32-разрядные приложения, пользуясь системным интерфейсом Win32.
Что это означает для вас, как программиста, привыкшего к 16-разрядной Microsoft Windows? Не придется ли вам переучиваться заново, а также полностью переделывать свои наработки?
Спешим успокоить: перейти от 16- к 32-разрядному программированию гораздо проще, чем от программирования для DOS к программированию для Microsoft Windows. Хотя все же вам придется узнать много нового и привыкнуть к работе в сплошной модели памяти без использования сегментов и селекторов.
Тем не менее, затраченный на изучение Win32 труд полностью компенсируется, так как перед вами откроются новые возможности, ранее недостижимые или достижимые лишь с большим трудом.
Например, сплошная модель памяти позволит вам определять массивы и структуры любого размера, лишь бы они поместились в виртуальную память (реально это десятки и даже сотни мегабайт!). Такие популярные органы управления, как Toolbar , Statusbar, ProgressBar, движковые регуляторы и пр. создаются теперь на базе встроенных в систему классов. Новая файловая система позволяет задавать длинные имена файлов, избавляя пользователей от необходимости называть свои документы 8-буквенными сокращениями вроде OLDLET94.DOC.Стала доступной компонентная модель объектов СOM (Component Object Model), позволяющая приложениям использовать функции, экспортируемые другими приложениями и выполнять обмен данными между различными объектами. Кстати, сами приложения работают теперь в режиме вытесняющей мультизадачности и в изолированных адресных пространствах.
Словом, изменилось многое. Слишком многое, чтобы это можно было перечислить в одном абзаце.
Операционная система Windows 95 для программиста
Для того чтобы ваше приложение соответствовало современным стандартам и было удобно в работе, к его главному окну желательно добавить такие органы управления, как Toolbar и Statusbar. Из предыдущей главы вы узнали, как они выглядят. Теперь пришло время убедиться в том, что при использовании программного интерфейса Microsoft Windows 95 добавление органов управления Toolbar и Statusbar не является такой сложной задачей, как это было при работе с 16-разрядным API Microsoft Windows версии 3.1.
Из чего "сделаны" новые органы управления?
Как и большинство других объектов в Microsoft Windows, органы управления создаются на базе предопределенных классов окон. Для них внутри Microsoft Windows имеются функции окон, реализующие все возможности и определяющие внешний вид органов управления.
Конкретнее: все, необходимое для создания органов управления в среде Microsoft Windows 95 и Microsoft Windows NT, расположено в библиотеке динамической загрузки COMCTL32.DLL .
Создать орган управления не сложнее, чем создать обыкновенное окно. Более того, для этого можно использовать привычные вам функции CreateWindow или CreateWindowEx, указывая зарезервированные имена классов. Например, Toolbar и Statusbar создаются на базе классов, соответственно, TOOLBARCLASSNAME и STATUSCLASSNAME .
Дополнительно вы можете указывать различные стили окна, определяющие расположение и поведение органов управления.
В программном интерфейсе Win32 имеются специальные функции, облегчающие создание новых органов управления. Например, вы можете создать Toolbar с помощью функции CreateToolbarEx , а Statusbar - с помощью функции CreateStatusWindow .
После того как орган управления будет создан, вы получите его идентификатор. Пользуясь этим идентификатором, вы сможете управлять органом, посылая ему сообщения функцией SendMessage. Например, вы можете добавлять кнопки в Toolbar или удалять их оттуда, блокировать или разблокировать кнопки, отображать текст в одной из областей окна Statusbar и т. д.
Когда приложение создает орган управления, оно сообщает соответствующей функции идентификатор родительского окна (т. е. окна, которое создает орган управления). Когда пользователь работает с органом управления, последний посылает в родительское окно извещения в виде сообщений WM_COMMAND или WM_NOTIFY .
Так как орган Toolbar обычно дублирует самые нужные строки главного меню приложения, сообщения WM_COMMAND, создаваемые этим органом, ничем не отличаются от аналогичных сообщений, поступающих от главного меню приложения. Разумеется, вы сами определяете коды сообщений WM_COMMAND для каждой кнопки органа Toolbar.
Сообщение WM_NOTIFY посылается родительскому окну для извещения о том, что пользователь выполняет какие-либо действия с органом управления, например, добавляет в него новую кнопку либо удаляет ненужную.
Поэтому все, что приложение должно сделать для использования органа управления, - это создать его, вызвав одну из перечисленных ранее функций, и обеспечить обработку нескольких сообщений. А это, согласитесь, совсем не сложно.
Операционная система Windows 95 для программиста
Многие приложения отображают информацию в виде таблиц или списков. Операционная система Microsoft Windows 95 предоставляет в распоряжение программиста очень мощный встроенный орган управления List View .
Этот орган управления позволяет отображать списки в нескольких видах:
детальный многоколоночный отчет с возможностью изменения ширины столбцов и сортировки по столбцам;
окно с пиктограммами стандартного размера, аналогичного окну раскрытой папки;
окно с пиктограммами уменьшенного размера;
простой список с пиктограммами.
Такой набор подходит для большинства случаев. Например, детальный многоколоночный отчет удобен для организации просмотра и редактирования содержимого баз данных. Окно с пиктограммами можно использовать для работы с графическими изображениями.
Вы можете получить некоторое представление о возможностях органа управления List View , посмотрев рисунки из раздела "Приложение List Application", расположенного в конце этой главы (рис. 3.1 - 3.4).
Список состоит из элементов, каждому из которых назначается пиктограмма, название (label) и дополнительные текстовые строки, которые могут отображаться в столбцах при использовании режима детального просмотра (рис. 3.1). Кроме того, приложение может отмечать состояние элемента с помощью изображений из дополнительного списка (на рис. 3.1 - 3.4 не показано).
Изменение режима просмотра списка
Просмотрев приведенный только что список сообщений, вы не найдете там сообщения, предназначенного для изменения режима просмотра списка. Таким образом, с помощью посылки сообщения приложение не может изменить внешний вид окна (например, перейти от режима просмотра детального отчета к просмотру списка в виде пиктограмм).
Тем не менее, данная задача выполнима.
С помощью пары функций GetWindowLong и SetWindowLong приложение может изменить стиль окна созданного ранее органа управления List View, что приведет к немедленному изменению режима просмотра. Эти функции были описаны в 13 томе "Библиотеки системного программиста" в разделе "Дополнительная память в структуре окна".
Ниже мы привели фрагмент обработчика сообщения от строки меню, с помощью которой пользователь может переключить орган управления в режим просмотра пиктограмм стандартного размера из любого другого режима:
case ID_OPTIONS_ICONVIEW: { dwStyle = GetWindowLong(hwndList, GWL_STYLE);
if((dwStyle & LVS_TYPEMASK) != LVS_ICON) SetWindowLong(hwndList, GWL_STYLE, (dwStyle & ~LVS_TYPEMASK) | LVS_ICON); break; }
Изменение стиля окна выполняется только в том случае, если режим просмотра отличается от определяемого флагом LVS_ICON.
Аналогичным образом вы можете установить любой другой нужный вам режим просмотра, используя флаги LVS_SMALLICON, LVS_LIST и LVS_REPORT.
Сообщения для органа управления List View
Приложение может посылать органу управления List View многочисленные сообщения. С помощью этих сообщений можно изменять некоторые режимы работы органа, получать информацию об элементах списка, добавлять и удалять элементы списка и т. д.
Ограниченный объем книги не позволяет подробно описать все параметры этих сообщений, поэтому мы приведем только краткий список сообщений. За дополнительной информацией обращайтесь к справочной системе SDK. Там же вы найдете описание макрокоманд, с помощью которых удобно посылать эти сообщения. Некоторые из этих макрокоманд мы уже использовали в предыдущих разделах.
Сообщение | Описание |
LVM_ARRANGE | Выравнивание пиктограмм в окне просмотра списка |
LVM_CREATEDRAGIMAGE | Создание изображения, необходимого для выполнения операции перемещения "drag and drop" (в нашей книге эта возможность органа управления List View не описана) |
LVM_DELETEALLITEMS | Удаление всех элементов из списка |
LVM_DELETECOLUMN | Удаление столбца из детального отчета |
LVM_DELETEITEM | Удаление конкретного элемента из списка |
LVM_EDITLABEL | Начать процесс редактирования имени элемента |
LVM_ENSUREVISIBLE | Размещение элементов в окне просмотра таким образом, чтобы они были видны полностью или по крайней мере частично. При необходимости добавляются полосы просмотра |
LVM_FINDITEM | Поиск элемента в списке по имени или по строке, соответствующей дополнительному элементу |
LVM_GETBKCOLOR | Определение фонового цвета окна List View |
LVM_GETCALLBACKMASK | Определение маски функций обратного вызова |
LVM_GETCOLUMN | Определение атрибутов столбца |
LVM_GETCOLUMNWIDTH | Определение ширины столбца |
LVM_GETCOUNTPERPAGE | Определение количества элементов, которые можно разместить в видимой части окна просмотра по вертикали в режиме списка или детального отчета |
LVM_GETEDITCONTROL | Определение идентификатора однострочного редактора текста EDIT, который применяется для редактирования названия элемента. Этот идентификатор может быть затем использован для изменения параметров редактора текста, например, для ограничения длины нового имени элемента |
LVM_GETIMAGELIST | Получение идентификатора списка изображений |
LVM_GETISEARCHSTRING | Получение инкрементальной строки поиска |
LVM_GETITEM | Получение всех или некоторых атрибутов элемента списка |
LVM_GETITEMCOUNT | Определение количества элементов в списке |
LVM_GETITEMPOSITION | Определение позиции элемента списка |
LVM_GETITEMRECT | Определение границ, занимаемых элементом в окне просмотра |
LVM_GETITEMSPACING | Определение расстояния между изображениями, соответствующими элементам списка |
LVM_GETITEMSTATE | Определение состояния элемента |
LVM_GETITEMTEXT | Получение имени элемента или текстовой строки, соответствующей заданному дополнительному элементу |
LVM_GETNEXTITEM | С помощью этого сообщения можно получить элемент, расположенный вблизи заданного (выше, ниже, правее или левее) |
LVM_GETORIGIN | Текущие координаты (view origin) окна органа управления List View |
LVM_GETSELECTEDCOUNT | Определение количества выделенных элементов списка |
LVM_GETSTRINGWIDTH | Определение ширины заданной текстовой строки, которая получится при использовании шрифта, выбранного для органа управления List View |
LVM_GETTEXTBKCOLOR | Определение цвета фона для текста в окне органа управления List View |
LVM_GETTEXTCOLOR | Определение цвета текста в окне органа управления List View |
LVM_GETTOPINDEX | Определение номера самого верхнего отображаемого элемента списка |
LVM_GETVIEWRECT | Определение координат воображаемого прямоугольника, ограничивающего изображение элемента списка при просмотре в режиме стандартных или уменьшенных пиктограмм |
LVM_HITTEST | Определение элемента, расположенного в данной позиции |
LVM_INSERTCOLUMN | Добавление столбца |
LVM_INSERTITEM | Добавление элемента |
LVM_REDRAWITEMS | Принудительная перерисовка элементов списка, заданных диапазоном номеров |
LVM_SCROLL | Свертка содержимого окна органа управления List View |
LVM_SETBKCOLOR | Установка фонового цвета окна List View |
LVM_SETCALLBACKMASK | Установка маски функций обратного вызова |
LVM_SETCOLUMN | Установка атрибутов столбца |
LVM_SETCOLUMNWIDTH | Установка ширины столбца |
LVM_SETIMAGELIST | Подключение списка изображений к органу управления List View |
LVM_SETITEM | Установка всех или некоторых атрибутов заданного элемента списка |
LVM_SETITEMCOUNT | Подготовка списка для добавления в него новых элементов (расширение списка) |
LVM_SETITEMPOSITION | Перемещение элемента в заданную позицию |
LVM_SETITEMPOSITION32 | Перемещение элемента в заданную позицию с использованием 32-разрядных координат |
LVM_SETITEMSTATE | Установка состояния элемента |
LVM_SETITEMTEXT | Установка названия элемента или текста, соответствующего заданному дополнительному элементу |
LVM_SETTEXTBKCOLOR | Установка цвета фона для текста в окне органа управления List View |
LVM_SETTEXTCOLOR | Установка цвета текста в окне органа управления List View |
LVM_SORTITEMS | Сортировка элементов списка с использованием заданной функции сравнения |
LVM_UPDATE | Обновление элемента списка |
Операционная система Windows 95 для программиста
В операционной системе Microsoft Windows 95 имеется мощное средство, предназначенное для просмотра и редактирования иерархических структур данных. Это орган управления Tree View (рис. 4.1).
Использование органа управления Tree View для просмотра ресурсов приложения в среде Microsoft Visual C++
С помощью такого органа управления вы можете просматривать иерархическую структуру каталогов, пространство имен Microsoft Windows 95 или любую другую информацию, структуру которой можно представить в виде дерева.
В этой главе мы расскажем о том, как можно создать и использовать такой орган управления. Мы приведем исходные тексты приложения Some Books, которое демонстрирует основные возможности органа управления Tree View . Более сложные (и более трудные для изучения) примеры вы найдете в SDK.
Заметим, что приемы работы с органом Tree View во многом напоминают приемы работы с органом управления List View, рассмотренном нами в предыдущей главе.
Сообщения для органа управления Tree View
Перечислим сообщения, которое можно посылать окну органа управления Tree View.
Сообщение | Описание |
TVM_CREATEDRAGIMAGE | Создание изображения, необходимого для выполнения операции перемещения "drag and drop" |
TVM_DELETEITEM | Удаление конкретного элемента из дерева |
TVM_EDITLABEL | Начать процесс редактирования имени элемента |
TVM_ENSUREVISIBLE | Размещение элемента в окне просмотра таким образом, чтобы он были виден полностью или по крайней мере частично. При необходимости добавляются полоса просмотра |
TVM_EXPAND | Расширение или сокращение списка элементов |
TVM_GETCOUNT | Определение количества элементов в дереве |
TVM_GETEDITCONTROL | Определение идентификатора редактора, который применяется для редактирования названия элемента |
TVM_GETIMAGELIST | Получение идентификатора списка изображения |
TVM_GETINDENT | Определение размера сдвига вложенных элементов (в пикселах) |
TVM_GETISEARCHSTRING | Получение инкрементальной строки поиска |
TVM_GETITEM | Получение всех или некоторых атрибутов элемента дерева |
TVM_GETITEMRECT | Определение границ, занимаемых элементом в окне просмотра. С помощью этого сообщения можно определить, виден ли указанный элемент в окне органа управления Tree View |
TVM_GETNEXTITEM | С помощью этого сообщения можно получить элемент, расположенный в соответствии с заданным критерием (следующий, следующий или предыдущий по иерархии, корневой, первый видимый и т. д.) |
TVM_GETVISIBLECOUNT | Определение количества элементов, которые видны в окне органа управления Tree View полностью |
TVM_HITTEST | Определение элемента, расположенного в данной позиции |
TVM_INSERTITEM | Добавление элемента |
TVM_SELECTITEM | Выделение заданного элемента списка, сдвиг элементов до тех пор пока заданный элемент не станет видимым или перерисовка элемента в стиле, обозначающем цель операции перемещения "drag and drop" |
TVM_SETIMAGELIST | Подключение списка изображений к органу управления Tree View |
TVM_SETINDENT | Установка размера сдвига вложенных элементов (в пикселах) |
TVM_SETITEM | Установка всех или некоторых атрибутов заданного элемента дерева |
TVM_SORTCHILDREN | Сортировка вложенных элементов для заданного элемента дерева |
TVM_SORTCHILDRENCB | Сортировка вложенных элементов для заданного элемента дерева с использованием заданной функции сравнения |
Операционная система Windows 95 для программиста
В 12 томе "Библиотеки системного программиста" мы рассказывали вам об органе управления EDIT, который представляет из себя простейший текстовый редактор. В операционной системе Microsoft Windows 95 вы по-прежнему можете его использовать, однако теперь вам доступно намного более мощное средство, о котором раньше вы не могли и мечтать. Это текстовый редактор, встроенный в Microsoft Windows 95 как орган управления Rich Edit .
Вот только основные возможности этого текстового редактора:
символы текста могут иметь любое шрифтовое оформление;
доступны как растровые шрифты, так и шрифты True Type ;
имеется возможность задавать оформление параграфов текста, такое как выравнивание влево или вправо, центровка и задание отступов;
не вызывает особого затруднения организация печати текста, загруженного для редактирования;
орган управления Rich Edit может загружать и сохранять как обычный текст без шрифтового или какого либо другого оформления, так и текст в формате RTF ;
орган управления Rich Edit способен работать с объектами OLE (Object Linking and Embedding).
В добавок, имеется почти полная обратная совместимость со "старым" органом управления EDIT, поэтому вы сможете использовать многие приемы работы, описанные в 12 томе "Библиотеки системного программиста".
Что такое формат RTF?
Формат RTF (Rich Text Format ) предназначен для хранения текста вместе со шрифтовым оформлением и оформлением параграфов. Детальное изучение формата RTF выходит за рамки нашей книги. При необходимости вы сможете найти полное описание этого формата в документации, которая поставляется вместе с SDK. Однако в большинстве случаев вам не придется создавать самостоятельно текстовые файлы в формате RTF, так как для этого можно использовать многие текстовые процессоры (например, Microsoft Word for Windows или приложение WordPad ).
Чтобы вы получили некоторое представление о том, что представляет собой текстовый файл в формате RTF, приведем небольшой пример.
Для преобразования в формат RTF мы взяли следующую текстовую строку:
This is RTF test file. This is RTF test file. This is RTF test file.
Мы загрузили эту строку в приложение RtfPad (исходные тексты которого будут приведены ниже в разделе "Исходные тексты приложения RtfPad"). Затем мы задали для текста шрифтовое оформление и сохранили как текст в формате RTF. Вот что получилось в результате:
{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fnil MS Sans Serif;}{\f1\fnil\fcharset2 Symbol;}{\f2\fswiss\fprq2 System;}{\f3\fswiss\fprq2 Arial;}{\f4\froman\fprq2 Calisto MT;}} {\colortbl\red0\green0\blue0;} \deflang1033\pard\plain\f4\fs38 This is RTF test file. This is RTF test file. This is RTF test file. \par \par \par \par }
Орган управления Rich Edit можно использовать для создания достаточно мощного текстового редактора, напоминающего приложение WordPad (которое поставляется вместе с Microsoft Windows 95). Однако для него можно найти и другое применение. Например, ваше приложение может отображать с его помощью красиво оформленные сообщения.
Обработка извещений
С помощью сообщения EM_SETEVENTMASK приложение, создавшее орган управленияRich Edit, может определить, какие извещения должны поступать в родительское окно. Как и в предыдущих случаях, извещение поступает в родительское окно в форме сообщения WM_NOTIFY .
Код извещения передается через поле code структуры NMHDR , адрес которой находится в параметре lParam сообщения WM_NOTIFY.
Для органа управления Rich Edit определены следующие коды извещений:
Код извещения | Описание |
EN_CORRECTTEXT | Выполняется корректировка слова. Используется только для перьевого ввода |
EN_DROPFILES | Пользователь переместил в окно органа управления Rich Edit пиктограмму файла при помощи операции "drag and drop" |
EN_IMECHANGE | Используется только для азиатских языков |
EN_MSGFILTER | Извещение о событии, созданном мышью или клавиатурой |
EN_PROTECTED | Пользователь попытался отредактировать защищенный текст |
EN_REQUESTRESIZE | Изменились размеры окна органа управления Rich Edit |
EN_SELCHANGE | Произошли изменения в выделении фрагмента текста |
EN_STOPNOUNDO | Было выполнено действие, результаты которого нельзя восстановить с помощью сообщения EM_UNDO |
Кроме того, можно использовать извещения, посылаемые обычному органу управления EDIT. Они были описаны нами в 12 томе "Библиотеки системного программиста".
Сообщения для органа управления Rich Edit
Приложение управляет органом управления Rich Edit таким же образом, что и другими органами управления - при помощи сообщений. Перечислим сообщения, которое можно посылать окну органа управления Rich Edit.
Сообщение | Описание |
EM_CANPASTE | С помощью этого сообщения можно проверить возможность вставки данных из универсального буфера обмена Clipboard в орган управления Rich Edit |
EM_DISPLAYBAND | Отображение фрагмента текста, предварительно отформатированного сообщением EM_FORMATRANGE |
EM_EXGETSEL | Определение начальной и конечной позиции выделенного фрагмента текста |
EM_EXLIMITTEXT | Установка предельного значения для объема текста, который можно записать в орган управления Rich Edit |
EM_LINEFROMCHAR | Определение номера строки, в которой расположен символ с заданным номером (считая от начала текста) |
EM_EXSETSEL | Выделение фрагмента текста |
EM_FINDTEXT | Поиск фрагмента текста |
EM_FINDTEXTEX | Расширенный поиск фрагмента текста |
EM_FINDWORDBREAK | Поиск символа переноса слова на другую строку |
EM_FORMATRANGE | Форматирование фрагмента или всего текста для отображения в заданном контексте устройства. Используется, например, для печати |
EM_GETCHARFORMAT | Определение текущих атрибутов форматирования |
EM_GETEVENTMASK | Задание маски событий, которая определяет набор извещений, посылаемых органом управления Rich Edit родительскому окну |
EM_GETOLEINTERFACE | Получение интерфейса IRichEditOle для доступа к сервису OLE |
EM_GETPARAFORMAT | Определение атрибутов форматирования параграфа |
EM_GETPUNCTUATION | Определение используемых символов пунктуации. Используется только для азиатских языков |
EM_GETSELTEXT | Переписывание в заданный буфер выделенного текста |
EM_GETTEXTRANGE | Переписывание в заданный буфер заданного фрагмента текста |
EM_GETWORDWRAPMODE | Определение режима свертки. Используется только для азиатских языков |
EM_HIDESELECTION | Разрешение или запрещение визуального отображения выделения текста |
EM_PASTESPECIAL | Запись данных в заданном формате из универсального буфера обмена Clipboard в орган управления Rich Edit |
EM_REQUESTRESIZE | После получения этого сообщения окно Rich Edit посылает родительскому окну извещение EN_REQUESTRESIZE. Это извещение означает, что размеры окна Rich Edit изменились |
EM_SELECTIONTYPE | Определение типа выделения: текст, один или несколько OLE -объектов |
EM_SETBKGNDCOLOR | Установка цвета фона для окна органа управления Rich Edit |
EM_SETCHARFORMAT | Установка атрибутов форматирования текста |
EM_SETEVENTMASK | Установка маски событий, которая определяет набор извещений, посылаемых органом управления Rich Edit родительскому окну |
EM_SETOLEINTERFACE | Предоставление органу Rich Edit адреса интерфейса IRichEditOleCallback для доступа к ресурсам OLE |
EM_SETOPTIONS | Установка режимов работы и стилей органа управления Rich Edit, таких как ES_AUTOVSCROLL, ES_READONLY, ES_SAVESEL и т. д. |
EM_SETPARAFORMAT | Установка атрибутов форматирования параграфа текста |
EM_SETPUNCTUATION | Установка используемых символов пунктуации. Используется только для азиатских языков |
EM_SETTARGETDEVICE | Установка контекста устройства отображения и ширины строки для обеспечения работы в режиме WYSIWYG (What You See Is What You Get - что вы видите, то и получите (имеется в виду, при печати) |
EM_SETWORDWRAPMODE | Установка режима свертки. Используется только для азиатских языков |
EM_STREAMIN | Запись в орган управления Rich Edit данных с замещением из потока данных (из файла). Можно указывать обычный текстовый формат или формат RTF |
EM_STREAMOUT | Сохранение содержимого органа управления Rich Edit в потоке (в файле). Можно указывать обычный текстовый формат или формат RTF |
Как видите, сообщений много. Поэтому мы не можем рассказать о них подробно. Однако самые важные из этих сообщений будут рассмотрены при описании исходных текстов приложения RtfPad. Если вам нужна детальная информация, обращайтесь к справочной системе SDK.
Создание органа управления Rich Edit
Орган управления Rich Edit создается на базе предопределенного класса окна "RICHEDIT " при помощи функции CreateWindowEx или CreateWindow, как и многие другие описанные нами в этом томе органы управления.
Однако перед тем как создать окно, необходимо загрузить в память DLL-библиотеку RICHED32.DLL , в которой находятся все необходимые функции. Это можно сделать при помощи функции LoadLibrary :
HINSTANCE hRTFLib; hRTFLib = LoadLibrary("RICHED32.DLL");
О том, что такое DLL-библиотеки, вы уже знаете из 13 тома "Библиотеки системного программиста". Там же была описана и функция LoadLibrary.
После загрузки библиотеки можно создавать окно органа управления Rich Edit:
hwndEdit = CreateWindowEx(0L, "RICHEDIT", "", WS_VISIBLE | WS_CHILD | WS_BORDER | WS_HSCROLL | WS_VSCROLL | ES_NOHIDESEL | ES_AUTOVSCROLL | ES_MULTILINE | ES_SAVESEL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hWnd, (HMENU)IDC_RTFEDIT, hInst, NULL);
Для окна органа управления Rich Edit вы можете использовать следующие дополнительные стили окна:
Стиль | Описание |
ES_DISABLENOSCROLL | Когда полосы просмотра ненужны, они не удаляются, а изображаются в заблокированном состоянии |
ES_NOIME | Запрещение работы редактора методов ввода (нужно только для работы с азиатскими языками) |
ES_SAVESEL | Когда орган управления Rich Edit теряет фокус ввода, сохраняется выделение символов, выполненное пользователем. Если вы не укажите этот стиль, после повторного получения фокуса орган управления выделит весь имеющийся в его окне текст (что не всегда удобно) |
ES_SELFIME | Разрешение работы редактора методов ввода (нужно только для работы с азиатскими языками) |
ES_SUNKEN | Окно органа управления Rich Edit выглядит как углубленное в поверхность родительского окна |
ES_VERTICAL | Рисование в вертикальном направлении (нужно только для работы с азиатскими языками) |
Кроме перечисленных выше стилей вы можете использовать следующие стили, определенные для обычного органа управления Edit:
Стиль | Описание |
ES_AUTOHSCROLL | Выполняется автоматическая свертка текста по горизонтали. Когда при наборе текста достигается правая граница окна ввода, весь текст сдвигается влево на 10 символов |
ES_AUTOVSCROLL | Выполняется автоматическая свертка текста по вертикали. Когда при наборе текста достигается нижняя граница окна ввода, весь текст сдвигается вверх на одну строку |
ES_CENTER | Центровка строк по горизонтали в многострочном текстовом редакторе |
ES_LEFT | Выравнивание текста по левой границе окна редактирования |
ES_MULTILINE | Создается многострочный редактор текста |
ES_NOHIDESEL | Если редактор текста теряет фокус ввода, при использовании данного стиля выделенный ранее фрагмент текста отображается в инверсном цвете. Если этот стиль не указан, при потере фокуса ввода выделение фрагмента пропадает и появляется вновь только тогда, когда редактор текста вновь получает фокус ввода |
ES_READONLY | Создаваемый орган управления предназначен только для просмотра текста, но не для редактирования |
ES_WANTRETURN | Стиль используется в комбинации со стилем ES_MULTILINE. Используется только в диалоговых панелях. При использовании этого стиля клавиша <Enter> действует аналогично кнопке диалоговой панели, выбранной по умолчанию |
ES_RIGHT | Выравнивание текста по правой границе окна редактирования |
Стиль, который нельзя использовать для органа управления Rich Edit | Описание |
ES_LOWERCASE | Выполняется автоматическое преобразование введенных символов в строчные |
ES_OEMCONVERT | Выполняется автоматическое преобразование кодировки введенных символов из ANSI в OEM и обратно. Обычно используется для ввода имен файлов |
ES_PASSWORD | Этот стиль используется для ввода паролей или аналогичной информации. Вместо введенных символов отображается символ "*" или другой, указанный при помощи сообщения EM_SETPASSWORDCHAR |
ES_UPPERCASE | Выполняется автоматическое преобразование введенных символов в заглавные |
Операционная система Windows 95 для программиста
Если ваше приложение сложное и имеет большое количество параметров, следует хорошо подумать о том, как пользователь будет их настраивать. Обычно для настройки предлагается многоуровневая система вложенных меню и нагромождение диалоговых панелей, которые вызываются друг из друга, однако это совсем не то, чему обрадуется пользователь.
Если вы посмотрите, как выглядит система настройки параметров, например, в приложении Microsoft Word for Windows версии 6.0, то увидите, что она организована в виде блокнота, состоящего из нескольких диалоговых панелей с закладками (рис. 6.1). По-видимому, это наиболее удачный вариант, так как пользователь может легко найти и выбрать нужную ему группу параметров.
Блокнот настройки параметров в приложении Microsoft Word for Windows версии 6.0
Реализация блокнота средствами программного интерфейса Microsoft Windows версии 3.1 весьма непроста, однако в операционной системе Microsoft Windows 95 имеется встроенное средство, значительно облегчающее создание подобных систем настройки параметров. Это средство - органы управления Tab и Property Sheet .
Орган управления Tab выглядит как набор закладок (верхняя часть рис. 6.1). Его можно использовать отдельно (исходные тексты соответствующего приложения TABCTRL есть в SDK), однако мы ограничимся случаем, который встречается чаще - использованием его в составе органа управления Property Sheet, который мы и будем называть блокнотом.
Орган управления Property Sheet в Microsoft Windows95 выглядит немного иначе, чем блокнот, показанный на рис. 6.1. Для сравнения вы можете взглянуть на рис. 1.6, расположенный в первой главе, или на рис. 6.2 (см. ниже). Отличие заключается в том, что кнопки управления блокнотом (OK, Cancel, Help и Apply) расположены в нижней части окна блокнота.
Как работают эти кнопки?
Если нажать на кнопку OK, будут установлены новые значения параметров, после чего окно блокнота исчезнет с экрана. Как и следовало ожидать, при помощи кнопки Cancel можно отменить внесение изменений в параметры. Кнопка Help предоставляет доступ к справочной системе.
Кнопка Apply дает возможность изменить параметры и посмотреть, как отразятся эти изменения на приложении. Если нажать на эту кнопку, окно блокнота останется на экране, так что если новая комбинация параметров вас не удовлетворит, вы сможете попробовать другую. При этом вам не придется снова выбирать из меню строку, вызывающую на экран блокнот.
Теперь о волшебстве.
Конечно, наша книга не о колдовстве или магии, однако пользователи любят, когда программы самостоятельно выполняют за них всю работу или хотя бы часть работы (чем не волшебство?). Тем не менее, какая бы "умная" не была ваша программа, все же ей приходится при выполнении задач в полуавтоматическом режиме задавать пользователю вопросы или ставить его перед необходимостью выбора различных альтернатив.
И хотя Microsoft Windows95 не содержит никаких магических органов управления, способных справится с любой работой, в этой операционной системе все же есть средство, позволяющее легко организовать диалог с пользователем в процессе полуавтоматического выполнения тех или иных задач. Примером может послужить диалог при установке операционной системы Microsoft Windows95. Это средство - орган управления Wizard (в переводе это означает "колдун", однако мы воздержимся от такой терминологии).
Орган управления Wizard , так же как и блокнот, представляет собой набор диалоговых панелей (рис. 1.7, 6.6, 6.7 и 6.8). Различие заключается в том, что в блокноте пользователь имеет доступ к любой диалоговой панели, выдвигая ее на передний план при помощи закладки, а в органе управления Wizard он передвигается от одной панели к другой и обратно при помощи кнопок Back и Next. При достижении последней диалоговой панели кнопка Next заменяется на кнопку Finish. Стоит на нее нажать и... (о, чудо!) все будет сделано.
Несмотря на указанные различия, органы управления Property Sheet и Wizard очень похожи друг на друга (не по внешнему виду, а по способу создания и управления). Поэтому мы и рассмотрим их в одной главе.
Вначале займемся органом управления Property Sheet.
Обработка извещений
Когда пользователь нажимает кнопки OK, Cancel или Help, расположенные в нижней части окна блокнота или кнопки Back, Next или Finish, расположенные в нижней части окна органа управления Wizard, функция диалога текущей страницы получает сообщение WM_NOTIFY . Код извещения передается через поле code структуры NMHDR , адрес которой находится в параметре lParam сообщения WM_NOTIFY.
Для органов управленияPropery Sheet и Wizard определены следующие коды извещений:
Код извещения | Описание |
PSN_SETACTIVE | Это извещение передается функции диалога, когда активизируется соответствующая страница блокнота или органа управления Wizard. Обработчик извещения может выполнить все необходимые инициализирующие действия |
PSN_KILLACTIVE | Страница отодвигается на задний план или удаляется с экрана. Обработчик этого извещения может проверить введенные пользователем значения и если они неправильны, заблокировать переключение на другие страницы блокнота |
PSN_APPLY | Это извещение посылается когда пользователь нажимает кнопку OK или Apply |
PSN_HELP | Извещение PSN_HELP посылается когда пользователь нажимает кнопку Help |
PSN_QUERYCANCEL | Извещение PSN_QUERYCANCEL посылается когда пользователь нажимает кнопку Cancel, собираясь закрыть блокнот. Обработчик может запретить это действие, например, если пользователь не указал какие-либо необходимые параметры |
PSN_RESET | Это извещение посылается вслед за извещением PSN_QUERYCANCEL, если обработчик последнего не запретил закрытие блокнота |
PSN_WIZBACK | Посылается, когда пользователь нажал кнопку Back в органе управления Wizard |
PSN_WIZNEXT | Посылается, когда пользователь нажал кнопку Next в органе управления Wizard |
PSN_WIZFINISH | Посылается, когда пользователь нажал кнопку Finish в органе управления Wizard |
Обработчики извещений могут возвращать значение FALSE или TRUE, однако в большинстве случаев дополнительно необходимо устанавливать код завершения в структуре данных диалога с помощью функции SetWindowLong. При этом в качестве второго параметра для этой функции следует указать значение DWL_MSGRESULT.
В следующем фрагменте кода, который взят из приложения "Property Sheet Demo", проверяется длина строки szTempBuf. Если она больше 8, возвращается значение TRUE, а если меньше - FALSE:
if(lstrlen(szTempBuf) > 8) { SetWindowLong(hdlg, DWL_MSGRESULT, TRUE); return TRUE; } else { SetWindowLong(hdlg, DWL_MSGRESULT, FALSE); return FALSE; }
Более подробную информацию об использовании этих извещений вы сможете найти в справочной системе SDK. Самые нужные из них будут описаны в разделах "Приложение Property Sheet Demo" и "Wizard Demo".
Посылка сообщений
Обработчики сообщений, расположенные в функциях диалога, могут посылать органам управления Property Sheet и Wizard различные сообщения, добавляя или удаляя отдельные страницы, изменяя состояние кнопок, таких как Apply или Next, и т. д.
Ниже мы привели список таких сообщений с кратким описанием.
Сообщение | Описание |
PSM_ADDPAGE | Добавление новой страницы в конец блокнота |
PSM_APPLY | Действие этого сообщения эквивалентно действию кнопки Apply. При этом текущая страница получит извещение с кодом PSN_KILLACTIVE |
PSM_CANCELTOCLOSE | Если послать это сообщение, вместо кнопки Cancel появится кнопка Close. Используется в тех случаях, когда пользователь выполнил такие изменения, от которых уже нельзя отказаться |
PSM_CHANGED | Это сообщение разблокирует кнопку Apply |
PSM_GETTABCONTROL | С помощью этого сообщения можно узнать идентификатор органа управления Tab (в нашей книге не описан), который используется для создания закладок в блокноте |
PSM_PRESSBUTTON | С помощью этого сообщения можно симулировать действие кнопок управления блокнотом или органом управления Wizard, таких как, например, OK, Next или Finish |
PSM_QUERYSIBLINGS | Передача сообщения функциям диалога всех страниц в блокноте |
PSM_REMOVEPAGE | Удаление страницы из блокнота |
PSM_REBOOTSYSTEM | Это сообщение посылается при обработке извещений PSN_APPLY или PSN_KILLACTIVE, если для использования новых параметров необходимо выполнить перезапуск системы. При этом функция PropertySheet возвратит значение ID_PSREBOOTSYSTEM. Перезапуск системы приложение может выполнить при помощи функции ExitWindowsEx |
PSM_RESTARTWINDOWS | Аналогично предыдущему, но используется когда нужно перезапустить Microsoft Windows 95 без полного перезапуска системы |
PSM_SETCURSEL | Активизация указанной страницы блокнота по номеру или идентификатору |
PSM_SETCURSELID | Активизация указанной страницы блокнота по ее идентификатору в ресурсах приложения |
PSM_SETFINISHTEXT | Установка нового текста для кнопки Finish с блокированием кнопок Back и Next |
PSM_SETTITLE | Установка заголовка блокнота Property Sheet |
PSM_SETWIZBUTTONS | Блокирование или разблокирование кнопок Back, Next и Finish в органе управления Wizard |
PSM_UNCHANGED | Это сообщение блокирует кнопку Apply |
Самые важные из этих сообщений будут рассмотрены ниже при описании исходных текстов приложений Property Sheet Demo и Wizard Demo. Исчерпывающую информацию об использовании этих сообщений вы найдете, конечно, в справочной системе SDK.
Операционная система Windows 95 для программиста
В этой главе мы расскажем о группе новых органов управления, которые называются общими (generic) органами управления. Это Trackbar , Progressbar , анимационный орган управления Animation , орган циклического просмотра Up-Down и, наконец, орган управления Hot Key .
Все перечисленные выше органы управления просты и удобны.
С помощью органа управления Trackbar пользователь может регулировать какие-либо аналоговые или дискретные параметры, такие как, например, громкость или яркость.
Орган управления Progressbar удобен для отображения процента завершения какого-либо процесса, например, процесса установки программного обеспечения или копирования данных.
Анимационный орган управления Animation предназначен для просмотра видеоклипов (без звукового сопровождения), "оживляющих" приложение.
Ниже в этой главе мы приведем полные исходные тексты приложения Compact Disk Player, демонстрирующих практическое использование трех перечисленных выше органов управления в приложении, предназначенном для проигрывания звуковых компакт-дисков.
Кроме того, в некоторых случаях могут оказаться весьма полезными органы управления Up-Down и Hot Key. Первый из них позволяет организовать циклический просмотр и выбор чисел или текстовых строк, а второй является удобным средством для ввода комбинаций клавиш ускоренного доступа.
В этой главе вы научитесь создавать органы управления Up-Down и Hot Key на примере приложения UpDown, исходные тексты которого приведены в конце книги.
Операционная система Windows 95 для программиста
В этом разделе мы расскажем об основных отличиях Microsoft Windows 95 от Microsoft Windowsверсии 3.1, существенных для программиста. Мы кратко рассмотрим распределение виртуальной памяти, мультизадачность, файловую систему, регистрационную базу данных и другие важные новшества. Более подробное изложение вы найдете в соответствующих главах этого и следующих томов "Библиотеки системного программиста".
Адресация памяти
В операционных системах Microsoft Windows 95 и Microsoft Windows NT для 32-разрядных приложений используется сплошная, несегментированная модель памяти (FLAT-модель ). Основанная на аппаратных особенностях процессоров Intel 80386, 80486 и Pentium, эта модель позволяет адресовать память при помощи 32-разрядного смещения.
Забудьте про сегментные регистры. Их содержимое равно нулю и вам нельзя работать с сегментными регистрами в своих приложениях (даже если вы создаете драйвер устройства).
Забудьте про ключевые слова NEAR и FAR . Сплошная модель памяти похожа на модель памяти TINY , в которой программа адресуется к данным и функциям только при помощи смещения без использования сегментов. Отличие, однако, заключается в том, что размер виртуального адресного пространства в операционных системах Microsoft Windows 95 и Microsoft Windows NT достигает 4 Гбайт.
Сказанное не означает, что любое приложение имеет доступ ко всей памяти. Так как процессор работает в защищенном режиме, адресация памяти выполняется с использованием страничной адресации, глобальной таблицы дескрипторов GDT , а также локальных таблиц дескрипторов LDT . А раз так, то операционная система может ограничить права обычных приложений, "не допуская" их к системной памяти и памяти других приложений (подробное описание схемы адресации памяти в защищенном режиме вы найдете в 6 томе "Библиотеки системного программиста").
В то же время имеются удобные средства организации взаимодействия между различными процессами, исключающими необходимость адресации к памяти других приложений. Это каналы, семафоры и совместно используемая память.
Теперь о том, как используется виртуальное адресное пространство в операционной системе Microsoft Windows 95 (рис. 1.1).
Рис. 1.1. Распределение виртуального адресного пространства в операционной системе Microsoft Windows 95
Верхний гигабайт адресного пространства зарезервирован для использования операционной системой (неплохой запас, не правда ли?). В этой области располагаются виртуальные драйверы, работающие в нулевом кольце защиты, планировщик виртуальных машин, расширитель DOS (DOS extender ), а также сервер DPMI.
Системная область хорошо защищена от обычных приложений и программ DOS, так как последние работают в третьем кольце защиты.
Третий гигабайт виртуального адресного пространства (область совместного использования) нужна для создания блоков памяти, доступных одновременно из нескольких приложений. Из этой области выделяется память для 16-разрядных приложений Windows, а также память, полученная от сервера DPMI.
32-разрядные приложения также работают с этой областью. В частности, здесь находятся некоторые системные 32-разрядные DLL-библиотеки (KERNEL32.DLL , USER32.DLL , GDI32.DLL ), из этой области выделяется память для работы с отображаемыми файлами (об отображаемых файлах мы расскажем в разделе "Изменения в файловой системе"). Кроме того, область совместного использования нужна виртуальным драйверам для создания глобальных блоков памяти, доступных в любой момент времени.
Область, которая простирается от границы первых 4 Мбайт до границы 2 Гбайт содержит адресное пространство текущего 32-разрядного процесса (который в данный момент активен). Здесь размещается исполнимый код процесса, его данные и полученные динамически блоки памяти. Защита адресных пространств разных процессов достигается при помощи механизма страничной адресации.
И, наконец, первые четыре мегабайта виртуального адресного пространства зарезервированы для системы. К этой области имеют доступ 16-разрядные приложения Windows и программы DOS, причем текущая виртуальная машина располагается в пределах первого мегабайта. Остальные три мегабайта нужны для загрузки резидентных программ и драйверов DOS (теперь вряд ли вы теперь сможете пожаловаться на то, что для резидентных программ и драйверов выделяется слишком мало памяти). Заметим также, что первые четыре мегабайта виртуального адресного пространства недоступны для 32-разрядных приложений.
Библиотеки динамической загрузки
По сравнению с Microsoft Windows версии 3.1 в Microsoft Windows 95 и Microsoft Windows NT структура и методы работы с библиотеками динамической загрузки (DLL-библиотеками ) сильно изменились. Например, функция инициализации библиотеки вызывается не один раз при первой загрузке библиотеки в память, а каждый раз, когда к библиотеке подключается новый процесс или новая задача.
Изменения в файловой системе
Файловой системе DOS присущи многие недостатки, один из которых - ограничение длины имени файла. В операционной системе Microsoft Windows95 используется так называемая таблица размещения файлов защищенного режима (Protected-mode FAT или VFAT ), которая позволяет использовать имена файлов длиной до 260 символов (включая двоичный нуль, закрывающий строку имени).
Одно из достоинств таблицы VFAT заключается в том, что она совместима с обычной таблицей FAT . При этом файлы и каталоги, имеющие длинные имена, видны и старым программам, правда, в несколько необычном виде.
Для программ, которые могут воспринимать только короткие имена файлов "в стандарте 8.3" файловая система Microsoft Windows 95 создает альтернативные имена (алиасы). Эти алиасы состоят из первых 6 символов длинного имени, вслед за которыми следует символ "тильда" (~) и число.
Вот, например, как выглядит содержимое каталога Program Files, если его распечатать при помощи команды DIR:
Volume in drive C is MS-DOS_6 Volume Serial Number is 1E76-A1EB Directory of C:\Program Files . <DIR> 17.08.95 20:15 . .. <DIR> 17.08.95 20:15 .. PLUS! <DIR> 17.08.95 21:47 Plus! ACCESS~1 <DIR> 17.08.95 20:15 Accessories THEMIC~1 <DIR> 17.08.95 20:18 The Microsoft Network MICROS~1 <DIR> 17.08.95 20:17 Microsoft Exchange Q DOC 0 05.09.95 10:30 q.doc 1 file(s) 0 bytes 6 dir(s) 33 841 152 bytes free
Обратите внимание, что в правой части листинга выводятся полные имена файлов и каталогов.
Конечно, работать с алиасами неудобно. Тем не менее, на наш взгляд эта проблема в Microsoft Windows 95 решена лучше, чем в операционной системе IBM OS/2 Warp версии 3.0. Последняя вовсе не позволяет программам DOS работать с длинными именами файлов и каталогов, расположенных на дисках HPFS . Такие файлы и каталоги не видны, например, из программы Norton Commander for DOS. Поэтому в IBM OS/2 Warp версии 3.0 программы DOS имеют ограниченный доступ к разделам HPFS.
Другое, весьма существенное новшество, которое появилось в Microsoft Windows 95 (а также в Microsoft Windows NT) - файлы, отображаемые на память .
Программист может открыть файл таким образом, что его содержимое будет автоматически отображаться в виртуальное адресное пространство (в область совместного использования, имеющую размер 1 Гбайт). Далее приложение может выполнять операции чтения и записи в файл, просто работая с оперативной памятью через полученный от системы указатель. Таким образом, вы можете легко "превратить" файл в массив, расположенный в оперативной памяти.
Файл, отображаемый в память, можно сделать доступным одновременно для нескольких работающих параллельно приложений, организовав таким образом обмен данными между этими процессами.
Новые органы управления
Для того чтобы придать приложению современный вид, вы должны создать в его главном окне линейку инструментальных средств (орган управления Toolbar ), область для отображения сообщений (орган управления Statusbar ), а также обеспечить удобные средства просмотра списков (если приложение работает со списками). Если приложение выполняет какую-либо длительную операцию, необходимо отображать процент ее выполнения в наглядном виде. Эта задача выполняется обычно органом управления Progressbar . Существуют и другие элементы пользовательского интерфейса, нужные в большинстве приложений.
К сожалению, в программном интерфейсе операционной системы Microsoft Windowsверсии 3.1 не было предусмотрено никаких средств для создания перечисленных выше органов управления. Программисты были вынуждены создавать их самостоятельно на базе обычных окон, кнопок, диалоговых панелей и т. п. Это было непростым делом, так как каждый такой орган управления состоял из множества взаимодействующих между собой объектов.
Для упрощения процедуры создания приложений с такими органами управления, как Toolbar и Statusbar, широко используют библиотеки объектных классов Microsoft MFC и Borland OWL , а также автоматические генераторы исходного текста приложений, такие как AppWizard из пакета Microsoft Visual C++.
Тем не менее, для стандартизации внешнего вида и поведения приложений было бы неплохо, если бы операционная система содержала внутри себя все необходимые средства для создания элементов пользовательского интерфейса.
Очень хорошей новостью является то, что приложения Microsoft Windows 95 могут создавать сложные органы управления на базе предопределенных классов окна. Таким образом, теперь процедура создания таких органов управления, как Toolbar , Statusbar и Progressbar не намного сложнее процедуры создания кнопки или списка типа Combobox.
Многие из новых органов управления, создаваемых на базе предопределенных в Microsoft Windows 95 классов, вы можете увидеть в главном окне приложения Explorer (рис. 1.3), заменяющего приложения File Manager и Program Manager из Microsoft Windows версии 3.1.
Рис. 1.3. Новые органы управления в окне приложения Explorer
В верхней и нижней части главного окна вы можете заметить органы управления Toolbar и Statusbar. С ними вы знакомы по таким приложениям, как, например, Microsoft Word for Windows.
Обратите внимание на окно в левой части рис. 1.3. В этом окне отображается иерархическая структура пространства имен Microsoft Windows 95. Для отображения используется орган управления Tree view , созданный на базе предопределенного класса. Пользуясь этим органом управления, вы можете раскрывать или закрывать отдельные папки (каталоги), что очень удобно, если просматривается очень большое дерево. Вообразите себе, как было бы трудно создать такой орган управления с использованием только тех средств, которые есть в составе программного интерфейса Microsoft Windows версии 3.1!
Правая часть главного окна приложения Explorer также очень интересна. Она состоит из двух частей. Вверху находятся заголовки столбцов (Name, Size, Type, Modified), сделанные в виде органа управления Column Header . Заголовки столбцов можно передвигать мышью. Если же сделать по заголовку щелчок, данные в соответствующем столбце будут отсортированы. Можно сделать двойной щелчок по разделителю столбцов в заголовке таблицы. В этом случае ширина соответствующей колонки будет установлена так, чтобы в колононке поместилась самая длинная строка из данного столбца.
Ниже окна органа управления Column Header находится список, который создан на базе органа управления Listview. Этот список содержит не только текстовые строки, но и графические изображения (пиктограммы).
Вы сможете легко создать в своем приложении органы управления Column Header и Listview на базе преопределенных классов окна. Реализация этой задачи старыми средствами потребовала бы значительных усилий. А ведь таблицы и списки - неотъемлемая часть приложений, ориентированных на обработку электронных таблиц и баз данных.
Другой часто встречающийся элемент пользовательского интерфейса - движковый регулятор (ползунок). Его можно использовать как для отображения текущего состояния какого-либо процесса, так и для регулирования параметров (например, громкости). На рис. 1.4 показано использование движкового регулятора в приложении Media Player.
Рис. 1.4. Использование движкового регулятора в приложении Media Player
Как и следовало ожидать, в операционной системе Microsoft Windows 95 предусмотрен класс окна для создания такого регулятора.
Большое впечатление производит на многих орган управления Animation , показанный в действии (насколько это возможно в книге) на рис. 1.5.
Рис. 1.5. "Летающие" листки бумаги, созданные с использованием органа управления Animation
Как работает такой орган управления?
Очень просто. В прямоугольном окне проигрывается avi-файл, в котором записан небольшой видеофрагмент. О том как создавать такие файлы без использования дорогостоящей видеоаппаратуры (например, на основе заранее подготовленного набора картинок - мультфильма) вы можете узнать из 15 тома "Библиотеки системного программиста", который называется "Мультимедиа для Windows".
Заметим, что орган управления Animation создается очень легко на базе предопределенного класса окна. Таким же образом вы можете создать и орган управления Progressbar, расположенный в нижней части диалоговой панели, показанной на рис. 1.5.
Еще один орган управления, встроенный в систему, называется Property Sheet . Он показан на рис. 1.6.
Рис. 1.6. Использование органа управления Property Sheet для настройки режима работы программы DOS
Для чего нужен такой орган управления, объяснять не нужно. Современные приложения достаточно сложны и имеют многочисленные параметры, настройка которых через систему меню или диалогов бесконечной вложенности не вызывает у пользователей никакого энтузиазма. Достаточно вспомнить, как эта операция выполнялась в ранних системах разработки Borland C++.
Орган управления Property Sheet создается на базе предопределенного класса и набора диалоговых панелей. Он очень нагляден и удобен в работе.
В Microsoft Windows 95 есть и "волшебный" орган управления Wizard. Что это такое?
Претворяя в жизнь идею о приближении компьютера к человеку, многие современные системы и приложения выполняют достаточно сложные процедуры в полуавтоматическом режиме, задавая вам лишь самые необходимые вопросы. Такие системы называют "волшебниками" (wizard), способными сделать почти все самостоятельно без вмешательства человека.
В качестве примера можно привести средства автоматического создания сложных документов и таблиц в текстовом процессоре Microsoft Word for Windows, систему автоматической генерации исходного текста приложений AppWizard из пакета Microsoft Visual C++, а также, конечно, многочисленные системы, встроенные в Microsoft Windows 95.
Все подобные автоматические системы общаются с вами с помощью набора диалоговых панелей. Пример такой панели показан на рис. 1.7.
Рис. 1.7. Одна из диалоговых панелей системы автоматического создания теневых пиктограмм
В каждой из таких панелей есть кнопки "Back", "Next" и "Cancel", предназначенные, соответственно, для перехода к следующей или предыдущей панели, а также для отмены выполняемого в автоматическом режиме процесса. Кроме этих кнопок на панели имеются другие органы управления, с помощью которых и вы сможете принять посильное участие в происходящем.
Система управления диалоговыми панелями встроена в Microsoft Windows 95, поэтому ваши приложения смогут легко воспользоваться ей. Учтите, что операционная система, какая бы она не была умная, не сможет по волшебству решить любую вашу задачу. Она лишь поможет управиться с диалоговыми панелями, остальное лежит на ваших плечах.
А что вы скажите о новом органе управления, предназначенном для отображения и редактирования текста с использованием шрифтового оформления и различных способов выравнивания отдельных параграфов (рис. 1.8)?
Рис. 1.8. Орган управления Rich Edit Control , на базе которого создано приложение WordPad
Вы можете создать такой орган управления (разумеется, без изображенных на рис. 1.8 кнопок, линеек и т. п.) простым вызовом функции CreateWindow. Далее, вы сможете загружать в этот редактор и выгружать из него текстовые файлы в формате RTF, который понимают многие текстовые процессоры. Вы даже можете разместить в окне редактирования OLE -объекты, например, изображения, созданные приложением Paint.
Предусмотрен специальный орган управления Hot Key, с помощью которого пользователь может легко определить комбинация клавиш активизации приложения. Внешне он похож на однострочный редактор текста. Подробности вы узнаете из седьмой главы нашей книги.
И под конец мы покажем вам еще один новый встроенный в систему орган управления. Возможно, он не самый впечатляющий, но тем не менее удобный в работе. Этот орган управления называется Up-Down и предназначен для изменения значений чисел или перебора текстовых строк (рис. 1.9).
Рис. 1.9. Использование органа управления Up-down вместе с однострочным редкатором текста EDIT для установки количества копий документа при печати
Новый вид стандартных диалоговых панелей
Обратим ваше внимание на новый вид стандартных диалоговых панелей, предназначенных для выполнения таких операций, как открытие файла или документа, сохранение файла или документа, печать и т. д.
Эти изменения вызваны, с одной стороны, необходимостью отображения длинных имен файлов (до 260 символов), с другой - необходимостью отображения пространства имен оболочки Microsoft Windows 95.
Что касается имен файлов, тут все ясно. Длинные имена не поместятся в узких рамках старых диалоговых панелей. Поэтому соответствующие органы управления занимают в новых панелях почти всю ширину (рис. 1.10).
Рис. 1.10. Новый вид стандартной диалоговой панели "Open"
Под пространством имен оболочки Microsoft Windows 95 понимается совокупность имен файлов, каталогов, принтеров, дисковых устройств, сетевых ресурсов и т. д. Новые диалоговые панели позволяют работать со всеми этими объектами.
Пространство имен имеет иерархическую структуру и в этом оно похоже на иерархическую систему каталогов и файлов. Отличие, однако, заключается в том, что в пространство имен включаются не только файлы и каталоги, но и другие объекты (см. рис. 1.3).
Изменился также внешний вид диалоговой панели, предназначенной для печати документов (рис. 1.11).
Рис. 1.11. Новая диалоговая панель, предназначенная для печати документов
Подробнее мы рассмотрим новые стандартные диалоговые панели позже, в отдельной главе одной из следующих книг. Сейчас отметим только, что для внесения изменений в стандартные диалоговые панели вам теперь не нужно готовить свой собственный шаблон - вы можете добавить новые органы управления в уже существующую панель.
Объектно-ориентированная оболочка
Одно из новшеств операционной системы Microsoft Windows95 - объектно-ориентированная оболочка (shell). В большинстве случаев эта оболочка избавляет пользователя от необходимости работать с древовидной файловой системой. Вместо этого она предоставляет ему модель рабочего стола с лежащими на нем папками и другими объектами.
Пользователь может открывать и закрывать папки , создавать новые (как на поверхности рабочего стола, так и внутри других папок), создавать в папках новые документы и перекладывать из одной папки в другую существующие - словом, делать то, что он делает, когда работает в своей конторе за обычным столом. Печать документов выполняется простым перемещением пиктограммы документа на пиктограмму принтера, удаление - перемещением пиктограммы документа на пиктограмму мусорной корзины.
Такая технология удобна, особенно для начинающих пользователей компьютера, не знакомых с командами DOS, каталогами и файлами. Однако и более опытные пользователи легко смогут к ней привыкнуть.
Контекстное меню
Важной особенностью объектно-ориентированной оболочки Microsoft Windows 95 является возможность работы с так называемыми контекстными меню. Пример такого меню показан на рис. 1.12.
Рис. 1.12. Контекстное меню для принтера
Для того чтобы вызвать контекстное меню, пользователь должен сделать щелчок правой клавишей мыши, установив курсор на нужную пиктограмму или другой объект, либо на свободную поверхность рабочего стола. Практически каждый объект оболочки имеет контекстное меню, содержание которого определяется самим объектом.
Блокнот свойств объекта
Обратите внимание на строку "Properties" в контекстном меню принтера (рис. 1.12). Если выбрать эту строку, на экране появится блокнот свойств объекта , сделанный на базе органа управления Property Sheet (рис. 1.13).
Рис. 1.13. Блокнот свойств объекта (принтера)
С помощью этого блокнота пользователь может изменить различные параметры объекта. Разумеется, внешний вид блокнота, как и контекстного меню, определяется объектом.
Программные интерфейс Microsoft Windows 95 позволяет вам относительно легко определять для своих объектов контекстное меню и блокнот свойств. Это легче сделать с использованием библиотеки классов MFC , которая входит в состав Microsoft Visual C++.
Теневые пиктограммы
Еще одно из нововведений - теневые пиктограммы , предназначенные для ускоренного запуска приложений или работы с другими объектами, такими как папки, документы, принтеры, локальные и сетевые дисковые устройства и т. д. Вы можете отличить эти пиктограммы по названию, которое имеет вид "Shortcut to ...".
Теневая пиктограмма является визуальным представлением объекта данных, который служит для доступа к другому объекту данных. Последний может находится в любом месте пространства имен оболочки (например, в любой папке).
Ваше приложение может работать с теневыми пиктограммами через интерфейс COM . Соответствующие программы составляются, как правило, на базе библиотеки классов MFC.
Просмотр содержимого файлов и документов
Одно из достоинств популярной программы Norton Commander заключается в возможности форматного просмотра файлов: текстовых, графических, а также файлов баз данных. Просмотр выполняется очень просто - достаточно выделить нужный файл и нажать клавишу <F3>. В зависимости от формата файла автоматически вызывается соответствующая программа просмотра.
В составе оболочки Microsoft Windows 95 имеется похожая по назначению система просмотра. С ее помощью, например, вы можете просматривать содержимое doc-файлов в формате текстового процессора Microsoft Word for Windows, даже если у вас нет этого текстового процессора. Систему просмотра файлов вы можете расширить, добавив в нее собственные средства просмотра файлов новых форматов.
Реальная мультизадачность
Приложения Microsoft Windows версии 3.1 работали в режиме невытесняющей ("добровольной") мультизадачности, передавая друг другу управление в момент выборки сообщения из очереди функцией GetMessage . Этот способ не лишен недостатков, так как ошибка в одном из приложений могла привести к краху всей системы.
В среде Microsoft Windows 95 (и, разумеется, Microsoft Windows NT) организована вытесняющая мультизадачность , когда для работы приложениям выделяются кванты времени. Соответствующая подсистема основана на использовании аппаратных прерываний таймера, поэтому она устойчива к ошибкам приложений.
Однако самая приятная новость заключается в том, что теперь приложения могут создавать подзадачи. И эти подзадачи будут работать параллельно с создавшим их приложением и параллельно с другими приложениями.
В вашем распоряжении есть средства синхронизации задач (семафоры ), а также средства обмена данными между задачами и процессами (каналы и совместно используемая память ).
Все это облегчает создание сложных приложений, допускающих мультизадачную обработку.
Регистрационная база данных
Регистрационная база данных сама по себе не является чем-то новым - она существовала и раньше в Microsoft Windows версии 3.1. Есть она и в Microsoft Windows NT. Как правило, эта база использовалась приложениями, работающими с DDE и OLE . Такие приложения хранят в регистрационной базе данных различную информацию о себе, например, имя сервера.
Вся остальная информация о собственной конфигурации записывалась 16-разрядными приложениями в текстовые файлы с расширением имени ini, которые называются ini-файлами.
Размер системного файла WIN.INI ограничен величиной 64 Кбайт, поэтому приложения вынуждены создавать свои собственные ini-файлы. Большое количество ini-файлов вызывает путаницу (так как нет никакого стандарта на формат записанной там информации), усложняя или делая невозможной процедуру удаления (деинсталляции) ненужных приложений.
В операционных системах Microsoft Windows 95 и Microsoft Windows NT вместо ini-файлов практически всегда используется регистрационная база данных (хотя в каталоге Microsoft Windows 95 присутствуют файлы SYSTEM.INI и WIN.INI).
Регистрационная база данных имеет иерархическую структуру. Вы можете просмотреть или отредактировать ее содержимое при помощи приложения REGEDIT.EXE (рис. 1.2).
Рис. 1.2. Редактирование содержимого регистрационной базы данных
Позже мы научим вас работать с регистрационной базой данных. Пока только скажем, что это несложно, так как в составе Win32 имеются соответствующие функции.
При установке приложения в регистрационную базу данных среди всего прочего записываются сведения, необходимые для деинсталляции, поэтому пользователь сможет при необходимости легко удалить приложение.
БЛАГОДАРНОСТИ
Мы благодарим сотрудника Microsoft A.O. Юрия Томашко за предоставленное в наше распоряжение программное обеспечение.
Мы также выражаем признательность корректору Кустову В. С. и сотрудникам издательского отдела АО "Диалог-МИФИ" Голубеву О. А., Дмитриевой Н. В., Виноградовой Е. К., Кузьминовой О. А.
КАК СВЯЗАТЬСЯ С АВТОРАМИ
Вы можете передать нам свои замечания и предложения по содержанию этой и других наших книг через электронную почту:
Сеть | Наш адрес | Сеть | Наш адрес | |
Relcom | frolov@glasnet.ru | CompuServe | >internet: frolov@ glasnet.ru | |
GlasNet | frolov@glasnet.ru | UUCP | cdp!glas!frolov | |
Internet | frolov@glasnet.ru |
Если электронная почта вам недоступна, присылайте ваши отзывы в АО "Диалог-МИФИ" по адресу:
115409, Москва, ул. Москворечье, 31, корп. 2, тел. 324-43-77
Приносим свои извенения за то что не можем ответить на каждое письмо. Мы также не занимаемся рассылкой дискет и исходных текстов к нашим книгам. По этому вопросу обращайтесь непосредственно в издательство "Диалог-МИФИ".
ЛИТЕРАТУРА
1. Фролов А.В., Фролов Г.В. Библиотека системного программиста. М.: ДИАЛОГ-МИФИ, 1991-1995
Т.6. Защищенный режим работы процессоров Intel 80286/80386/80486.
Т.11 - 13. Операционная система Microsoft Windows 3.1 для программиста.
Т.14. Графический интерфейс GDI в Microsoft Windows.
Т.15. Мультимедиа для Windows.
Т.17. Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы.
Т.20. Операционная система IBM OS/2 Warp.
2. Дженнингс Р. Windows-95 в подлиннике. "BHV-Санкт-Петербург", С.-П.:, 1995
3. Рэй Данкан. Создание RTF-файлов для справочных систем в Windows// PC MAGAZINE/RUSSIAN EDITION, N6,1995, с. 174
4. M. A. Jacobs. Не все приложения Windows 95 работают под управлением Windows NT//COMPUTER WEEK-MOSCOW, N40, с. 23
5. Майкл. Дж. Миллер. Готовимся к Windows 95// PC MAGAZINE/RUSSIAN EDITION, N8,1995, с. 32
6. Дж. Дворак. Windows 95 против OS/2 Warp// PC MAGAZINE/RUSSIAN EDITION, N8,1995, с. 120
7. Джефф Просис. Windows 95: расширения оболочек // PC MAGAZINE/RUSSIAN EDITION, N8,1995, с. 143
8. Брайан Просис. Нужно ли отказываться от FAT// PC MAGAZINE/RUSSIAN EDITION, N8,1995, с. 154
9. Барри Саймон. Стиль программирования: пользовательский интерфейс Windows 95// PC MAGAZINE/RUSSIAN EDITION, N9,1995, с. 163
10. Джефф Просис. Готова ли VFAT выйти на первые роли?// PC MAGAZINE/RUSSIAN EDITION, N9,1995, с. 170
и на свет появилась новая
Итак, долгожданное чудо произошло и на свет появилась новая версия Windows - Microsoft Windows95. Если вы следили за компьютерной прессой, то наверняка находитесь в курсе споров на тему, какая операционная система лучше - Microsoft Windows 95, Microsoft Windows NT или IBM OS/2 Warp (а может быть, одна из версий UNIX?).
Мы не будем развивать эту тему дальше, так как по нашему убеждению, каждая из перечисленных выше операционных систем найдет свою область применения. В любом случае, найдется достаточное количество пользователей, которые пожелают заменить привычную (и порядком уже надоевшую) среду Windows версии 3.1 на объектно-ориентированную среду Microsoft Windows 95. Последняя обладает прекрасным дизайном, вполне приемлемой производительностью, удобными средствами работы в локальных и глобальных сетях. Она также практически полностью совместима с существующими приложениями DOS и Windows. Есть и другие преимущества, о которых вы еще узнаете.
В нашей книге вы не найдете описания приемов работы в Microsoft Windows 95, процедуры установки этой операционной системы и другую информацию, предназначенную скорее для пользователя, чем для программиста. В магазинах есть уже достаточно много литературы на эту тему (книги для пользователей Microsoft Windows 95 появились в продаже еще до официального представления окончательной версии этой операционной системы). Возможно, позже мы посвятим работе пользователя в Microsoft Windows 95 книгу в серии "Персональный компьютер - шаг за шагом".
Этот том "Библиотеки системного программиста" предназначен для тех, кто уже умеет создавать приложения для Windows версии 3.1, поэтому здесь нет описания базовых понятий, таких как цикл обработки сообщений, контекст отображения или цветовая палитра. Если же эти слова для вас незнакомы, обратитесь к томам 11 - 17 "Библиотеки системного программиста".
Несмотря на большое количество нововведений, многое осталось. Поэтому переход от программирования в среде Microsoft Windows версии 3.1 к программированию в среде Microsoft Windows 95 не вызовет у вас шока. Скорее, вы испытаете огромное облегчение, так как в Microsoft Windows 95 сняты многие ограничения, в том числе, связанные с 16-разрядной сегментной адресацией. Кроме того, в операционную систему Microsoft Windows 95 встроены новые органы управления, такие как Toolbar и TreeView, реализация которых раньше была очень трудоемка, новые средства работы с файлами, шрифтами, графикой, мультимедиа и еще много чего.
Практически все, о чем говорится в этой книге, пригодится вам и для программирования в среде операционной системы Microsoft Windows NT, так как в перспективе эта операционная система и Microsoft Windows 95 должны стать эквивалентными по своим возможностям.
Итак, о чем же наша новая книга?
В первой главе мы расскажем вам о том, что появилось нового в операционной системе Microsoft Windows 95 по сравнению с Microsoft Windows 3.1. Вы узнаете, как преобразовать исходный текст приложений, разработанных для Microsoft Windows 3.1 так, чтобы они работали в среде Microsoft Windows 95. Вы научитесь работать в сплошной модели памяти FLAT и узнаете об изменениях в формате сообщений.
Вторая глава посвящена органам управления Toolbar и Statusbar, которые стали неотъемлемой частью многих новых приложений. Теперь, когда эти органы управления стали составной частью операционной системы, их стало значительно легче встраивать в приложения.
Третья глава расскажет вам о том, как создать органы управления, специально предназначенные для просмотра таблиц, списков строк и пиктограмм. Теперь приложения могут делать это с помощью встроенного в операционную систему органа управления List view. Этот орган управления найдет широкое применение, например, в приложениях, работающих с электронными таблицами и базами данных.
В четвертой главе описан встроенный орган управления Tree view, с помощью которого можно просматривать иерархически организованные структуры данных (такие, например, как структуры вложенных каталогов). Реализация подобного органа управления средствами одного только программного интерфейса Microsoft Windows 3.1 была бы очень затруднительной.
В пятой главе мы вам расскажем о новом встроенном редакторе текста Rich Edit. Подобно другим органам управления, он создается на базе предопределенного в системе класса окна. В этом он похож на свой прообраз из Microsoft Windows 3.1 - орган управления EDIT. Однако в отличие от последнего редактор Rich Edit позволяет задавать шрифтовое оформление символов и выравнивание параграфов. Кроме того, редактор текста Rich Edit может сохранять и загружать текстовые файлы в формате RTF, содержащие сведения о шрифтовом оформлении и выравнивании параграфов. Вы даже можете поместить в окно редактора Rich Edit объекты OLE, такие, например, как изображения, подготовленные с помощью приложения Paint.
В шестой главе мы расскажем об органах управления Property Sheet и Wizard, которые представляют собой наборы диалоговых панелей и средства для управления ими. Орган управления Property Sheet удобен для создания систем настройки параметров приложения. С помощью органа управления Wizard можно создавать приложения, выполняющие работу в автоматизированном режиме.
Седьмая глава посвящена органам управления Trackbar, Progressbar, Animation, Up-Down и Hot Key.
Первые два из них предназначены, соответственно, для установки параметра с помощью движка и для графического отображения значения параметра (например, процента завершения какого-либо процесса). Вы можете увидеть эти органы управления в большинстве приложений мультимедиа.
Орган управления Animation предназначен для показа небольших видеофрагментов, главным образом в диалоговых панелях. Это оживляет приложение, увеличивая его привлекательность для пользователя.
С помощью органа управления Up-Down можно легко организовать выбор из нескольких значений. Эта задача встречается очень часто, например, при настройке параметров (номер прерывания, количества копий при печати и т. д.).
И, наконец, орган управления Hot Key позволяет задать комбинацию клавиш активизации для приложения Windows 95, с помощью которой пользователь, например, может выдвинуть окно приложения на передний план (этот процесс напоминает активизацию резидентной программы в DOS).
Для работы вам потребуется компьютер, оснащенный памятью размером 4 - 8 Мбайт (лучше 16 Мбайт), а также система разработки приложений Microsoft Visual C++ версии 2.0, 2.1 или 4.0. Кроме того, мы рекомендуем вам приобрести набор компакт-дисков "Microsoft Developer Network. Development Library", в который помимо всего прочего входит полный набор операционных систем, средства разработки и полная документация для программиста (на английском языке).
Разумеется, для изучения средств мультимедиа вам не обойтись без звукового адаптера. Мы рекомендуем вам приобрести адаптер Sound Blaster 16, обладающий прекрасной совместимостью практически с любым программным обеспечением.
Кроме того, будет очень хорошо, если вы оснастите свой компьютер устройством чтения компакт-дисков (хотя бы потому, что Microsoft Visual C++ последних версий, а также "Microsoft Developer Network. Development Library" поставляется на компакт-дисках).
Все программы, приведенные в книге, были отлажены в системе разработки Microsoft Visual C++ версии 2.0, на компьютере, оснащенном процессором Pentium-90, оперативной памятью объемом 16 Мбайт, диском 540 Мбайт, устройством чтения компакт-дисков Mitsumi FX-400, звуковым адаптером Sound Blaster 16 MultiCD, видеоадаптером Diamond Stealth-64 DRAM PCI. Многочисленные черновые копии книги и программ печатались на принтере OKI OL 410e.
Для работы в одноранговой сети под управлением Microsoft Windows 95 нами был также использован второй компьютер с процессором AMD80386, тактовой частотой 40 Мгц и объемом оперативной памяти 5 Мбайт. Этот компьютер служил в основном как сервер. Даже при такой, не очень мощной по современным понятиям, конфигурации компьютера, операционная система Microsoft Windows 95 работала вполне удовлетворительно.
В будущем мы планируем выпустить тома, посвященные другим аспектам программирования для операционных систем Microsoft Windows 95 и Microsoft Windows NT. Мы рассмотрим, в частности, приемы использования вытесняющей мультизадачности, программирование с использованием библиотеки классов MFC (уже в следующем томе "Библиотеки системного программиста"), работу с семафорами и т. д. Уделим много внимания самой развитой на сегодняшний день файловой системе Microsoft Windows NT, технологии компонентного объектного программирования COM и OLE, которые становятся краеугольными камнями всех новых разработок Microsoft.
Операционная система Windows 95 для программиста
Приложение, создавшее орган управления List View, должно обрабатывать сообщение WM_NOTIFY , поступающее в функцию окна, создавшего этот орган управления.
Коды извещений
Код извещения передается через поле code структуры NMHDR . Напомним, что адрес этой структуры находится в параметре lParam сообщения WM_NOTIFY .
Родительское окно может получить следующие коды извещений:
Код извещения | Описание |
TVN_BEGINDRAG | Начало операции переноса "drag and drop" при помощи левой клавиши мыши |
TVN_BEGINLABELEDIT | Начало операции редактирования названия элемента |
TVN_BEGINRDRAG | Начало операции переноса "drag and drop" с использованием правой клавиши мыши |
TVN_DELETEITEM | Удаление определенного элемента дерева |
TVN_ENDLABELEDIT | Завершение операции редактирования названия элемента |
TVN_GETDISPINFO | Орган управления запрашивает информацию, необходимую для отображения элемента |
TVN_ITEMEXPANDED | Произошло расширение списка дочерних (вложенных) элементов |
TVN_ITEMEXPANDING | С помощью этого извещения родительскому окну предоставляется возможность отменить начатое расширение списка дочерних элементов |
TVN_KEYDOWN | Была нажата клавиша |
TVN_SETDISPINFO | Родительское окно должно обновить информацию об элементах дерева, которую оно хранит в своих структурах данных |
Более подробную информацию об использовании этих извещений вы сможете найти в справочной системе SDK.
Коды извещений
Код извещения передается через поле code структуры NMHDR . Напомним, что адрес этой структуры находится в параметре lParam сообщения WM_NOTIFY.
Родительское окно может получить следующие коды извещений:
Код извещения | Описание |
LVN_BEGINDRAG | Начало операции переноса "drag and drop" |
LVN_BEGINLABELEDIT | Начало операции редактирования названия элемента |
LVN_BEGINRDRAG | Начало операции переноса "drag and drop" с использованием правой клавиши мыши |
LVN_COLUMNCLICK | Пользователь сделал щелчок мышью по заголовку столбца в режиме детального отчета |
LVN_DELETEALLITEMS | Удаление всех элементов списка |
LVN_DELETEITEM | Удаление определенного элемента списка |
LVN_ENDLABELEDIT | Завершение операции редактирования названия элемента |
LVN_GETDISPINFO | Орган управления запрашивает информацию, необходимую для отображения элемента. Это извещение приходит, в частности, когда при добавлении элемента вместо адреса реальной текстовой строки была указана константа LPSTR_TEXTCALLBACK |
LVN_INSERTITEM | Вставка в список нового элемента |
LVN_ITEMCHANGED | Произошло изменение элемента |
LVN_ITEMCHANGING | С помощью этого извещения родительскому окну предоставляется возможность отменить предполагаемое изменение элемента |
LVN_KEYDOWN | Была нажата клавиша |
LVN_SETDISPINFO | Родительское окно должно обновить информацию об элементах списка, которую оно хранит в своих структурах данных |
Рассмотрим особенности обработки некоторых извещений на примере нашего приложения List Application. Подробную информацию об остальных извещениях вы сможете найти в справочной системе SDK.
LVN_GETDISPINFO
Так как при добавлении элементов в поле pszText была записана константа LPSTR_TEXTCALLBACK, для отображения списка орган управления List View "попросит" родительское окно предоставить ему адрес реальной текстовой строки. В результате родительское окно получит извещение с кодом LVN_GETDISPINFO.
Вместе с этим извещением в параметре lParam передается указатель на структуру LV_DISPINFO , которая будет использоваться для передачи информации:
typedef struct tagLV_DISPINFO { NMHDR hdr; // для любого сообщения WM_NOTIFY LV_ITEM item; // информация об элементе списка } LV_DISPINFO;
Структура LV_ITEM была описана выше в разделе "Вставка элементов списка".
При получении извещения LVN_GETDISPINFO родительское окно должно проверить содержимое поля mask структуры item. Маски в этом поле определяют, какая информация должна быть предоставлена при обработке извещения. Возможны следующие значения:
Значение | Запрашиваемая информация |
LVIF_IMAGE | Необходимо заполнить в структуре item поле iImage (номер изображения в списке изображений) |
LVIF_STATE | Поле state (состояние элемента списка) |
LVIF_TEXT | В поле pszText необходимо записать адрес буфера, содержащего строку текста |
LV_DISPINFO * lpLvdi = (LV_DISPINFO *)pnmhdr; APPLINFO * lpAppinfo = (APPLINFO *)(lpLvdi->item.lParam); static char szBuf[20]; ... case LVN_GETDISPINFO: { if(lpLvdi->item.mask & LVIF_TEXT) { switch(lpLvdi->item.iSubItem) { case 0: lpLvdi->item.pszText = lpAppinfo->szAppName; break; case 1: lpLvdi->item.pszText = lpAppinfo->szIconName; break; case 2: itoa(lpAppinfo->iCost, szBuf, 10); lpLvdi->item.pszText = szBuf; break; default: break; } break; } }
Если в поле mask установлен флаг LVIF_TEXT , обработчик извещения анализирует поле iSubItem структуры item.
В том случае, когда содержимое этого поля равно 0, требуется получить текстовую строку названия элемента списка. Адрес этой строки определяется с помощью поля lParam структуры item (соответствующее значение было записано в это поле при добавлении элементов к списку макрокомандой ListView_InsertItem ).
Аналогично обрабатывается извещение для первого дополнительного элемента. Второй дополнительный элемент содержит не текстовое, а числовое значение. Поэтому нам приходится выполнять преобразование при помощи функции itoa.
LVN_COLUMNCLICK
Проверяя работу органа управления List View, вы сможете убедиться в том что с его помощью можно легко выполнить сортировку элементов списка по имени или по содержимому дополнительных элементов. Для этого вам достаточно лишь сделать щелчок мышью по заголовку нужного столбца.
Можно было бы подумать, что орган управления List View выполняет сортировку сам, без дополнительных усилий со стороны программиста, однако это не так. Очевидно, функции окна List View не известно, какой именно алгоритм сортировки должен быть использован в вашем приложении.
Тем не менее вы без особого труда сможете организовать простейшую сортировку текстовых и числовых полей. Для этого вам нужно создать обработчик извещения LVN_COLUMNCLICK и написать свою функцию сравнения двух элементов.
Обработчик извещения LVN_COLUMNCLICK может выглядеть, например, так:
NM_LISTVIEW *lpNm = (NM_LISTVIEW *)pnmhdr; ... case LVN_COLUMNCLICK: { ListView_SortItems(lpNm->hdr.hwndFrom, LVCompareProc, (LPARAM)(lpNm->iSubItem)); return 0L; break; }
Обработка извещения LVN_COLUMNCLICK сводится к вызову единственной макрокоманды ListView_SortItems, посылающей окну органа управления List View сообщение LVM_SORTITEMS :
BOOL ListView_SortItems( HWND hwnd, // идентификатор окна органа List View PFNLVCOMPARE pfnCompare, // указатель на функцию сравнения LPARAM lParamSort); // произвольное значение, которое // передается функции сравнения
В качестве последнего параметра мы передаем макрокоманде номер дополнительного элемента, по которому выполняется сортировка.
При вызове обработчика извещения LVN_COLUMNCLICK в параметре lParam сообщения WM_NOTIFY передается адрес структуры NM_LISTVIEW , определенной следующим образом:
typedef struct tagNM_LISTVIEW { NMHDR hdr; // для любого сообщения WM_NOTIFY int iItem; // номер элемента списка int iSubItem; // номер дополнительного элемента списка UINT uNewState; // новое состояние элемента UINT uOldState; // старое состояние элемента UINT uChanged; // изменившиеся атрибуты элемента POINT ptAction; // позиция, в котором произошло событие LPARAM lParam; // дополнительное значение } NM_LISTVIEW;
Наш обработчик извещения LVN_COLUMNCLICK получает номер дополнительного элемента, по которому выполняется сортировка, из поля iSubItem структуры NM_LISTVIEW.
Функция сравнения должна выглядеть так (имя функции может быть любым):
int CALLBACK LVCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { int iResult; ........ return(iResult); }
Параметры lParam1 и lParam2 указывают на данные, относящиеся к сравниваемым элементам. Параметр lParamSort содержит значение, которое было передано через последний параметр макрокоманде ListView_SortItems. В нашем случае это номер дополнительного элемента списка, по которому выполняется сравнение.
Пример функции сравнения вы найдете в исходных текстах приложения List Application (листинг 3.1).
LVN_BEGINLABELEDIT
LVN_ENDLABELEDIT
Если при создании органа управления List View был указан стиль LVS_EDITLABELS, пользователь сможет редактировать имена элементов списка.
Для этого достаточно выделить нужный элемент и сделать по нему щелчок левой клавишей мыши. Примерно через секунду появится окно редактирования имени "по месту". Такой способ пригоден в любом режиме работы органа управления List View.
Перед началом редактирования имени элемента списка родительское окно получает извещение LVN_BEGINLABELEDIT. Если обработчик этого сообщения возвратит ненулевое значение, редактирование будет заблокировано. Таким образом можно запретить пользователю редактировать названия некоторых элементов списка.
В простейшем случае обработчик извещения LVN_BEGINLABELEDIT может выглядеть так:
case LVN_BEGINLABELEDIT: { return 0L; break; }
Когда пользователь завершил редактирование имени элемента списка, родительскому окну передается извещение LVN_ENDLABELEDIT. При этом параметр lParam сообщения WM_NOTIFY содержит адрес структуры LV_DISPINFO.
Обработчик извещения LVN_ENDLABELEDIT может, например, обновить имя элемента в структуре данных, где это имя хранится.
Если пользователь отменил редактирование, в поле item.iItem будет находиться значение -1. В этом случае обновление выполнять не нужно:
case LVN_ENDLABELEDIT: { if((lpLvdi->item.iItem != -1) && (lpLvdi->item.pszText != NULL)) lstrcpy(lpAppinfo->szAppName, lpLvdi->item.pszText); return 0L; break; }
Выбор из списка
Как правило, список нужен не только для просмотра, но и для того чтобы сделать из него выбор одного или нескольких элементов.
Прежде чем выбрать элементы из списка, пользователь вначале должен их выделить. Один элемент списка можно выделить, щелкнув по нему левой клавишей мыши. Для того чтобы выделить несколько элементов, можно дополнительно воспользоваться клавишами <Shift> и <Control>. В первом случае будет выделен непрерывный диапазон элементов, во втором - любой набор элементов (на обязательно расположенных рядом).
Если окно органа управления List View создано внутри диалоговой панели, после выделения нужных элементов пользователь может нажать кнопку, подтверждающую выбор. В том случае, когда выбирается только один элемент, можно предоставить возможность выбора с помощью двойного щелчка левой клавишей мыши по изображению пиктограммы или по строке названия нужного элемента.
В любом случае у программиста возникает необходимость организовать поиск в списке выделенных элементов. Это можно сделать с помощью макрокоманды ListView_GetNextItem , посылающей окну органа управления List View сообщение LVM_GETNEXTITEM :
int ListView_GetNextItem( HWND hwnd, // идентификатор органа List View int iStart, // номер элемента, с которого начинается поиск UINT flags); // условие поиска
Параметр iStart может быть равен -1. В этом случае поиск продолжается до тех пор, пока не будет найден первый элемент, удовлетворяющий условию поиска. Если же задан конкретный номер элемента, с которого начинается поиск, то этот элемент в поиске не участвует.
Условие поиска задается в виде флагов, определяющих геометрическое расположение элементов, участвующих в поиске, и флагов, определяющих состояние элемента.
В первом наборе определено пять флагов:
Флаг расположения | Расположение элементов, участвующих в поиске |
LVNI_ABOVE | Выше указанного |
LVNI_ALL | Поиск выполняется во всех элементах (это значение используется по умолчанию) |
LVNI_BELOW | Ниже указанного |
LVNI_TOLEFT | Слева от указанного |
LVNI_TORIGHT | Справа от указанного |
Приведем возможные значения флагов состояния:
Флаг состояния | Состояние элемента |
LVNI_CUT | LVIS_CUT отмечен для удаления и последующей вставки |
LVNI_DROPHILITED | LVIS_DROPHILITED выделен как целевой элемент для операции перемещения "drag and drop" |
LVNI_FOCUSED | LVIS_FOCUSED элемент имеет фокус ввода |
LVNI_SELECTED | LVIS_SELECTED элемент выделен |
В нашем приложении List Application мы выполняем выбор элемента двойным щелчком левой клавишей мыши по пиктограмме или строке названия элемента.
Как это можно осуществить?
Извещение NM_DBLCLK
Когда пользователь делает двойной щелчок левой клавишей мыши внутри окна органа управления List View, родительское окно получает сообщение WM_NOTIFY с кодом извещения NM_DBLCLK. Обработчик этого извещения может определить номер выделенного элемента с помощью макрокоманды ListView_GetNextItem , как это сделано в приведенном ниже фрагменте кода:
case NM_DBLCLK: { int index; LV_ITEM lvi; char szBuf[256]; strcpy(szBuf, "Selected item:\n");
index = ListView_GetNextItem(hwndList, -1, LVNI_SELECTED); if(index == -1) return 0;
memset(&lvi, 0, sizeof(lvi)); lvi.mask = LVIF_TEXT;
lvi.iItem = index; lvi.iSubItem = 0; ListView_GetItem(hwndList, &lvi); strcat(szBuf, lvi.pszText);
lvi.iItem = index; lvi.iSubItem = 1; ListView_GetItem(hwndList, &lvi); strcat(szBuf, " : "); strcat(szBuf, lvi.pszText);
lvi.iItem = index; lvi.iSubItem = 2; ListView_GetItem(hwndList, &lvi); strcat(szBuf, " : $"); strcat(szBuf, lvi.pszText);
MessageBox(hWnd, szBuf, szAppName, MB_OK); return 0L; break; }
Если пользователь сделал двойной щелчок там, где нет пиктограммы или строки названия элемента, макрокоманда ListView_GetNextItem вернет значение -1. В этом случае обработчик извещения NM_DBLCLK завершает свою работу, так как пользователь не выбрал ни одного элемента.
Если же выбор сделан, обработчик извещения получает текстовую информацию о выделенном элементе списка с помощью макрокоманды ListView_GetItem. Эта макрокоманда заполняет поля структуры LV_ITEM, отмеченные в поле mask. Макрокоманда вызывается несколько раз - для основного и всех дополнительных элементов.
Операционная система Windows 95 для программиста
Орган управления Animation очень прост в использовании и может увеличить привлекательность приложения. На рис. 1.5 в первой главе показано, как с помощью органа управления Animation можно "оживить" процедуру копирования файла. В нашем приложении Compact Disk Player, к которому мы скоро перейдем, этот орган управления используется для изображения вращающегося компакт диска. Диск вращается только тогда, когда выполняется проигрывание дорожки.
Принцип действия органа управления Animation заключается в проигрывании AVI -файла, содержащего видеоизображение. Вы можете создать небольшой мультфильм из отдельных BMP-файлов с помощью приложения VidEdit, которое входит в состав Microsoft Video for Windows 3.1 версии 1.1. Соответствующая процедура описана в 15 томе "Библиотеки системного программиста", который называется "Мультимедиа для Windows".
Учтите, что для сжатия вы можете использовать только алгоритм RLE (можно также использовать несжатые файлы), причем AVI-файл не должен содержать звуковой информации. Если же вам нужно проигрывать видеоклип с звуковым сопровождением, да и еще сжатый более эффективно, лучше всего использовать орган управления MCIWnd , который был подробно описан в 15 томе нашей библиотеки.
Извещения от органа управления Animation
Орган управления может посылать в родительское окно извещения в форме сообщения WM_COMMAND . Это извещения ACN_START и ACN_STOP .
Первое из них сообщает о том, что процесс проигрывания видеоролика начался, а второй - что этот процесс завершился.
Сообщения для органа управления Animation
Для органа управления Animation определены макрокоманды, посылающие сообщения ACM_OPEN, ACM_PLAY и ACM_STOP. Все они возвращают значение TRUE в случае успешного завершения и FALSE при ошибке.
Открытие видеоролика
BOOL Animate_Open (hwnd, lpszName);
Через параметр hwnd макрокоманде передается идентификатор органа управления Animation.
Параметр lpszName должен содержать указатель на текстовый буфер, в который записан путь к AVI-файлу или идентификатор ресурса AVI, созданный с помощью макрокоманды MAKEINTRESOURCE.
Закрытие видеоролика
BOOL Animate_Close (hwnd);
Параметр hwnd должен содержать идентификатор органа управления Animation.
Запуск проигрывания
BOOL Animate_Play (hwnd, wFrom, wTo, cRepeat);
Эта макрокоманда запускает проигрывание открытого видеоролика для органа управления Animation с идентификатором hwnd.
Параметры wFrom и wTo указывают, соответственно, номера начального и конечного кадра в видеоролике. Эти номера не должны превышать значения 65536, причем нулевое число означает начало видеоролика.
Параметр cRepeat определяет количество повторных проигрываний, которые необходимо выполнить. Если в этом параметре указано значение -1, проигрывание выполняется бесконечное число раз.
Останов проигрывания
BOOL Animate_Stop (hwnd);
Макрокоманда Animate_Stop выполняет останов запущенного ранее проигрывания видеоролика.
Позиционирование
BOOL Animate_Seek (hwnd, wFrame);
С помощью макрокоманды Animate_Seek вы можете отобразить кадр открытого видеоролика с номером wFrame.
Создание органа управления Animation
Если вы желаете создать орган управления Animation в обычном окне, то это можно сделать с помощью макрокоманды Animate_Create :
HWND Animate_Create( HWND hwndP, // идентификатор родительского окна UINT id, // идентификатор окна органа Animation DWORD dwStyle, // стиль окна органа Animation HINSTANCE hInstance; // идентификатор приложения );
Эта макрокоманда создает орган управления Animation, вызывая функцию CreateWindow и указывая ей предопределенный класс окна ANIMATE_CLASS .
В параметре dwStyle вы можете указать один из следующих стилей:
Стиль | Описание |
ACS_AUTOPLAY | Проигрывание видеоизображения начинается автоматически сразу после открытия соответствующего AVI-файла |
ACS_CENTER | Видеоизображение будет центрировано в окне органа управления |
ACS_TRANSPARENT | Изображение рисуется в прозрачном режиме |
В том случае когда орган управления Animation должен быть расположен в диалоговой панели, его необходимо переместить туда из палитры редактора диалоговых панелей. Если же вы пользуетесь системой разработки Microsoft Visual C++ версии 2.0, вам придется отредактировать файл ресурсов самостоятельно. Для этого откройте его в текстовом режиме и вставьте следующие строки:
CONTROL "Animate",IDC_ANIMATE, "SysAnimate32", WS_BORDER | WS_TABSTOP | 0x1, 219, 34, 33, 33
Последние четыре числа определяют, соответственно расположение и размеры окна органа управления Animation.
Дополнительно к стилям WS_BORDER и WS_TABSTOP могут быть добавлены описанные выше специфические стили органа управления Animation, определенные следующим образом:
#define ACS_CENTER 0x0001 #define ACS_TRANSPARENT 0x0002 #define ACS_AUTOPLAY 0x0004
Операционная система Windows 95 для программиста
Последний орган управления, который мы рассмотрим в этой книге, предназначен для ввода комбинации клавиш активизации приложения. Однако прежде мы должны немного рассказать о том, что это такое.
Пользователь может определить комбинацию клавиш для быстрого доступа к какой-либо часто выполняемой операции. Такую комбинацию клавиш мы будем называть комбинацией клавиш активизации или просто клавишами активизации .
В операционной системе Microsoft Windows 95 вы можете установить так называемую глобальную комбинацию клавиш для активизации при помощи сообщения WM_SETHOTKEY , послав его главному окну приложения. Заметим, что сообщение WM_SETHOTKEY не имеет никакого отношения к органу управления Hot Key .
Параметр lParam этого сообщения должен быть равен нулю. Клавиши активизации задаются параметром lParam следующим образом:
wParam = (WPARAM)MAKEWORD (vkey, modifiers);
Здесь vkey определяет виртуальный код клавиши. Список виртуальных кодов для различных клавиш вы найдете в пятой главе 12 тома "Библиотеки системного программиста" (стр. 158).
Параметр modifiers определяет клавиши модификации, такие как Ctrl и Alt, которые нужно нажимать вместе с клавишей, заданной параметром vkey для активизации. Параметр modifiers нужно задавать как комбинацию следующих значений:
Значение | Клавиша модификации |
HOTKEYF_ALT | Alt |
HOTKEYF_CONTROL | Ctrl |
HOTKEYF_EXT | Дополнительные клавиши, такие как правая клавиша Ctrl или правая клавиша Alt. Дополнительные клавиши есть не на всех клавиатурах |
HOTKEYF_SHIFT | Shift |
Ниже мы показали, как задать комбинацию Ctrl+Alt+V в качестве клавиш активизации:
SendMessage(hWnd, WM_SETHOTKEY, (WPARAM)MAKEWORD('V', HOTKEYF_ALT | HOTKEYF_CONTROL), 0);
Что же произойдет, когда пользователь нажмет клавиши активизации, заданные таким образом?
Главное окно приложение будет выдвинуто на первый план, а его функция получит сообщение WM_SYSCOMMAND с кодом команды SC_HOTKEY . При этом обработчик сообщения WM_SYSCOMMAND может выполнить какие-либо действия, например, послать главному окну приложения другое сообщение.
Ниже мы привели исходный текст обработчика сообщения WM_SYSCOMMAND из приложения UpDown:
void WndProc_OnSysCommand(HWND hwnd, UINT cmd, int x, int y) { if(cmd == SC_HOTKEY) { SendMessage(hwndMainWindow, WM_COMMAND, (WPARAM)MAKELONG(ID_FILE_OPTIONS, 0), 0L); return 0; } return FORWARD_WM_SYSCOMMAND (hwnd,cmd,x,y,DefWindowProc); }
Здесь обработчик посылает главному окну сообщение WM_COMMAND, имитируя выбор из меню File строки Options.
С помощью сообщения WM_SETHOTKEY пользователь может назначить для приложения только одну комбинацию клавиш активизации.
Приложение может определить, была ли назначена окну комбинация клавиш активизации и если была, то какая именно. Для этого достаточно послать окну сообщение WM_GETHOTKEY , например, так:
wHotKey = (WORD)SendMessage(hwndMainWindow,WM_GETHOTKEY,0,0);
Если комбинация клавиш активизации не была назначена, возвращается значение NULL, а если была, то возвращается значение, которое можно использовать в качестве параметра wParam сообщения WM_SETHOTKEY.
Итак, для того чтобы определить комбинацию клавиш активизации, можно воспользоваться сообщением WM_SETHOTKEY. Что же касается подготовки значения wParam для этого сообщения, то это можно сделать с помощью органа управления Hot Key, к описанию которого мы и перейдем.
Внешне орган управления Hot Key похож на однострочный текстовый редактор (рис. 7.8).
Окно органа управления Hot Key
Когда это окно получает фокус ввода, пользователь может нажимать комбинацию клавиш активизации, которая тотчас же будет в нем отображаться. Таким образом, пользователь сразу видит, какая комбинация клавиш выбрана.
Послав окну органа управления Hot Key сообщение HKM_GETHOTKEY , приложение может определить выбранную комбинацию клавиш и передать значение, возвращенное функцией SendMessage как параметр wParam сообщению WM_SETHOTKEY.
Этот нехитрый механизм позволяет легко организовать процедуру определения пользователем комбинации клавиш активизации.
Сообщения для органа управления Hot Key
Инициализацию органа управления Hot Key выполняют с помощью сообщения HKM_SETHOTKEY . Параметр lParam должен быть равен нулю, а параметр wParam следует определить следующим образом:
wParam = MAKEWORD (vkey, modifiers);
Параметры vkey и modifiers имеют то же назначение, что и в сообщении WM_SETHOTKEY.
Кроме этого, при инициализации с помощью сообщения HKM_SETRULES можно указать запрещенные комбинации клавиш и клавиши, которые используются по умолчанию.
Параметры сообщения HKM_SETRULES приведены ниже:
wParam = (WPARAM) fwInvalid; lParam = MAKELPARAM (modifiers, 0);
Параметр fwInvalid указывает запрещенные клавиши и может быть комбинацией следующих значений:
Значение | Запрещенные клавиши |
HKCOMB_A | <Alt> |
HKCOMB_C | <Ctrl> |
HKCOMB_CA | <Ctrl + Alt> |
HKCOMB_NONE | Запрещается использовать клавиши без модификаторов, т. е. без клавиш <Alt>, <Ctrl> или <Shift> |
HKCOMB_S | <Shift> |
HKCOMB_SA | <Shift + Alt> |
HKCOMB_SC | <Shift + Ctrl> |
HKCOMB_SCA | <Shift + Ctrl + Alt> |
Когда пользователь пытается определить запрещенную комбинацию клавиш, вместо нее будет выбрана та, что указана параметром modifiers.
Создание органа управления Hot Key
Вы можете создать орган управления Hot Key функцией CreateWindowEx на базе предопределенного класса окна HOTKEY_CLASS , либо добавить его к диалоговой панели, выбрав соответствующую пиктограмму из палитры редактора диалога. Например:
hwndHotKey = CreateWindowEx( 0, HOTKEY_CLASS, "", WS_CHILD | WS_VISIBLE, 30, 50, 100, 32, hWnd, NULL, hInst, NULL);
В приложении UpDown мы выбрали второй способ.
Операционная система Windows 95 для программиста
Орган управления Progressbar ничем не управляет, а служит только для отображения как линейный индикатор (рис. 7.5).
Орган управления Progressbar
Он очень прост в использовании, так как не посылает извещений и воспринимает небольшое количество сообщений.
Сообщения для органа управления Progressbar
Для органа управления Progressbar определены пять сообщений:
Сообщение | Описание |
PBM_DELTAPOS | Продвижение заполняющей полосы в окне индикатора на заданное расстояние, определенное сообщением PBM_SETSTEP |
PBM_SETPOS | Установка текущего положения заполняющей полосы и перерисовка индикатора |
PBM_SETRANGE | Установка минимальной и максимальной позиции для органа управления Progressbar |
PBM_SETSTEP | Установка шага продвижения при поступлении сообщения PBM_STEPIT (по умолчанию шаг равен 10) |
PBM_STEPIT | Продвижение заполняющей полосы в окне индикатора на величину, определенную сообщением PBM_SETSTEP |
При инициализации необходимо установить диапазон изменений значений и шаг продвижения.
Первая задача решается с помощью сообщения PBM_SETRANGE:
SendMessage(hProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, nTrackCnt));
Параметр wParam этого сообщения должен быть равен нулю. Значение MAKELPARAM(min, max), записанное в lParam, определяет минимальное min и максимальное max значения позиции для органа управления Progressbar.
Шаг продвижения устанавливается в параметре wParam сообщения PBM_SETSTEP (параметр lParam должен быть равен нулю):
SendMessage(hProgressBar, PBM_SETSTEP, 1, 0);
Если вам нужно установить новое текущее положение заполняющей полосы, это можно сделать при помощи сообщения PBM_SETPOS, указав положение в параметре wParam:
SendMessage(hProgressBar, PBM_SETPOS, nCurTrack, 0);
При этом параметр lParam должен быть равен нулю.
Сообщение PBM_STEPIT не имеет параметров и может быть использовано для продвижения полосы следующим образом:
SendMessage(hProgressBar, PBM_STEPIT, 0, 0);
Если необходимо продвинуть полосу на заданное расстояние, используйте сообщение PBM_DELTAPOS:
SendMessage(hProgressBar, PBM_DELTAPOS, nDelta, 0);
Расстояние должно быть указано в параметре wParam. Параметр lParam должен быть равен нулю.
Создание органа управления Progressbar
Так же как и Trackbar, вы можете создать орган управления Progressbar при помощи функции CreateWindowEx , указав ей класс окна PROGRESS_CLASS .
Кроме того, вы можете использовать Progressbar в диалоговых панелях аналогично органу управления Trackbar. Для того чтобы в палитре органов управления редактора диалоговых панелей системы разработки Microsoft Visual C++ версии 2.0 появилась пиктограмма Progressbar, вы должны внести описанные ранее изменения в регистрационную базу данных.
Для органа управления Progressbar при инициализации необходимо задать диапазон изменения значений и начальное значение (в пределах от 0 до 65535).
Операционная система Windows 95 для программиста
Процедура создания органа управления Statusbar намного проще процедуры создания Toolbar . Вы можете создать Statusbar либо с помощью функции CreateWindowEx на основе класса окна STATUSCLASSNAME , либо воспользоваться специально предназначенной для этого функцией CreateStatusWindow.
В первом случае вы можете создать Statusbar, например, так:
hwndSb = CreateWindowEx( 0L, // расширенный стиль окна STATUSCLASSNAME, // класс окна для Statusbar "", // заголовок окна отсутствует WS_CHILD | WS_BORDER | // стиль окна WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0, // координаты, ширина, высота hWnd, // идентификатор родительского окна (HMENU)IDS_STATUSBAR, // идентификатор Statusbar hInst, // идентификатор приложения NULL ); // доп. данные для окна
Обратите внимание на стиль SBARS_SIZEGRIP . Если Statusbar имеет этот стиль, его правый нижний угол принимает вид, показанный на рис. 2.2.
Орган управления Toolbar , имеющий стиль SBARS_SIZEGRIP
Во втором случае вы должны вызвать функцию CreateStatusWindow , прототип которой приведен ниже:
HWND CreateStatusWindow( LONG style, // стиль окна LPCTSTR lpszText, // текст для первой области Statusbar HWND hwndParent, // идентификатор родительского окна UINT wID // идентификатор Statusbar );
Обычно создание органов управления Statusbar и Toolbar выполняется приложением при обработке функцией главного окна сообщения WM_CREATE.
При создании Statusbar вы можете также использовать стиль CCS_TOP . При этом окно Statusbar будет расположено в верхней части родительского окна. Очевидно, этот стиль нельзя комбинировать со стилем SBARS_SIZEGRIP , так как во-первых, такой орган управления будет выглядеть очень странно, а во-вторых, он не будет работать так, как этого ожидает пользователь.
Определение режима работы Statusbar
Орган управления Statusbar может работать в двух режимах - стандартном и упрощенном.
В первом режиме приложение может разделить окно Statusbar на несколько областей для раздельного вывода в эти области текста или графической информации.
В упрощенном режиме приложение может выводить в окно Statusbar только текстовую информацию, причем разделение этого окна на несколько областей невозможно.
Орган управления Statusbar переводится из стандартного режима в упрощенный и обратно при помощи сообщения SB_SIMPLE , которое мы рассмотрим немного позже. В процессе переключения содержимое области стандартного режима не исчезает, так как соответствующие данных хранятся в разных местах для разных режимов.
Разделение Statusbar на области
Для того чтобы разделить Statusbar на несколько областей достаточно сразу после создания послать ему сообщение SB_SETPARTS :
SendMessage(hwndSb, SB_SETPARTS, 3, (LPARAM)ptWidth);
Через параметр wParam передается количество областей (в нашем примере создается три области).
Параметр lParam должен содержать адрес массива ширин областей Toolbar :
int ptWidth[3]; // таблица ширин для Statusbar
Количество элементов в массиве должно быть равно количеству областей, на которые делится Statusbar.
Однако это еще не все.
При обработке сообщения WM_SIZE вы должны выполнить повторное определение областей:
void WndProc_OnSize(HWND hwnd, UINT state, int cx, int cy) { SendMessage(hwndTb, WM_SIZE, cx, cy); SendMessage(hwndSb, WM_SIZE, cx, cy); ptWidth[0] = cx/2; ptWidth[1] = cx/2 + cx/4; ptWidth[2] = -1; SendMessage(hwndSb, SB_SETPARTS, 3, (LPARAM)ptWidth); return FORWARD_WM_SIZE(hwnd, state, cx, cy, DefWindowProc); }
Когда обработчик сообщения WM_SIZE передает сообщение WM_SIZE органам управления Toolbar и Statusbar, они устанавливают размеры своих окон.
Затем необходимо подготовить массив ширин областей Statusbar.
В элемент массива вы можете записать либо позицию правой границы области от левого края окна Statusbar, либо значение -1. В последнем случае правая граница области простирается до правого края окна Statusbar.
Рисование графического изображения в области Statusbar
Если в сообщении SB_SETTEXT указать константу SBT_OWNERDRAW , родительское окно, создавшее Statusbar, может нарисовать в соответствующей области любое изображение или написать текст любым шрифтом, используя всю мощь графического интерфейса GDI.
Ниже мы привели фрагмент кода, который загружает из ресурсов приложения битовое изображение и передает его идентификатор через параметр lParam сообщения SB_SETTEXT . При этом номер области, в которой будет нарисовано это изображения, комбинируется с константой SBT_OWNERDRAW :
hSbLogoBmp = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SBLOGO)); SendMessage(hwndSb, SB_SETTEXT, 2 | SBT_OWNERDRAW, (LPARAM)hSbLogoBmp);
Когда область Statusbar должны быть перерисована, родительское окно получает сообщение WM_DRAWITEM . Параметр wParam этого сообщения содержит идентификатор органа управления, которое послало сообщение, или ноль, если сообщение пришло от меню. В нашем случае через wParam будет передаваться идентификатор органа управления Statusbar.
Параметр lParam содержит указатель на структуру типа DRAWITEMSTRUCT (описание полей приведено для Statusbar):
typedef struct tagDRAWITEMSTRUCT { UINT CtlType; // не используется UINT CtlID; // идентификатор окна Statusbar UINT itemID; // номер области, которая будет перерисована UINT itemAction; // не используется UINT itemState; // не используется HWND hwndItem; // идентификатор окна Statusbar HDC hDC; // идентификатор контекста отобаржения RECT rcItem; // координаты области DWORD itemData; // значение lParam сообщения SB_SETTEXT } DRAWITEMSTRUCT;
Обработчик сообщения WM_DRAWITEM должен проверить содержимое поля CtlID - в этом поле должен находится идентификатор Statusbar. Далее обработчик может выполнить рисование, пользуясь контекстом отображения hDC в области, координаты которой передаются через поле rcItem.
При этом обработчик сообщения WM_DRAWITEM может воспользоваться содержимым поля itemData, которое равно значению параметра lParam сообщения SB_SETTEXT. Через этот параметр можно передать, например, идентификатор изображения, которое должно быть нарисовано в области Statusbar, идентификатор шрифта, которым должен быть написан текст в этой области или любая другая информация.
Ниже мы привели фрагмент исходного текста приложения Smart Application, который рисует в самой правой области Statusbar небольшое графическое изображение:
void WndProc_OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem) { if(lpDrawItem->CtlID == IDS_STATUSBAR) { LPDRAWITEMSTRUCT lpDis; HDC hdcMem; HBITMAP hbmOld; BITMAP bm; lpDis = (LPDRAWITEMSTRUCT)lpDrawItem; hdcMem = CreateCompatibleDC(lpDis->hDC); hbmOld = SelectObject(hdcMem, hSbLogoBmp); GetObject(hSbLogoBmp, sizeof(bm), &bm); BitBlt(lpDis->hDC, lpDis->rcItem.left, lpDis->rcItem.top, bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY); SelectObject(hdcMem, hbmOld); DeleteDC(hdcMem); } return FORWARD_WM_DRAWITEM(hwnd, lpDrawItem, DefWindowProc); }
Если вы незнакомы с понятиями контекста отображения, не умеете работать с битовыми графическими изображениями или никогда не пользовались функцией BitBlt, мы рекомендуем вам обратиться к 14 тому "Библиотеки системного программиста", который называется "Графический интерфейс GDI в Microsoft Windows".
Если вам нужно нарисовать непрямоугольное или частично прозрачное изображение, недостаточно выбрать в качестве цвета фона цвет окна Statusbar, так как пользователь может легко изменить цветовую гамму оболочки Microsoft Windows95. В этом случае мы рекомендуем вам использовать более сложные процедуры рисования с использованием растровых операций ROP . Всю необходимую для этого информацию, а также пример приложения (которое называется BMPLOGO) вы найдете в 14 томе "Библиотеки системного программиста".
Сообщения для Statusbar
В этом разделе мы перечислим и кратко опишем сообщения, специально предназначенные для работы с органом управления Statusbar. Полную информацию вы сможете найти в справочной системе SDK.
SB_SETMINHEIGHT
Установка минимальной высоты области окна Statusbar, которая используется для отображения текста или рисования изображений.
wParam = (WPARAM) minHeight; // минимальная высота в пикселах
Значение параметра lParam должно быть равно нулю.
SB_SETTEXT
Запись текста в заданную область окна Statusbar.
wParam = (WPARAM) iPart | uType; // область и тип отображения lParam = (LPARAM) (LPSTR) szText; // адрес строки
Через параметр iPart передается номер области. Этот номер может комбинироваться при помощи логической операции ИЛИ с одной из нескольких констант, описанной нами ранее в разделе " Запись текста в область Statusbar".
Через параметр szText передается адрес строки текста. Если используется константа SBT_OWNERDRAW, параметр сообщения lParam служит для передачи произвольного 32-разрядного значения, например, идентификатора битового изображения.
SB_SETPARTS
Установка количества областей и определение правой границы каждой области.
wParam = (WPARAM) nParts; // количество областей lParam = (LPARAM) (LPINT) aWidths; // границы
Это сообщение мы подробно описали в разделе " Разделение Statusbar на области".
SB_SIMPLE
Переключение органа Statusbar из стандартного режима в упрощенный и обратно.
wParam = (WPARAM) (BOOL); // флаг режима
Параметр lParam должен быть равен нулю.
Если флаг fSimple принимает значение TRUE, Statusbar переключается в упрощенный режим. если FALSE - возвращается в стандартный режим.
Отметим, что в упрощенном режиме родительское окно не может рисовать в единственной области окна Statusbar. Поэтому упрощенный режим пригоден только для отображения текстовых сообщений.
SB_GETBORDERS
Определение ширины горизонтальной и вертикальной рамки окна Statusbar.
lParam = (LPARAM) (LPINT) aBorders; // адрес массива
Параметр wParam должен быть равен нулю.
Перед тем как послать окну Statusbar сообщение SB_GETBORDERS, вы должны подготовить массив из трех переменных типа int. В первый элемент массива будет записана ширина горизонтальной рамки, во второй - ширина вертикальной рамки, и в третий - ширина рамки между прямоугольниками.
SB_GETPARTS
Определение количества областей в окне состояния и координат правых границ этих областей.
wParam = (WPARAM) nParts; // количество областей lParam = (LPARAM) (LPINT) aRightCoord; // массив координат
Через параметр nParts передается количество областей, информация о координатах правых границ которых записывается в массив aRightCoord.
Функция SendMessage, пославшая сообщение SB_GETPARTS, возвращает количество существующих в окне Statusbar областей или нуль при ошибке.
SB_GETRECT
Определение границ заданной области в окне Statusbar.
wParam = (WPARAM) iPart; // номер области lParam = (LPARAM) (LPRECT) lprc; // границы области
Границы области, номер которой задан через параметр iPart, передается приложению через структуру типа RECT. Адрес этой структуры должен быть указан в параметре lprc перед посылкой сообщения.
SB_GETTEXT
Извлечение текста из заданной области Statusbar.
wParam = (WPARAM) iPart; // номер области lParam = (LPARAM) (LPSTR) szText; // адрес буфера для текста
Функция SendMesage возвращает в младшем 16-разрядном слове длину текста, в старшем, константу 0, SBT_NOBORDERS, SBT_POPOUT или SBT_RTLREADING. Если родительское окно само рисует внутри области при обработке сообщения WM_DRAWITEM, возвращается 32-разрядное значение, которое было передано при посылке сообщения SB_SETTEXT.
Перед тем как извлекать текст из области Statusbar, необходимо определить размер буфера для записи соответствующей текстовой строки. Это можно сделать при помощи сообщения SB_GETTEXTLENGTH, описанного ниже.
SB_GETTEXTLENGTH
Определение длины строки для заданной области окна Statusbar.
wParam = (WPARAM) iPart; // номер области
Значение параметра lParam должно быть равно нулю.
Функция SendMesage возвращает точно такое же значение, как и для сообщения SB_GETTEXT.
Запись текста в область Statusbar
Для записи текста в область Statusbar необходимо использовать сообщение SB_SETTEXT :
SendMessage(hwndSb,SB_SETTEXT,0, (LPARAM)"Statusbar, Part 1"); SendMessage(hwndSb, SB_SETTEXT,1 | SBT_NOBORDERS, (LPARAM)"");
Через параметр wParam передается номер области, который может быть скомбинирован при помощи логической операции ИЛИ с одной из констант, определяющих внешний вид области:
Константа | Описание |
SBT_NOBORDERS | Текст рисуется без рамки |
SBT_POPOUT | Текст рисуется с рамкой, которая выглядит приподнятой над поверхностью окна Statusbar |
SBT_RTLREADING | Текст отображается справа налево (такой способ отображения используется, например, в арабских странах) |
SBT_OWNERDRAW | Текст (или графическое изображение) рисуется родительским окном во время обработки сообщения WM_DRAWITEM |
Через параметр lParam передается указатель на строку текста, которая должна быть записана в область.
Текстовая строка может быть пустой. Если необходимо выполнить выравнивание текста по центру или по правому краю, вы можете включить в текстовую строку символы табуляции \t. Текст, расположенный после первого символа табуляции, выравнивается по центру, после второго - по правому краю области.
Операционная система Windows 95 для программиста
Для начала займемся изображениями, которые нарисованы на кнопках Toolbar . Затем мы расскажем вам о том, как создать окно органа управления Toolbar.
Обработка извещений от Toolbar
Орган управления Toolbar посылает в родительское окно сообщения WM_COMMAND и WM_NOTIFY. О том, как обрабатывать первое из них, вы знаете из предыдущих томов "Библиотеки системного программиста", посвященных программированию для Microsoft Windows. Остановимся на обработке нового для вас сообщения WM_NOTIFY .
Через параметр wParam этого сообщения передается идентификатор органа управления. Если извещение пришло от Toolbar , то это должен быть идентификатор Toolbar.
Параметр lParam содержит указатель на структуру типа NMHDR или на структуру большего размера, содержащую в своем начале структуру NMHDR :
typedef struct tagNMHDR { HWND hwndFrom; UINT idFrom; UINT code; } NMHDR;
В этой структуре поле hwndFrom содержит идентификатор окна, приславшего сообщение, поле idFrom - идентификатор органа управления, приславшего сообщение, а поле code - код извещения.
Органы управления могут присылать следующие коды извещения:
Код извещения | Описание |
NM_CLICK | Пользователь сделал щелчок левой клавишей мыши внутри органа управления |
NM_DBLCLICK | Пользователь сделал двойной щелчок левой клавишей мыши внутри органа управления |
NM_RCLICK | Пользователь сделал щелчок правой клавишей мыши внутри органа управления |
NM_RDBLCLICK | Пользователь сделал двойной щелчок правой клавишей мыши внутри органа управления |
NM_RETURN | Когда орган управления имел фокус ввода, пользователь нажал клавишу <Enter> |
NM_KILLFOCUS | Орган управления потерял фокус ввода |
NM_SETFOCUS | Орган управления получил фокус ввода |
Перечисленные выше коды извещений используются всеми стандартными органами управления. Что же касается органа управления Toolbar , до для него имеются некоторые добавления.
Во-первых, параметр lParam сообщения WM_NOTIFY содержит указатель на структуру TBNOTIFY (содержащую в самом начале только что описанную структуру NMHDR ):
typedef struct { NMHDR hdr; int iItem; TBBUTTON tbButton; int cchText; LPTSTR pszText; } TBNOTIFY, FAR * LPTBNOTIFY;
В этой структуре поле iItem содержит номер кнопки, от которой пришло извещение (напомним, что нумерация кнопок начинается с нуля).
Структура tbButton типа TBBUTTON содержит описание кнопки. Мы уже рассказывали вам об этой структуре.
В поле cchText находится длина текстовой строки, соответствующей кнопке. Адрес этой строки передается через параметр pszText.
Во-вторых, для органа управления Toolbar определены дополнительные коды извещений:
Код извещения Toolbar | Описание |
TBN_BEGINADJUST | Пользователь приступил к настройке Toolbar |
TBN_BEGINDRAG | Пользователь начал передвигать кнопку по поверхности Toolbar |
TBN_ENDADJUST | Пользователь закончил настройку Toolbar |
TBN_ENDDRAG | Пользователь закончил передвижение кнопки по поверхности Toolbar |
TBN_CUSTHELP | Пользователь нажал кнопку "Help" в диалоговой панели, которая была вызвана для настройки Toolbar . Позже мы расскажем об этой диалоговой панели |
TBN_GETBUTTONINFO | Это извещение окно Toolbar посылает в том случае, если ему нужна информация об одной из кнопок |
TBN_QUERYDELETE | С помощью этого извещения окно Toolbar запрашивает возможность удаления кнопки в процессе настройки |
TBN_QUERYINSERT | С помощью этого извещения окно Toolbar запрашивает возможность вставки новой кнопки слева от указанной в процессе настройки |
TBN_RESET | Пользователь нажал кнопку "Reset" в диалоговой панели, которая была вызвана для настройки Toolbar |
TBN_TOOLBARCHANGE | Пользователь изменил внешний вид Toolbar в результате выполнения настройки |
LRESULT WndProc_OnNotify(HWND hWnd, int idFrom, NMHDR* pnmhdr) { LPTOOLTIPTEXT lpToolTipText; LPTBNOTIFY lptbn; int nItem; static CHAR szBuf[128];
switch(pnmhdr->code) { case TTN_NEEDTEXT: lpToolTipText = (LPTOOLTIPTEXT)pnmhdr; LoadString(hInst, lpToolTipText->hdr.idFrom, szBuf, sizeof(szBuf)); lpToolTipText->lpszText = szBuf; break;
case TBN_GETBUTTONINFO: lptbn = (LPTBNOTIFY)pnmhdr; nItem = lptbn->iItem; lptbn->tbButton.iBitmap = tbButtons[nItem].iBitmap; lptbn->tbButton.idCommand = tbButtons[nItem].idCommand; lptbn->tbButton.fsState = tbButtons[nItem].fsState; lptbn->tbButton.fsStyle = tbButtons[nItem].fsStyle; lptbn->tbButton.dwData = tbButtons[nItem].dwData; lptbn->tbButton.iString = tbButtons[nItem].iString;
return((nItem < sizeof(tbButtons)/sizeof(tbButtons[0]))? TRUE : FALSE); break;
case TBN_QUERYDELETE: lptbn = (LPTBNOTIFY)pnmhdr; nItem = lptbn->iItem; return (nItem == 0)? FALSE : TRUE; break;
case TBN_QUERYINSERT: lptbn = (LPTBNOTIFY)pnmhdr; nItem = lptbn->iItem; return (nItem == 0)? FALSE : TRUE; break;
case TBN_TOOLBARCHANGE: SendMessage(hwndTb, TB_AUTOSIZE, 0L, 0L); return TRUE; break;
default: break; } return FALSE; }
Рассмотрим особенности обработки отдельных извещений.
TTN_NEEDTEXT
Если при создании Toolbar был указан стиль TBSTYLE_TOOLTIP , пользователь может получить краткую справку о назначении любой кнопки Toolbar, просто установив на нее курсор мыши и подождав примерно одну секунду. При этом рядом с кнопкой появляется небольшое временное окно с описанием назначения кнопки.
Для того чтобы использовать эту возможность, в файле ресурсов приложения вы должны подготовить таблицу строк, содержащих краткое описание назначения кнопок. Лучше подготовить эту таблицу для всех строк меню, а не только для тех, которые дублируются кнопками Toolbar .
Вот пример такой таблицы (мы привели сокращенный вариант из приложения Smart Application):
STRINGTABLE DISCARDABLE BEGIN ID_FILE_NEW "Creates a new document" ID_FILE_OPEN "Open an existing document" ID_FILE_CLOSE "Closes the active document" ID_FILE_SAVE "Save the active document" ID_FILE_PRINT "Prints the active document" END STRINGTABLE DISCARDABLE BEGIN ID_FILE_EXIT "Exit application" ID_FILE_SAVEAS "Saves the active document under" " a different name" ID_HELP_ABOUT "Displays information about application" END
Как вы увидите в дальнейшем, эта таблица пригодится нам для органа управления Statusbar.
Когда пользователь устанавливает курсор мыши на кнопку Toolbar и оставляет его в покое, окно, создавшее Toolbar, получает извещение TTN_NEEDTEXT.
Обработчик извещения TTN_NEEDTEXT должен извлечь идентификатор кнопки, загрузить из ресурсов приложения соответствующую текстовую строку и записать ее адрес в поле lpszText:
case TTN_NEEDTEXT: lpToolTipText = (LPTOOLTIPTEXT)pnmhdr; LoadString(hInst, lpToolTipText->hdr.idFrom, szBuf, sizeof(szBuf)); lpToolTipText->lpszText = szBuf; break;
Вот и все, что нужно для того чтобы предоставить пользователю возможность определять назначение кнопок Toolbar с помощью органа управления Tool Tip.
TBN_GETBUTTONINFO
Это извещение преследует двоякую цель. Во-первых, с его помощью родительское окно может узнать, что пользователь внес изменения в Toolbar . Во-вторых, при помощи этого извещения функция окна органа управления Toolbar может получить информацию о любой кнопке Toolbar (если, конечно, приложение предоставит такую информацию).
Следующий фрагмент кода возвращает функции окна Toolbar сведения о кнопке, номер которой передается вместе с извещением:
case TBN_GETBUTTONINFO: lptbn = (LPTBNOTIFY)pnmhdr; nItem = lptbn->iItem; lptbn->tbButton.iBitmap = [nItem].iBitmap; lptbn->tbButton.idCommand = tbButtons[nItem].idCommand; lptbn->tbButton.fsState = tbButtons[nItem].fsState; lptbn->tbButton.fsStyle = tbButtons[nItem].fsStyle; lptbn->tbButton.dwData = tbButtons[nItem].dwData; lptbn->tbButton.iString = tbButtons[nItem].iString; return((nItem < sizeof(tbButtons)/sizeof(tbButtons[0]))? TRUE : FALSE); break;
Номер кнопки берется из поля iItem описанной ранее структуры TBNOTIFY, а информация о кнопке - из структуры tbButtons типа TBBUTTON, которая была подготовлена еще до создания Toolbar .
Обратите внимание на то, что обработчик извещения TBN_GETBUTTONINFO возвращает TRUE, если номер кнопки не вышел за пределы возможных значений индекса массива структур tbButtons. В противном случае возвращается значение FALSE.
Когда пользователь сделает двойной щелчок левой клавишей мыши по окну Toolbar для того чтобы вызвать диалоговую панель настройки этого органа управления, функция окна Toolbar будет присылать извещения TBN_GETBUTTONINFO до тех пор, пока соответствующий обработчик не вернет значение FALSE. При этом номер кнопки будет все время возрастать на единицу.
В документации SDK сказано, что обработчик извещения TBN_GETBUTTONINFO должен возвращать TRUE, если он предоставил информацию о нужной кнопке и FALSE в противном случае. Вы, конечно, можете возвращать значение FALSE для любого номера кнопки, не предоставляя никакой информации, однако при этом диалоговая панель настройки Toolbar будет работать неправильно. В частности, с ее помощью вы сможете удалить любую кнопку, но вернуть ее обратно будет уже невозможно.
TBN_QUERYDELETE
В процессе настройки органа управления Toolbar пользователь может удалить ненужные ему кнопки. Однако для некоторых кнопок вы можете запретить такую операцию, обеспечив специальную обработку извещения TBN_QUERYDELETE.
Если обработчик извещения вернет значение TRUE, пользователь сможет удалить кнопку, номер которой передается вместе с извещением в поле iItem. Если же обработчик вернет значение FALSE, кнопка останется на своем месте.
Ниже мы привели обработчик извещения TBN_QUERYDELETE, который запрещает удаление кнопки с номером ноль, но разрешает удаление любых других кнопок:
case TBN_QUERYDELETE: lptbn = (LPTBNOTIFY)pnmhdr; nItem = lptbn->; return (nItem == 0)? FALSE : TRUE; break;
TBN_QUERYINSERT
Извещение TBN_QUERYINSERT обрабатывается аналогично предыдущему.
Если обработчик этого извещения вернет значение TRUE, пользователь сможет вставить новую кнопку слева от той, номер которой передается в поле iItem. В противном случае вставка новой кнопки в данной позиции будет невозможна.
TBN_TOOLBARCHANGE
Извещение TBN_TOOLBARCHANGE посылается родительскому окну, создавшему Toolbar , когда пользователь изменил внешний вид этого органа управления.
В ответ родительское окно обычно посылает органу Toolbar сообщение TB_AUTOSIZE, которое вызывает автоматическое изменение размеров Toolbar:
case TBN_TOOLBARCHANGE: SendMessage(hwndTb, TB_AUTOSIZE, 0L, 0L); return TRUE; break;
TBN_BEGINADJUST
Это извещение поступает в родительское окно, когда пользователь приступил к настройке Toolbar . В ответ на него обработчик может вернуть любое значение, так как оно все равно будет проигнорировано.
TBN_ENDADJUST
Когда пользователь закончил настройку Toolbar , родительское окно получает извещение TBN_ENDADJUST. Соответствующий обработчик может вернуть любое значение.
TBN_BEGINDRAG
Если пользователь начал передвигать кнопку по поверхности Toolbar , родительское окно получает извещение TBN_BEGINDRAG. Так же как и в предыдущих двух случаях, обработчик извещения может вернуть любое значение.
TBN_ENDDRAG
Когда пользователь закончит передвижение кнопки по поверхности Toolbar , родительское окно получит извещение TBN_ENDDRAG. В ответ оно может вернуть любое значение.
TBN_RESET
Если родительское окно получило извещение TBN_RESET, это означает, что пользователь нажал кнопку "Reset" в диалоговой панели, которая была вызвана для настройки Toolbar . Обработчик этого извещения (если он предусмотрен), должен восстановить исходный вид органа управления Toolbar и вернуть любое значение.
Посылая органу Toolbar сообщение TB_SAVERESTORE вы можете сохранить в регистрационной базе данных и восстановить состояние Toolbar.
TBN_CUSTHELP
Извещение TBN_CUSTHELP передается родительскому окну, когда пользователь нажал кнопку "Help" в диалоговой панели, которая была вызвана для настройки Toolbar .
Обработчик этого извещения должен отобразить на экране соответствующий раздел справочной системы и вернуть любое значение.
Описание кнопок
Далее вы должны создать массив структур TBBUTTON , который описывает кнопки и разделители между группами кнопок. В этом массиве необходимо зарезервировать по одной структуре для каждой кнопки и для каждого разделителя групп кнопок.
В файле commctrl.h находится такое определение структуры TBBUTTON:
typedef struct _TBBUTTON { int iBitmap; int idCommand; BYTE fsState; BYTE fsStyle; DWORD dwData; int iString; } TBBUTTON, NEAR * PTBBUTTON, FAR * LPTBBUTTON; typedef const TBBUTTON FAR * LPCTBBUTTON;
В поле iBitmap каждой структуры массива необходимо записать номер кнопки (нумерация начинается с нуля). Для разделителя в этом поле следует указать нулевое значение.
В поле idCommand вы должны записать идентификатор, который будет передаваться родительскому окну с сообщением WM_COMMAND, когда пользователь нажмет соответствующую кнопку. Если элемент массива структур TBBUTTON описывает разделитель группы кнопок, в поле idCommand вам нужно записать нулевое значение.
Поле fsState должно содержать флаг исходного состояния кнопки:
Флаг | Описание |
TBSTATE_ENABLED | Кнопка находится в разблокированном состоянии. Если этот флаг не установлен, кнопка заблокирована и отображается серым цветом |
TBSTATE_CHECKED | Кнопка изображается в нажатом состоянии. Этот флаг используется для кнопок с фиксацией |
TBSTATE_HIDDEN | Скрытая кнопка, не отображается |
TBSTATE_INDETERMINATE | Кнопка отображается серым цветом |
TBSTATE_PRESSED | Кнопка изображается в нажатом состоянии |
TBSTATE_WRAP | Кнопки, расположенные после той, что имеет флаг TBSTATE_WRAP, отображаются на новой строке. Таким образом, вы можете создать многострочный Toolbar . Этот флаг можно указывать только тогда, когда установлен флаг TBSTATE_ENABLED |
Теперь вам не нужно готовить отдельные изображения для разных состояний кнопок, так как при необходимости Toolbar изменяет внешний вид кнопок автоматически.
После того как Toolbar будет создан, приложение может изменять состояние кнопки, посылая окну Toolbar сообщение TB_SETSTATE. Позже мы перечислим сообщения, которые можно посылать окну Toolbar.
Теперь займемся полем fsStyle. Как видно из названия, в это поле нужно записать стиль кнопки. Здесь вы можете использовать комбинацию следующих стилей:
Стиль кнопки | Описание |
TBSTYLE_BUTTON | Стандартная кнопка |
TBSTYLE_CHECK | Кнопка с фиксацией. Эта кнопка "залипает", когда пользователь нажимает на нее. Для того чтобы вернуть кнопку в исходное состояние, необходимо нажать на нее еще раз |
TBSTYLE_CHECKGROUP | Кнопка с фиксацией, которая остается нажатой до тех пор, пока нажата другая кнопка из этой же группы |
TBSTYLE_GROUP | Стандартная кнопка, которая остается нажатой до тех пор, пока нажата другая кнопка из этой же группы |
TBSTYLE_SEP | Разделитель между группами кнопок |
Через поле dwData можно передать дополнительные данные, которые будут хранится в описании кнопки и использоваться при необходимости. Вы можете записать в это поле нулевое значение.
И, наконец, в поле iString можно записать номер текстовой строки, которую необходимо написать на поверхности кнопки. Для добавления таких строк к внутреннему списку Toolbar необходимо послать сообщение TB_ADDSTRING , передав вместе с ним адрес буфера с текстовыми строками. Все строки в этом буфере должны быть закрыты двоичным нулем, а последняя - двумя двоичными нулями.
Если текстовые строки не используются, в поле iString следует записать нулевой значение.
Вот образец подготовленного массива структур TBBUTTON, описывающий восемь кнопок и три разделителя между ними:
TBBUTTON tbButtons[] = { { 0, ID_FILE_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 1, ID_FILE_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 2, ID_FILE_SAVE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0}, { 3, ID_EDIT_CUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 4, ID_EDIT_COPY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 5, ID_EDIT_PASTE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0}, { 6, ID_FILE_PRINT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0}, { 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0L, 0}, { 7, ID_HELP_ABOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0L, 0} };
Подготовка изображений для кнопок
В предыдущих томах "Библиотеки системного программиста" мы создавали Toolbar средствами Win16. Тогда для каждой кнопки мы готовили три различных изображения - для отжатого, нажатого и заблокированного состояния. Если кнопок много, рисовать приходится долго.
Теперь вам нужно только одно изображение, правда, в нем должны располагаться рисунки для всех кнопок. В качестве примера лучше всего взять файл TOOLBAR.BMP, который создается автоматически генератором приложений AppWizard из Microsoft Visual C++ (рис. 2.1).
Рис. 2.1. Изображение стандартных кнопок для органа управления Toolbar , которое создается генератором приложений AppWizard
Вы можете создать свои изображения, взяв этот файл за основу, изменив существующие пиктограммы или добавив новые. Для этого можно воспользоваться, например, приложением Paint, которое входит в состав Microsoft Windows 95. Можно также создать новый bmp-файл, который должен быть 16-цветным. Другое условие - все пиктограммы в этом изображении должны быть одного размера.
В любом случае вы должны добавить созданное изображение в файл ресурсов приложения, снабдив его идентификатором, например:
IDB_TBBITMAP BITMAP DISCARDABLE "toolbar.bmp"
Если вы пользуетесь Microsoft Visual C++, то эта среда разработки приложений внесет все необходимые изменения в rc-файл автоматически, как только вы определите соответствующий ресурс.
Сообщения для Toolbar
Посылая сообщения органу Toolbar , приложение может управлять кнопками, получать информацию о состоянии кнопок, вызывать на экран диалоговую панель для настройки Toolbar и выполнять множество других действий. Ниже мы приведем краткое описание сообщений, предназначенных для Toolbar. Полную информацию вы сможете найти в справочной системе SDK для Win32.
TB_ADDBITMAP
Добавление одного или нескольких изображений к списку изображений органа управления Toolbar .
Параметры сообщения:
wParam = (WPARAM) nButtons; // количество добавляемых // изображений lParam = (LPARAM) (LPTBADDBITMAP) lptbab; // указатель на // структуру TBADDBITMAP
Как мы уже говорили, для Toolbar вы должны подготовить изображение, содержащее несколько картинок, которые будут нарисованы на кнопках. Если вы создаете Toolbar функцией CreateWindowEx, для добавления изображений необходимо послать созданному окну сообщение TB_ADDBITMAP:
tbab.hInst = hInst; tbab.nID = IDB_TBBITMAP; SendMessage(hwndTb, TB_ADDBITMAP, (WPARAM)8, (LPARAM)&tbab);
TB_ADDBUTTONS
Добавление кнопок к органу управления Toolbar .
wParam = (WPARAM) (UINT) uNumButtons; // количество кнопок lParam = (LPARAM) (LPTBBUTTON) lpButtons; // указатель на // заполненный массив структур TBBUTTON
Это сообщение используется в процессе создания Toolbar , так же как и предыдущее:
SendMessage(hwndTb, TB_ADDBUTTONS, (WPARAM)11, (LPARAM)&tbButtons);
Количество кнопок задается с учетом промежутков между группами кнопок. Каждый промежуток при этом считается за одну кнопку, хотя вы можете создавать промежутки размером в несколько кнопок (например, чтобы разместить там другие органы управления).
TB_ADDSTRING
Добавление новых текстовых строк в список органа управления Toolbar .
wParam = (WPARAM) (HINSTANCE) hinst; // идентификатор модуля lParam = (LPARAM) MAKELONG(idString, 0); // идентификатор // строки
Вы можете добавлять текстовые строки не только из ресурсов приложения, но и из массива в оперативной памяти. В этом случае параметр hinst должен быть равен нулю, а через параметр lParam необходимо передать адрес массива строк. Каждая строка в массиве должна заканчиваться двоичным нулем, а последняя - двумя нулями.
TB_AUTOSIZE
Параметры этого сообщения должны быть равны нулю. Оно посылается органу управления Toolbar сразу после создания, а также при изменении количества или расположения кнопок.
TB_BUTTONCOUNT
После посылки этого сообщения органу управления Toolbar функция SendMessage возвращает количество кнопок, добавленных в него с момента создания. Параметры сообщения должны быть равны нулю.
TB_BUTTONSTRUCTSIZE
С помощью этого сообщения приложение, создавшее орган управления Toolbar , должно сообщить последнему размер структуры TBBUTTON.
wParam = (WPARAM) cb; // размер структуры TBBUTTON
Значение параметра lParam должно быть равно нулю.
Сообщение TB_BUTTONSTRUCTSIZE следует послать органу Toolbar сразу после его создания функцией CreateWindowEx:
SendMessage(hwndTb, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
TB_CHANGEBITMAP
Замена изображения на поверхности кнопки.
wParam = (WPARAM) idButton; // идентификатор кнопки lParam = (LPARAM) MAKELPARAM(iBitmap, 0); // номер нового // изображения
TB_CHECKBUTTON
С помощью этого сообщения можно переключать кнопку из отжатого состояния в нажатое и обратно.
wParam = (WPARAM) idButton; // идентификатор кнопки lParam = (LPARAM) MAKELONG(fCheck, 0); // флаг
Если значение флага равно TRUE, кнопка переводится в нажатое состояние, если FALSE - в отжатое.
TB_COMMANDTOINDEX
Определение номера кнопки по ее идентификатору (нумерация кнопок начинается с нуля).
wParam = (WPARAM) idButton; // идентификатор кнопки
Значение параметра lParam должно быть равно нулю.
Номер кнопки возвращается функцией SendMessage после посылки с ее помощью сообщения TB_COMMANDTOINDEX.
TB_CUSTOMIZE
Если окну Toolbar послать сообщение TB_CUSTOMIZE и если при создании Toolbar был указан стиль CCS_ADJUSTABLE, на экране появляется диалоговая панель настройки. С помощью этой панели (которая будет описана ниже) пользователь может изменять внешний вид органа управления Toolbar.
Параметры сообщения должны быть равны нулю.
TB_DELETEBUTTON
С помощью этого сообщения приложение может удалить кнопку из окна Toolbar . Порядковый номер удаляемой кнопки передается через параметр wParam:
wParam = (WPARAM) iButton;
Параметр lParam должен быть равен нулю.
Отметим, что вы можете определить порядковый номер кнопки по ее идентификатору с помощью сообщения TB_COMMANDTOINDEX, описанного выше.
TB_ENABLEBUTTON
С помощью сообщения TB_ENABLEBUTTON приложение может заблокировать или разблокировать кнопку.
wParam = (WPARAM) idButton; // идентификатор кнопки lParam = (LPARAM) MAKELONG(fEnable, 0); // флаг блокировки
Если флаг равен TRUE, кнопка разблокируется, если FALSE - блокируется.
TB_GETBITMAP
Определение номера изображения по идентификатору кнопки.
wParam = (WPARAM) idButton; // идентификатор кнопки
Параметр lParam должен быть равен нулю.
Порядковый номер изображения возвращается функцией SendMessage.
TB_GETBITMAPFLAGS
С помощью этого сообщения можно определить способность монитора отображать картинки большого размера. Это возможно в том случае, если в одном логическом дюйме контекста отображения экрана помещается не менее 120 пикселов.
Если монитор может отображать большие картинки, в возвращаемом функцией SendMessage значении установлен флаг TBBF_LARGE.
TB_GETBUTTON
Получение информации о кнопке, заданной своим номером.
wParam = (WPARAM) iButton; // номер кнопки lParam = (LPARAM) (LPTBBUTTON) lpButton; // адрес структуры // TBBUTTON
TB_GETBUTTONTEXT
Получение текстовой строки, связанной с кнопкой, которая задана своим номером.
wParam = (WPARAM) idButton; // номер кнопки lParam = (LPARAM) (LPSTR) lpszText; // адрес буфера для строки
TB_GETITEMRECT
Определение координат области, занимаемой кнопкой, которая задана своим номером.
wParam = (WPARAM) iButton; // номер кнопки lParam = (LPARAM) (LPRECT) lprc; // адрес структуры RECT
TB_GETROWS
Определение количества строк в органе управления Toolbar , имеющим стиль TBSTYLE_WRAPABLE.
Параметры сообщения должны быть равны нулю.
TB_GETSTATE
Определение состояния кнопки, заданной своим идентификатором.
wParam = (WPARAM) idButton; // идентификатор кнопки
Приведем список возможных состояний кнопки.
Состояние | Описание |
TBSTATE_CHECKED | Кнопка имеет стиль BSTYLE_CHECKED и нажата |
TBSTATE_ENABLED | Кнопка разблокирована и может быть нажата пользователем |
TBSTATE_HIDDEN | Кнопка скрыта |
TBSTATE_INDETERMINATE | Кнопка находится в неопределенном состоянии и отображается серым цветом |
TBSTATE_PRESSED | Кнопка нажата |
TBSTATE_WRAP | После этой кнопки начинается новая строка органа управления Toolbar |
TB_GETTOOLTIPS
Определение идентификатора органа управления Tool Tip, связанного с данным органом управления Toolbar .
Параметры сообщения должны быть равны нулю.
TB_HIDEBUTTON
С помощью этого сообщения можно отобразить или скрыть кнопку, заданную своим идентификатором.
wParam = (WPARAM) idButton; // идентификатор кнопки lParam = (LPARAM) MAKELONG(fShow, 0); // флаг
Если флаг равен TRUE, кнопка становится скрытой, если FALSE - отображается.
TB_INDETERMINATE
С помощью этого сообщения можно установить или отменить для кнопки неопределенное состояние, когда кнопка отображается серым цветом.
wParam = (WPARAM) idButton; // идентификатор кнопки lParam = (LPARAM) MAKELONG(fIndeterminate, 0); // флаг
Если флаг равен TRUE, неопределенное состояние устанавливается, если FALSE - отменяется.
TB_INSERTBUTTON
Вставка кнопки в Toolbar .
wParam = (WPARAM) iButton; // номер кнопки lParam = (LPARAM)(LPTBBUTTON)lpButton; // указатель на // структуру TBBUTTON
Если кнопка была вставлена успешно, функция SendMessage вернет значение TRUE, в противном случае - FALSE.
TB_ISBUTTONCHECKED
С помощью этого сообщения приложение может проверить состояние кнопки - нажата кнопка или нет.
wParam = (WPARAM) idButton; // идентификатор кнопки
Значение параметра lParam должно быть равно нулю.
Если кнопка нажата, функция SendMessage вернет значение TRUE, в противном случае - FALSE.
TB_ISBUTTONENABLED
С помощью этого сообщения приложение может проверить состояние блокировки кнопки - заблокирована кнопка или нет.
wParam = (WPARAM) idButton; // идентификатор кнопки
Значение параметра lParam должно быть равно нулю.
Если кнопка разблокирована, функция SendMessage вернет значение TRUE, в противном случае - FALSE.
TB_ISBUTTONHIDDEN
С помощью этого сообщения приложение может проверить, скрыта кнопка или нет.
wParam = (WPARAM) idButton; // идентификатор кнопки
Значение параметра lParam должно быть равно нулю.
Если кнопка скрыта, функция SendMessage вернет значение TRUE, в противном случае - FALSE.
TB_ISBUTTONINDETERMINATE
С помощью этого сообщения приложение может проверить, находится ли кнопка в неопределенном состоянии, когда она отображается серым цветом.
wParam = (WPARAM) idButton; // идентификатор кнопки
Значение параметра lParam должно быть равно нулю.
Если кнопка находится в неопределенном состоянии, функция SendMessage вернет значение TRUE, в противном случае - FALSE.
TB_ISBUTTONPRESSED
С помощью этого сообщения приложение может проверить, находится ли кнопка в нажатом состоянии.
wParam = (WPARAM) idButton; // идентификатор кнопки
Значение параметра lParam должно быть равно нулю.
Если кнопка находится в нажатом состоянии, функция SendMessage вернет значение TRUE, в противном случае - FALSE.
TB_PRESSBUTTON
С помощью этого сообщения приложение может установить кнопку в нажатое или отжатое состояние.
wParam = (WPARAM) idButton; // идентификатор кнопки lParam = (LPARAM) MAKELONG(fPress, 0); // флаг
Для того чтобы перевести кнопку в нажатое состояние, необходимо установить значение флага fPress равным TRUE, а для того чтобы перевести кнопку в отжатое состояние - равным FALSE.
Если состояние кнопки было изменено успешно, функция SendMessage вернет значение TRUE, в противном случае - FALSE.
TB_SAVERESTORE
Посылая органу управления Toolbar сообщение TB_SAVERESTORE, приложение может сохранить или восстановить состояние Toolbar. Для хранения состояния Toolbar используется системная регистрационная база данных.
wParam = (WPARAM) (BOOL) fSave; // флаг lParam = (LPARAM) (TBSAVEPARAMS *)ptbsp; // указатель на // структуру TBSAVEPARAMS
Если значение флага fSave равно TRUE, будет выполнено сохранение состояния Toolbar , а если FALSE - восстановление.
Через параметр ptbsp передается указатель на структуру типа TBSAVEPARAMS , приведенную ниже:
typedef struct { HKEY hkr; // идентификатор ключа регистрации LPCTSTR pszSubKey; // имя ключа LPCTSTR pszValueName; // значение ключа } TBSAVEPARAMS;
Работа с системной регистрационной базой данных Microsoft Windows 95 будет описана в одном из следующих томов "Библиотеки системного программиста".
TB_SETBITMAPSIZE
С помощью сообщения TB_SETBITMAPSIZE приложение может установить размер картинки, изображенной на поверхности кнопки.
lParam = (LPARAM) MAKELONG(dxBitmap, dyBitmap); // размеры
Значение параметра wParam должно быть равно нулю.
Через параметры dxBitmap и dyBitmap передается, соответственно, ширина и высота изображения.
TB_SETBUTTONSIZE
С помощью сообщения TB_SETBUTTONSIZE приложение может установить размер кнопки.
Param = (LPARAM) MAKELONG(dxButton, dyButton); // размеры
Значение параметра wParam должно быть равно нулю.
Через параметры dxButton и dyButton передается, соответственно, ширина и высота кнопки.
TB_SETCMDID
С помощью этого сообщения можно присвоить кнопке с заданным номером командный идентификатор.
wParam = (WPARAM) (UINT) index; // номер кнопки lParam = (WPARAM) (UINT) cmdId; // идентификатор
TB_SETPARENT
С помощью сообщения TB_SETPARENT приложение может назначить для органа управления Toolbar родительское окно.
wParam = (WPARAM) (HWND) hwndParent; // идентификатор // родительского окна
Значение параметра lParam должно быть равно нулю.
TB_SETROWS
Установка количества строк кнопок в органе управления Toolbar .
wParam = (WPARAM) MAKEWPARAM(cRows, fLarger); lParam = (LPARAM) (LPRECT) lprc;
Через параметр cRows передается количество строк. Минимальное значение параметра равно одной строке, максимальное - количеству кнопок в окне Toolbar .
Если параметр fLarger равен TRUE, при недостатке места для размещения всех кнопок в cRows строках будет создана дополнительная строка. Если же параметр fLarger равен FALSE, дополнительная строка не создается.
Перед тем как послать окну Toolbar сообщение TB_SETROWS, вы должны подготовить структуру типа RECT. Ее адрес нужно передать через параметр lprc. После обработки сообщения в эту структуру будут записаны новые размеры окна Toolbar.
TB_SETSTATE
Установка кнопки с заданным идентификатором в новое состояние.
wParam = (WPARAM) idButton; // идентификатор кнопки lParam = (LPARAM) MAKELONG(fState, 0); // состояние кнопки
Список возможных состояний кнопки приведен выше в описании сообщения TB_GETSTATE.
TB_SETTOOLTIPS
С помощью сообщения TB_SETTOOLTIPS приложение может назначить для Toolbar орган управления Tool Tip.
wParam = (WPARAM)(HWND)hwndToolTip; // идентификатор Tool Tip
Значение параметра lParam должно быть равно нулю.
Заметим, что при создании Toolbar со стилем TBSTYLE_TOOLTIPS для него автоматически создается орган Tool Tip , поэтому вам не нужно посылать окну Toolbar дополнительное сообщение TB_SETTOOLTIPS. Однако если вы посылаете такое сообщение, в Tool Tip будут зарегистрированы только те кнопки, которые были добавлены в Toolbar до момента посылки сообщения TB_SETTOOLTIPS.
Вызов функции создания окна Toolbar
Теперь, когда вы подготовили файл изображения кнопок, создали для него идентификатор в файле ресурсов приложения и подготовили массив структур TBBITMAP , описывающий кнопки, можно создавать окно Toolbar. Проще всего это сделать при помощи специально предназначенной для этого функции CreateToolbarEx:
HWND CreateToolbarEx( HWND hwnd, // идентификатор родительского окна DWORD ws, // стили окна Toolbar UINT wID, // идентификатор органа Toolbar int nBitmaps,// количество пиктограмм с изображением кнопок HINSTANCE hBMInst, // идентификатор приложения UINT wBMID, // идентификатор битового изображения кнопок LPCTBBUTTON lpButtons, // адрес описания кнопок int iNumButtons, // количество кнопок int dxButton, // ширина кнопок (в пикселах) int dyButton, // высота кнопок int dxBitmap,// ширина пиктограмм, нарисованных на кнопках int dyBitmap,// высота пиктограмм, нарисованных на кнопках UINT uStructSize // размер структуры в байтах );
Как можно узнать из документации, эта функция создает окно Toolbar и добавляет в него кнопки, описанные в массиве структур TBBITMAP. При этом ей также нужно указать идентификатор изображения кнопок, а также другие параметры, перечисленные выше.
При удачном завершении функция CreateToolbarEx возвращает идентификатор созданного органа управления Toolbar , который можно будет использовать для посылки сообщений. Если же Toolbar по каким-либо причинам создать так и не удалось, функция возвращает значение NULL.
Перед первым вызовом этой функции следует вызвать функцию InitCommonControls, которая не имеет параметров, не возвращает никакого значения и служит для инициализации библиотеки стандартных органов управления.
Вот пример применения этой функции в приложении Smart Application, исходные тексты которого будут приведены позже:
hwndTb = CreateToolbarEx(hWnd, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE, IDT_TOOLBAR, // идентификатор органа Toolbar 8, // количество пиктограмм hInst, // идентификатор приложения IDB_TBBITMAP, // идентификатор битового изображения кнопок (LPCTBBUTTON)&tbButtons, // адрес описания кнопок 11, // количество кнопок 16, 16, // ширина и высота кнопок 16, 16, // ширина и высота пиктограмм sizeof(TBBUTTON)); // размер структуры в байтах
В качестве первого параметра мы передаем функции идентификатор главного окна приложения. Это окно будет получать от органа Toolbar извещения в виде сообщений WM_COMMAND и WM_NOTIFY.
Параметр ws определяет стили окна Toolbar . Так как это окно всегда является дочерним по отношению к создавшему его окну, необходимо использовать стиль WS_CHILD. Для того чтобы окно Toolbar имело рамку и было видимым, мы указываем стили WS_BORDER и WS_VISIBLE. Если нужно чтобы пользователь мог изменять внешний вид Toolbar, необходимо использовать стиль CCS_ADJUSTABLE.
Кроме того, для органа управления Toolbar вы можете задать следующие стили:
Стиль Toolbar | Описание |
TBSTYLE_TOOLTIP | Вывод краткого описания кнопки в окне органа управления Tool Tip |
TBSTYLE_ALTDRAG | Если не указан стиль TBSTYLE_ALTDRAG, то пользователь может передвигать кнопки по поверхности Toolbar левой клавишей мыши при нажатой клавише <Shift>. Если же этот стиль указан, для перемещения кнопок используется клавиша <Alt>. В любом случае кнопки можно передвигать только тогда, когда указан стиль CCS_ADJUSTABLE |
TBSTYLE_WRAPABLE | Окно Toolbar может состоять из нескольких строк. Новые строки создаются в том случае, если все кнопки не помещаются в одной строке |
Стиль | Описание |
CCS_ADJUSTABLE | Если указан этот стиль, пользователь может изменять конфигурацию органа управления |
CCS_BOTTOM | Орган управления должен быть расположен в нижней части внутренней области окна |
CCS_TOP | Орган управления должен быть расположен в верхней части внутренней области окна |
CCS_NODIVIDER | В верхней части органа управления не надо рисовать разделительную линию шириной 2 пиксела |
CCS_NOHILITE | В верхней части органа управления не надо рисовать выделяющую линию шириной 1 пиксел |
CCS_NOMOVEY | В ответ на сообщение WM_SIZE орган управления будет изменять свои горизонтальные размеры и будет передвигаться по горизонтали, однако при этом его вертикальные размеры останутся прежними |
CCS_NOPARENTALIGN | Орган управления не будет автоматически перемещаться в верхнюю или нижнюю часть родительского окна |
CCS_NORESIZE | При установке начальных размеров не будут использоваться размеры, заданные по умолчанию. Приложение должно задать размеры органа управления явным образом |
Как мы уже говорили, вы можете создать Toolbar при помощи функции CreateWindowEx. Однако в этом случае вам придется добавлять к Toolbar изображение кнопок и сами кнопки, посылая ему сообщения TB_ADDBITMAP и TB_ADDBUTTONS.
Ниже приведен фрагмент исходного текста приложения, создающего Toolbar при помощи функции CreateWindowEx:
TBADDBITMAP tbab; hwndTb = CreateWindowEx(0, TOOLBARCLASSNAME, (LPSTR)NULL, WS_CHILD | WS_BORDER | WS_VISIBLE | TBSTYLE_TOOLTIPS | CCS_ADJUSTABLE, 0, 0, 0, 0, hWnd, (HMENU)IDT_TOOLBAR, // идентификатор органа Toolbar hInst, // идентификатор приложения NULL); if(hwndTb == NULL) return FALSE;
SendMessage(hwndTb, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
tbab.hInst = hInst; tbab.nID = IDB_TBBITMAP; SendMessage(hwndTb, TB_ADDBITMAP, (WPARAM)8, (LPARAM)&tbab);
SendMessage(hwndTb, TB_ADDBUTTONS, (WPARAM)11, (LPARAM)&tbButtons);
Сразу после создания окна Toolbar мы посылаем ему сообщение TB_BUTTONSTRUCTSIZE, указывая в нем размер структуры TBBUTTON.
Затем мы заполняем структуру TBADDBITMAP:
typedef struct { HINSTANCE hInst; UINT nID; } TBADDBITMAP, *LPTBADDBITMAP;
В поле hInst этой структуры мы записываем идентификатор приложения, в поле nID - идентификатор изображения кнопок, определенного в ресурсах приложения.
Адрес заполненной структуры типа TBADDBITMAP и количество изображений мы передаем в качестве параметров сообщения TB_ADDBITMAP.
После этого мы добавляем в Toolbar кнопки, передавая ему сообщение TB_ADDBUTTONS. Через параметры этого сообщения мы передаем количество кнопок (с учетом разделителей) и адрес заполненной структуры TBBUTTON, описывающей кнопки.
Операционная система Windows 95 для программиста
Внешний вид органа управления Trackbar показан на рис. 7.1.
Орган управления Trackbar
По принципу действия и назначению Trackbar напоминает орган управления Scrollbar (полоса просмотра), который мы подробно рассмотрели в 12 томе "Библиотеки системного программиста".
В окне Trackbar имеется движок, который можно перемещать мышью, клавишами перемещения курсора, а также клавишами Home, End, PgUp и PgDn. При перемещении движка родительское окно, создавшее орган управления Trackbar, получает извещения. Помимо движка, в окне органа управления Trackbar есть риски (tick marks), разделяющие движок на равные части. Кроме того, можно выделить любой диапазон в окне Trackbar.
Вы можете выбрать горизонтальное или вертикальное расположение органа управления Trackbar. Риски могут находиться с любой стороны, с обеих сторон или их может не быть совсем.
При создании Trackbar приложение должно определить диапазон значений, соответствующих положению движка, шаг расположения рисок, а также шаг изменения этих значений.
Обработка извещений
Когда пользователь перемещает движок органа управления Trackbar, родительское окно получает извещения в форме сообщения WM_HSCROLL (или WM_VSCROLL для горизонтального расположения). Эти извещения аналогичны извещениям, поступающим от полосы просмотра Scrollbar.
Младшее слово параметра wParam сообщения WM_HSCROLL может содержать один из следующих кодов извещения:
Код извещения | Описание |
TB_PAGEUP | Извещение поступает, когда пользователь сделал щелчок мышью по полосе Trackbar слева или сверху от движка, либо нажал клавишу с кодом VK_PRIOR (клавишу <PgUp>) |
TB_PAGEDOWN | Пользователь сделал щелчок справа или снизу от движка, либо нажал клавишу с кодом VK_NEXT (клавишу <PgDn>) |
TB_LINEUP | Была нажата клавиша с кодом VK_LEFT или VK_UP (клавиша перемещения курсора влево или вверх) |
TB_LINEDOWN | Была нажата клавиша с кодом VK_RIGHT или VK_DOWN (клавиша перемещения курсора вправо или вниз) |
TB_TOP | Пользователь нажал клавишу с кодом VK_HOME (клавишу <Home>) |
TB_BOTTOM | Пользователь нажал клавишу с кодом VK_END (клавишу <End>) |
TB_THUMBPOSITION | Это извещение приходит, когда пользователь переместил мышью движок в новое положение |
TB_THUMBTRACK | Извещение TB_THUMBTRACK приходит в процессе перемещения движка |
TB_ENDTRACK | Извещение приходит после завершения перемещения движка мышью или отпускания клавиши, с помощью которой перемещался движок |
Ниже мы привели функцию DlgProc_OnHScroll из приложения Compact Disk Player, обрабатывающую извещения от органа управления Trackbar:
void DlgProc_OnHScroll(HWND hdlg, HWND hwndCtl, UINT code, int pos) { switch(code) { case TB_LINEDOWN: case TB_PAGEDOWN: CdPlayNext(hdlg); break; case TB_LINEUP: case TB_PAGEUP: CdPlayPrev(hdlg); break; case TB_BOTTOM: CdPlay(hdlg, nTrackCnt); break; case TB_TOP: CdPlay(hdlg, 1); break; case TB_THUMBPOSITION: CdPlay(hdlg, pos); break; default: break; } }
Как видите, здесь все очень просто.
Функции DlgProc_OnHScroll передаются преобразованные параметры сообщения WM_HSCROLL. Код извещения находится в параметре code, а новое значение позиции (которое нужно для обработки извещения TB_THUMBPOSITION) - в параметре pos.