Коротенькая статья о выводе контекстного меню
- Автор: Still Zero
- Уровень знаний: начальный
- Подразделы: нет
- Дата публикации: 27.05.2005
Задача: создать всплывающее (контекстное, popup) меню, вызвать его при нажатии на кнопку, показать меню прямо под кнопкой.
Зачем именно под кнопкой: … так красивее 🙂
Создание меню
В ABC-шаблонах существует класс PopupClass, который предназначен для создания контекстного меню. Подробнее о нем вы можете прочитать в стандартной документации. Описание класса и его код находятся в файлах abpopup.inc, abpopup.clw в каталоге LIBSRC.
Из недокументированного:
- метод SetIcon служит для установки пункту меню иконки, прототип метода:
SetIcon PROCEDURE(STRING Name, STRING IconName) ! Name - метка пункта меню
- при добавлении пункта меню вы можете использовать свойства шрифта, например, Prop:FontStyle, это может понадобиться если вы захотите сделать текст пункта меню, например, наклонным.
PopupRefers PopupClass ! объявление объекта класса code PopupRefers.Init() ! инициализация PopupRefers.AddItem('Справочник #1','Refer1') ! добавление пунктов меню PopupRefers.AddItem('Справочник #2','Refer2') PopupRefers.AddItem('Справочник #3','Refer3') PopupRefers.AddItem('Справочник #4','Refer4') PopupRefers.AddItem('Справочник #5','Refer5') PopupRefers.AddItem('['&PROP:FontStyle&'(700)]Справочник #6','Refer6') !"толстый" шрифт ... PopupRefers.Kill() ! завершим работу класса
Вывод меню
Для того чтобы показать меню используется метод PopupClass с именем Ask. Метод принимает два необязательных параметра: координаты, в которых будет показано меню. Соответственно, все что необходимо для вывода, это выполнить метод Ask, передав в него координаты нижнего левого угла кнопки.
Для определения координат будем использовать API-функцию GetWindowRect, которая определяет координаты окна. Окном в нашем случае будет выступать кнопка.
По большому счету, наверное, можно обойтись и без API. Можно использовать свойства кнопки Prop:Xpos, Prop:Ypos+Prop:Heigth. Правда в этом случае, придется переключаться в MyWindow{Prop:Pixel}=TRUE, а потом обратно. Использование GetWindowRect избавляет вас о необходимости думать о DLU и пикселах, и, по моему мнению, более универсально.
Прототип GetWindowRect:
GetWindowRect(ULONG hWnd,LONG lpRect),BOOL,PASCAL
hWnd — хэндл окна, для которого необходимо определить координаты, в нашем случае это будет примерно так: ?MyButton{Prop:Handle}
lpRect — адрес на структуру Rect, в Кларионе это группа следующего вида:
Rect GROUP Left LONG Top LONG Right LONG Bottom LONG END где Left, Top, Right, Bottom соответствующие координаты
Таким образом код для вывода меню будем выглядеть следующим образом:
loc:Rect GROUP ! группа координат окна rLeft LONG rTop LONG rRight LONG rBottom LONG END SelectedItem STRING(20) ! выбранный пункт меню сode ... if GetWindowRect(?Button1{Prop:Handle},address(loc:Rect)) ! узнать координаты кнопки SelectedItem=PopupRefers.Ask(loc:Rect.rLeft,loc:Rect.rBottom) ! если все ОК, то выводим меню end
Известные проблемы
Кларион сам определяет с каким выравниванием показывать popup-меню. По умолчанию меню показывается «справа и вниз» от курсора мыши. Если ваше окно будет расположено слишком близко к правому краю десктопа, то меню будет показано слева от курсора мыши, так как при выводе «вправо» его не будет видно. По этой же причине меню может быть показано «вверх» от курсора мыши. Когда вы жестко фиксируете координаты вывода меню и возникает ситуация отличная от выравнивания «справа-вниз», то вся «красота» рушится 🙂
Я решил не обращать внимание на эту проблему, так как случаи ее возникновения достаточно редки, но это минус. По хорошему, я думаю, необходимо определять размер десктопа, используя API GetClientRect и GetDesktopWindow и в зависимости от координат кнопки и предполагаемого размера меню обрабатывать такие ситуации.
Пример выполнен на C55H, ABC
Popup Button (1077)
© Project Zero, 2005-2006. Все права защищены.