Главная » C++, C++ Builder » Динамическая загрузка меню в CBuilder

0

Для того чтобы загрузить ресурс меню из ресурсов, находящихся  в  исполняемом  файле  (или любой другой тип ресурсов, в данном случае), вам нужно знать идентификатор ресурса. Это тот ID, который мы написали в выражении MENU в файле ресурса. Этот идентификатор передается функции API LoadMenu для получения ссылки на ресурс меню. Вот где начинаются чудеса.

Когда мы загрузили меню,  нам  нужно знать, сколько пунктов главного меню (верхняя полоса) будет в данном меню. Это получается вызовом функции API GetMenuItemCount, которая имеет один параметр — ссылка1 на меню, с которым мы работаем. Это работает с главными меню или же подменю. В данном случае мы передаем ссылку на главное меню и получаем количество подменю в нем.

Для добавления пунктов меню мы пробегаем по всем подменю для данного ресурса меню. Каждое подменю добавляется в главное: создается объект типа TMenuItem для подменю, и его свойство Caption устанавливается в нужное имя подменю. Внутри подменю мы повторяем весь процесс. Мы получаем количество пунктов подменю и затем создаем каждый из них.

Важной  функцией,  используемой  нами,  является  функция  API  GetMenuString.  Эта  функция

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

ЗАМЕЧАНИЕ

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

Единственное, чего этот пример не показывает,  — корректная  обработка разделителей.  В принципе, нетрудно получить эту информацию из ресурса меню, прочитанного из файла ресурса (используя функцию API GetMenuState и проверяя флаги на предмет, является ли пункт меню разделителем). Я оставляю это за рамками примера, чтобы его было проще понять.

Удаление пунктов меню

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

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

1 Здесь и далее в основном под ссылкой понимается не элемент языка C++, а термин, по-английски звучащий как handle, который используется для идентификации разнообразных объектов в системе Windows. — Примеч. перев.

Во-первых, измените форму: добавьте две кнопки с названиями Удалить все и Добавить пункты. Новая форма показана на рис. 10.3. Первая кнопка будет использоваться для удаления всех существующих пунктов из меню, а вторая будет делать то, что мы  уже  делали  при  создании формы — динамически добавлять пункты меню.

Рис. 10.3. Измененная форма с динамическим меню

Вместо того чтобы заново набирать весь код для обработки нажатия на кнопку Добавить пункты, создайте функцию AddMenuItems. Переместите весь код из метода FormCreate в функцию AddMenuItems. Затем в методе FormCreate напишите простой вызов этой функции:

void __fastcall TForm1::FormCreate(TObject *Sender)

{

AddMenuItems();

}

Следующим шагом является удаление пунктов меню. Это  просто, как вы и могли подумать. В конце концов, пункты меню хранятся в свойстве Items объекта TMainMenu. Свойство Items (элементы), как и все свойства Items в VCL, имеет набор функций для установки и удаления элементов. В данном случае, однако, вместо метода Remove (который является стандартным способом удаления элементов из списка) мы используем метод Delete. Этот метод удалит меню и все подменю из списка, а также освободит память, связанную с пунктами меню. Метод Remove не освобождает память, так что часть памяти была бы потеряна в вашем приложении. Вот код обработчика нажатия на кнопку Удалить все:

void __fastcall TForm1::Butoon1Click(TObject *Sender)

{

while ( MainMenu1->Items->Count > 0 ) MainMenu1->Items->Delete( 0 );

}

Обработчик нажатия на кнопку Добавить пункты, конечно, представляет собой просто вызов функции AddMenuItems:

void __fastcall TForm1::Button2Click(TObject *Sender)

{

AddMenuItems();

}

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

Источник: Теллес М. – Borland C++ Builder. Библиотека программиста – 1998

По теме:

  • Комментарии