Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

465

Программа GADGETS посылает простой набор сообщений своей панели инструментов. Большинство из них относятся к действиям с конкретными кнопками, такие как TB_CHECKBUTTON для установки нажатого (checking) или отжатого (unchecking) состояния кнопки, и TB_ENABLEBUTTON для разрешения или запрещения действий над кнопкой. Два сообщения с запросами позволяют вам узнать число кнопок и число строк.

Сообщение TB_CUSTOMIZE вызывает появление диалогового окна изменения конфигурации (Customize Toolbar dialog box), что дает пользователю возможность добавить или удалить кнопку из панели инструментов. Ключом к правильной работе диалогового окна изменения конфигурации является правильная обработка уведомляющих сообщений TBN_QUERYINSERT, TBN_QUERYDELETE и TBN_GETBUTTONINFO. При изменении конфигурации панели инструментов следите за потоком уведомляющих сообщений, чтобы прочувствовать последовательность этих запросов.

Управление строкой состояния программы GADGETS

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

Наиболее интересным аспектом управления строкой состояния в программе GADGETS является то, каким образом программа обрабатывает сообщение WM_MENUSELECT с целью отображения в строке состояния вспомогательной информации. Все строки, выводимые в строку состояния, расположены в таблице строк программы. Для упрощения установки соответствия между идентификаторами пунктов меню и идентификаторами текстовых строк они заданы одинаковыми. Например, идентификатор команды меню File Open задан равным IDM_FILE_OPEN; в то же время эта величина является идентификатором строки "Open an existing document".

Для того чтобы обеспечить отображение в строке состояния вспомогательной информации для всплывающих меню, программа GADGETS устанавливает соответствие описателей меню идентификаторам строк. В программе GADGETS имеется десять всплывающих меню, являющихся дочерними трех родительских меню: главного меню, всплывающего меню Toolbar и всплывающего меню Statusbar. Описания ресурсов-строк строки состояния для этих всплывающих меню в этих родительских меню начинаются со строк IDS_MAIN_MENU, IDS_TOOLBAR_MENU и IDS_STATUSBAR_MENU. Программа GADGETS устанавливает соответствие между описателями родительских меню и этими тремя значениями, передавая их в функцию MenuHelp для отображения необходимой строки вспомогательного текста.

Наборы страниц свойств

Наборы страниц свойств иногда также называют диалогами с закладками (tabbed dialogs). Они дают возможность объединить несколько диалоговых окон в одно, составное диалоговое окно. В наборе страниц свойств каждый отдельный диалог называется страницей свойств (property page). На рис. 12.9 показан набор страниц свойств дисплея Display Properties, доступный с рабочего стола (desktop) Windows 95. (Для доступа к этому набору страниц свойств активизируйте контекстное меню оболочки системы, щелкнув правой кнопкой мыши и выбрав пункт меню Properies — свойства.) Различные страницы в этом наборе страниц свойств позволяют пользователю удобно задать такие настройки дисплея, как обои (wallpaper), хранитель экрана (screen saver), цвета (colors), шрифты (fonts), а также изменить установки дисплейного драйвера, связанные с числом доступных цветов (available colors), разрешением устройства (device resolution), и даже сменить текущий драйвер дисплея.

Рис. 12.9 Набор страниц свойств дисплея (Display Properties)

466

Набор страниц свойств позволяет модифицировать все установки сложного объекта, такого как, например, экран дисплея, путем объединения нескольких страниц свойств в единый элемент управления. Каждая страница имеет свою закладку (tab), щелчком на которой пользователь ее активизирует. Необязательная кнопка Apply позволяет пользователю посмотреть на изменения, им внесенные, без выхода из окна набора страниц свойств. Если результаты окажутся неудовлетворительными, то может быть сделан другой выбор, например, возврат к предыдущим установкам, которые доступны в наборе страниц свойств.

Другим типом составного диалогового окна, относящимся к набору страниц свойств, является мастер (wizard ). Мастер — это набор диалогов, которые получают информацию от пользователя в определенном порядке, для выполнения какой-либо специфичной задачи. На рис. 12.10 показана первая из шести страниц мастера установки принтера в Windows 95 (Add Printer Wizard), который позволяет пользователю последовательно ввести всю детальную информацию для подключения нового системного принтера. Программный интерфейс для мастеров такой же как и для наборов страниц свойств, хотя и имеются небольшие отличия в интерфейсе пользователя: кнопки OK и Cancel заменены кнопками Back и Next. Эти кнопки предназначены для переходов между страницами мастера (вместо закладок в наборе страниц свойств). На последней странице мастера отображается кнопка Finish, которая при нажатии, разрешает выполнение той задачи, для решения которой и был активизирован мастер.

Рис. 12.10 Страница мастера установки принтера (Add Printer Wizard)

Создание набора страниц свойств

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

Эти элементы элементизируются с использованием двух структур данных. Одна — для каждой страницы свойств, а вторая — заголовок, описывающий атрибуты набора страниц свойств целиком. Атрибуты каждой страницы свойств задаются в структуре типа PROPSHEETPAGE, а эти структуры объединяются в массив. Указатель на массив структур типа PROPSHEETPAGE включается в структуру данных типа PROPSHEETHEADER, содержащий атрибуты набора страниц свойств в целом.

Шаблоны диалога страниц свойств

Шаблоны диалога, используемые для страниц свойств, почти полностью идентичны тем шаблонам диалога, которые используются для обычных диалоговых окон. Шаблон диалога страницы свойств содержит обычные элементы управления, такие как окна редактирования (edits), списки (lists), кнопки (push buttons); он может также содержать элементы управления общего пользования, такие как, анимационное изображение (animation), списки типа Drag and Drop (drag lists), окна с движком для выбора значения из диапазона (trackbars) и полосы прокрутки, связанные с окном редактирования (up-down controls). Так же как и в случае обычного шаблона диалога, каждый элемент управления в шаблоне страницы свойств имеет уникальный идентификатор, указывая который при вызове функции GetDlgItem можно получить описатель окна.

467

Единственное отличие между обычным шаблоном диалога и шаблоном страницы свойств состоит в том, что последний обычно не содержит кнопок OK и Cancel. Набор страниц свойств создает и поддерживает разделяемый между всеми страницами свойств набор кнопок. Обычно, по умолчанию, набор страниц свойств имеет кнопки OK, Cancel и Apply, хотя возможно указание флага, удаляющего кнопку Apply, если в ней нет надобности. Возможно также задание флага, указывающего на необходимость вывода в наборе страниц свойств кнопки Help, которая будет доступна тем страницам свойств, которые поддерживают помощь. Мастера используют несколько отличающийся набор кнопок: Back и Next для пролистывания страниц мастера, и кнопку Finish на последней странице.

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

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

Структура PROPSHEETPAGE

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

typedef struct _PROPSHEETPAGE

 

 

 

{

 

 

 

DWORD

dwSize;

// = sizeof(PROPSHEETPAGE)

DWORD

dwFlags;

 

 

HINSTANCE

hInstance;

 

union

 

 

 

{

 

 

// по умолчанию

LPCSTR

pszTemplate;

LPCDLGTEMPLATE

pResource;

// PSP_DLGINDIRECT

} DUMMYUNIONNAME;

 

 

 

union

 

 

 

{

 

 

 

HICON

hIcon; // PSP_USEHICON

LPCSTR

pszIcon;

 

// PSP_USEICONID

} DUMMYUNIONNAME2;

 

 

 

LPCSTR

pszTitle;

 

// PSP_USETITLE

DLGPROC

pfnDlgProc;

 

LPARAM

lParam;

 

 

LPFNPSPCALLBACKA

pfnCallback;

// PSP_USECALLBACK

UINT FAR

*pcRefParent;// PSP_USEREFPARENT

} PROPSHEETPAGE, FAR *LPPROPSHEETPAGE;

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

dwSize — текущая версия страницы свойств; должно быть равно sizeof (PROPSHEETPAGE).

dwFlags — содержит один или несколько PSP-флагов, объединенных поразрядной оператором OR языка C. Большинство флагов влияют на то, будет или нет использоваться то или иное поле структуры PROPSHEETPAGE. Два дополнительных флага, неиспользуемых с этой целью, PSP_HASHELP и PSP_RTLREADING. Флаг PSP_HASHELP делает доступной кнопку Help, когда активна данная страница (флаг PSP_HASHELP должен быть указан в структуре PROPSHEETHEADER для того, чтобы кнопка Help присутствовала). Флаг PSP_RTLREADING заставляет страницу свойств использовать запись справа налево (для еврейского и арабского языков).

hInstance — идентифицирует выполняемый файл, из которого загружены ресурсы диалоговых шаблонов

(pszTemplate) и значков (pszIcon).

Шаблон диалогового окна идентифицируется pszTemplate (по умолчанию) для шаблонов, загруженных из ресурсов, или pResource (необходимо задание флага PSP_DLGINDIRECT в поле dwFlags) для шаблонов, загруженных из памяти.

На закладке страницы свойств дополнительно может быть отображен значок. Значок может быть идентифицирован описателем значка hIcon (при установленном флаге PSP_USEHICON в поле dwFlags) или идентификатором ресурса-значка pszIcon (при установленном флаге PSP_USEICONID в поле dwFlags).

468

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

pfnDlgProc — определяет диалоговую процедуру для страницы свойств.

lParam — задает начальное значение, передаваемое в функцию обратного вызова страницы свойств, заданную параметром pfnCallback.

pfnCallback — функция обратного вызова (при установленном в поле dwFalgs флаге PSP_USECALLBACK), вызываемая перед тем, как страница свойств создается, и после того, как уничтожается.

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

Ниже показано, как в примере программы PROPERTY в этой главе заполняется массив структур типа

PROPSHEETPAGE:

PROPSHEETPAGE pspage[2];

// Обнуляем данные

ZeroMemory(&pspage, 2 * sizeof(PROPSHEETPAGE));

// инициализируем данные первой страницы

pspage[0].dwSize

=

sizeof(PROPSHEETPAGE);

pspage[0].dwFlags

=

PSP_USECALLBACK | PSP_USEICONID;

pspage[0].hInstance

=

hInst;

pspage[0].pszTemplate

=

MAKEINTRESOURCE(IDD_STYLES);

pspage[0].pszIcon

=

MAKEINTRESOURCE(IDI_PAGE1);

pspage[0].pfnDlgProc

= StyleDlgProc;

pspage[0].lParam

=(LPARAM)&dwChildStyle;

pspage[0].pfnCallback = StylePageProc;

// инициализируем данные второй страницы

pspage[1].dwSize

= sizeof(PROPSHEETPAGE);

pspage[1].dwFlags

= PSP_USECALLBACK | PSP_USEICONID | PSP_HASHELP;

pspage[1].hInstance

= hInst;

pspage[1].pszTemplate

= MAKEINTRESOURCE(IDD_EXSTYLES);

pspage[1].pszIcon

= MAKEINTRESOURCE(IDI_PAGE2);

pspage[1].pfnDlgProc

= ExStyleDlgProc;

pspage[1].lParam

=(LPARAM)&dwChildExStyle;

pspage[1].pfnCallback

= ExStylePageProc;

Член структуры PROPSHEETPAGE pfnDlgProc содержит указатель на процедуру диалогового окна. В добавок к сообщениям WM_INITDIALOG и WM_COMMAND, которые обрабатываются в большинстве процедур диалоговых окон, диалоговые процедуры страниц свойств должны обрабатывать третье сообщение — WM_NOTIFY. Ниже приведен примерный шаблон диалоговой процедуры для страницы свойств:

BOOL CALLBACK EmptyPageDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)

{

switch(msg)

{

case WM_INITDIALOG:

[инициализация диалогового окна] break;

case WM_COMMAND:

[уведомления от обычных диалоговых элементов управления] break;

case WM_NOTIFY:

{

LPNMHDR pnmh =(LPNMHDR)lParam;

[уведомления от набора страниц свойств]

}

}

}

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

469

PROPSHEETPAGE, который содержит начальное значение, посланное создателем страницы свойств странице свойств (например, указатель на изменяемые данные). Ниже приведен шаблон функции обратного вызова страницы свойств:

static LPARAM InputData;

UINT CALLBACK EmptyPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)

{

switch(uMsg)

{

case PSPCB_CREATE:

InputData = ppsp->lParam; return TRUE;

case PSPCB_RELEASE: return 0;

}

}

В текущей реализации параметр описателя окна hwnd всегда равен NULL. Параметр uMsg равен PSPCB_CREATE для вызова перед созданием страницы свойств и равен PSPCB_RELEASE после того, как она будет уничтожена. Хотя уведомление при создании посылается только, если страница свойств действительно создается, уведомление при уничтожении всегда посылается каждой странице свойств, вне зависимости от того, была она создана или нет.

После заполнения массива структур типа PROPSHEETPAGE следующим шагом в создании набора страниц свойств является занесение указателя на этот массив в поле ppsp структуры заголовка набора страниц свойств

PROPSHEETHEADER.

Структура PROPSHEETHEADER

Структура PROPSHEETHEADER определена в файле PRSHT.H следующим образом:

typedef struct _PROPSHEETHEADER

 

 

 

{

 

 

 

 

DWORD

dwSize;

// = sizeof(PROPSHEETHEADER)

DWORD

dwFlags;

 

 

 

HWND

hwndParent;

 

 

HINSTANCE

hInstance;

 

 

 

union

 

 

 

 

{

 

 

 

 

HICON

hIcon; // PSH_USEHICON

 

LPCSTR pszIcon;

 

// PSH_USEICONID

} DUMMYUNIONNAME;

 

 

 

LPCSTR

pszCaption;

 

 

UINT

nPages;

 

 

 

union

 

 

 

 

{

 

 

//(по умолчанию)

UINT

nStartPage;

LPCSTR pStartPage;

// PSH_USEPSTARTPAGE

} DUMMYUNIONNAME2;

 

 

 

union

 

 

 

 

{

 

 

 

 

LPCPROPSHEETPAGE

 

ppsp;

// PSH_PROPSHEETPAGE

HPROPSHEETPAGE FAR

*phpage;

 

} DUMMYUNIONNAME3;

 

 

 

PFNPROPSHEETCALLBACK

 

pfnCallback;

// PSH_USECALLBACK

} PROPSHEETHEADER, FAR *LPPROPSHEETHEADER;

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

dwSize — текущая версия набора страниц свойств; должно быть равно sizeof (PROPSHEETHEADER).

dwFlags — содержит один или несколько PSH-флагов, объединенных поразрядной оператором OR языка C. Некоторые флаги определяют, будет или нет использоваться то или иное поле структуры PROPSHEETHEADER, как показано в предыдущем листинге.

hwndParent — идентифицирует родительское окно набора страниц свойств. Для модального набора страниц свойств родительское окно недоступно.

Соседние файлы в предмете Операционные системы