На этом шаге мы рассмотрим меню.
Самый простой способ выполнения различных команд состоит в том, чтобы организовать такие команды в виде пунктов меню. Эту задачу выполняет редактор меню VDЕ. Каждому пункту меню присваивается идентификатор ресурса. Ваше приложение может быть сделано более понятным, если присваивать каждому идентификатору ресурса имя, связанное с выполняемым действием.
Меню связываются с окнами во время создания окна. Параметр меню в предикате win_create определяет, что меню расположено в файле ресурсов или что оно динамически формируется из структуры языка Пролог.
При использовании режима MDI все меню будут появляться в окне Task. Меню автоматически изменяется при модификации активного окна.
Для того чтобы каждое окно имело свое собственное меню, нужно сбросить флаг MDI в эксперте приложений. Родительским окном должно быть окно Screen.
VPI имеет возможность создавать собственные меню. Это средство не является переносимым на все платформы. Обратите внимание, что редактор меню в VDE поддерживает только текстовые меню.
Рассмотрим домены, использующиеся при создании меню:
menu=res_menu(resId);dyn_menu(menu_item_list);no_menu menu_item_list=menu_item* menu_item= txt(menu_tag, % Целое значение для этого пункта меню string, % Текст меню integer Mnemonic, % Буква для акселератора boolean Enabled, boolean Checked, integer ItemState, % Константы: mis_None, mis_Checked, mis_Help. % Последний размещает пункт меню 'Window' % сразу перед этим пунктом. Обычно это % используется для размещения пункта % меню Help в крайнюю правую позицию menu_item_list); ownerdraw( menu_tag, long Val, % 32-разрядное число, передаваемое в e_ownerDraw boolean Enabled, boolean Checked, menu_item_list) ; separator; % Рисует горизонтальную линию в меню menu_break % Разрыв колонки в меню menu_tag = unsigned
Параметр ItemState определяет состояние пункта меню. Его значения приведены таблице 1.
Параметр | Описание |
---|---|
mis_None | Определяет обычное состояние |
mis_Checked | Устанавливает галочку в пункте меню |
mis_Help | Определяет, что этот пункт меню должен быть размещен сразу после меню Window; обычно это используется для того, чтобы поместить пункт Help в крайнее правое положение в меню (только в режиме MDI) |
Сочетание
ItemState=mis_Checked+mis_Help,
Для того чтобы пункт меню выполнял какое-то действие, в обработчике событий окна при помощи эксперта кода нужно сгенерировать предложение, которое обрабатывает событие от этого пункта меню. Любой код, помещенный в это предложение, будет выполняться при выборе данного пункта меню (если пункт меню заблокирован, то этот код никогда не будет выполнен, кроме случаев, когда существует кнопка на панели инструментов, которая не заблокирована и имеет тот же идентификатор ресурса).
Событие, которое было порождено выбором команды File | Open в окне Task, обрабатывается таким кодом:
task_win_event_handler(Window,e_Menu(id_file_open,ShiftCtlAlt),0):- dlg_note("Menu","You chose Open"), !.
Предикат menu_GetRes используется для получения меню из файла ресурсов. Меню загружается в структуру данных VPI из домена menu.
NewMenu=menu_GetRes(irm_my_menu), menu_Set(Window,NewMenu)
Текст отдельного пункта меню может быть изменен при помощи предиката menu_SetText/3. Следующая строка, вставленная в событие создания окна Task - e_Create - изменит стандартный текст File Open на другой, например, Open DataBase:
menu_SetText(Window,id_file_open,"Open DataBase")
С пунктами меню могут быть связаны метки, которые определяют, доступно некоторое свойство или нет. Начальное состояние задается в определении меню. Это состояние можно изменить, вызвав предикат menu_Check/3.
menu_Check(Window,menu_item_resource_identifier,Boolean)
По умолчанию новые пункты меню в редакторе меню являются включенными (кроме тех пунктов, которые автоматически генерируются экспертом приложений без кода). Их можно выключить или блокировать двойным щелчком мыши по имени пункта меню на этапе проектирования или изменением состояния заблокированного пункта, а во время работы приложения - вызовом предиката menu_Enable с последним параметром b_False.
% Блокировка пункта File|New menu_Enable(Window,id_file_new,b_False), % Включение пункта File|New menu_Enable(Window,id_file_new,b_True).
Если вы динамически изменяете текст пунктов меню в событиях, отличных от e_Create, то ваше изменение может быть не видно пользователю на некоторых платформах. Предикат menu_update/l объявляет область экрана, занимаемую меню, недостоверной, инициируя ее перерисовку:
menu_SetText(Window,id_file_open,"OpenDB"),
% Вызывает перерисовку области меню
menu_Update(Window)
Если пункт подменю нужно включить, блокировать, отметить галочкой или изменить текст, то в MS Windows необходимо использовать специальные варианты предикатов menu_Enable, menu_Check и menu_SetText, которые используют текст пункта меню вместо идентификатора.
menu_Enable(Window,String,Boolean) menu_Check(Window,String,Boolean) menu_SetText(Window,String,NewString)
Предикат menu_PopUp/4 используется для создания всплывающих меню и обычно вызывается в ответ на нажатие кнопки мыши. Следующее предложение:
my_event_handler(Window,e_MouseDbl(Pnt,_,_),0):-!, menu_PopUp(Window,res_menu(idr_my_pop_up),Pnt,align_Left).
отобразит меню с идентификатором ресурса idr_my_popup в точке Pnt в окне Window когда пользователь дважды щелкнет мышью в этом окне.
Последний параметр, который может быть равен align_Left, align_Right или align_Center, определяет положение всплывающего меню относительно точки Pnt.
Когда пользователь щелкает мышью во всплывающем меню для данного окна, VPI посылает обычное событие e_Menu обработчику событий этого окна.
Со следующего шага мы начнем рассматривать внешние базы данных в Visual Prolog.