Изменение стандартных менюшек

База знаний

Модераторы: m0p3e, edward_K, Модераторы

Ответить
Vik
Местный житель
Сообщения: 370
Зарегистрирован: 28 сен 2006, 15:43
Откуда: Санкт-Петербург
Контактная информация:

Изменение стандартных менюшек

Сообщение Vik »

Часто возникают вопросы, как изменить какую-либо стандартную менюшку в Галактике. Я для себя написал небольшой объект, который и использую для этих целей.
Файл vih:

Код: Выделить всё

#ifndef __MenuHelper_vih__
#define __MenuHelper_vih__


ObjInterface ObjMenuBuilder;
  #doc
    Назначение:
       Создать построителя динамического меню.
    Параметры:
       p_NameMenu - имя меню (с указанием компоненты), на основе которого будет построено дин. меню
  #end
  function buildDynMenu(p_NameMenu: string[80]) : objMenuBuilder;

  #doc
    Назначение:
       Добавить пункт в меню
    Параметры:
       p_NameItem - имя пункта
       p_Command - команда
  #end
  function addItem(p_NameItem: string[80]; p_Command: word) : objMenuBuilder;

  #doc
    Назначение:
       Добавить разделитель в меню
  #end
  function addSeparator : objMenuBuilder;

  #doc
    Назначение:
       Добавить в меню подменю
    Параметры:
       p_SubMenuName - имя добавляемого подменю (с указанием компоненты)
       p_MainMenuItem - пункт меню, отображаемый в главном меню
  #end
  function addSubMenu(p_SubMenuName, p_MainMenuItem: string[80]) : objMenuBuilder;

  #doc
    Назначение:
       Получить ссылку на меню
  #end
  function getMenu: longint;

  #doc
    Назначение:
       Проверка, не освобожден ли на данный момент хендл меню
  #end
  function isDispose: boolean;

  #doc
    Назначение:
       Сохранить меню и освободить хендл
  #end
  procedure storeAndDispose ;
end;


#doc
  Функции для работы с меню
#end
VipInterface MenuHelper Licensed(Free);
static:
  public function  DynMenuExist(p_NameMenu : string[80]): boolean;
  public function  GetDynMenuBuilder(p_NameMenu: string[80]): objMenuBuilder;
  public procedure DeleteAllDynMenuFromComponent(p_NameComp: string[80]);
end;

VipInterface MenuBuilder implements ObjMenuBuilder  Licensed(Free);

#endif
Реализация:

Код: Выделить всё

#include MenuHelper.vih
Interface MenuHelper ;

const
  MENU_PREFFIX : string[5] = 'MENU ';
end;

create view
from
 X$Resources
;

public function DynMenuExist(p_NameMenu : string[80]): boolean;
{
   p_NameMenu := MENU_PREFFIX + p_NameMenu;

   result := (RecordExists  X$Resources where (( 3 ==  X$Resources.XR$Type and p_NameMenu == X$Resources.XR$Name))
              = tsOk)
}

public function GetDynMenuBuilder(p_NameMenu: string[80]): objMenuBuilder;
{
   var menuBuilder : MenuBuilder new ;

   result := menuBuilder.buildDynMenu(p_NameMenu);
}

public procedure DeleteAllDynMenuFromComponent(p_NameComp: string[80]);
{
   p_NameComp := MENU_PREFFIX + p_NameComp + '::%' ;

   delete x$Resources where ((3 ==  X$Resources.XR$Type))
          and X$Resources.XR$Name like p_NameComp;
}


end.

interface MenuBuilder;
var
  m_Menu: longint;
  m_MenuName   : string[80];
  m_isDispose  : boolean;

create view;

HandleEvent
  cmOnVipLoad:
   {
      m_Menu := 0;
      m_MenuName    := '';
      m_isDispose   := false;
   }
end;

function buildDynMenu(p_NameMenu: string[80]) : objMenuBuilder;
{
   if (m_Menu = 0)
   {
     m_MenuName := p_NameMenu;
     DeleteMenuHowDynamics (m_MenuName);
     m_Menu := LoadMenuEx (m_MenuName, true, false);
     m_isDispose   := false;
   }

   result := objMenuBuilder(self);
}

function addItem(p_NameItem: string[80]; p_Command: word) : objMenuBuilder;
{
   if (m_Menu != 0)
      AddMenuItem(m_Menu, p_NameItem, p_Command );

   result := objMenuBuilder(self);
}

function addSeparator : objMenuBuilder;
{
   if (m_Menu != 0)
      AddMenuItem(m_Menu, 'separator', 666 );

   result := objMenuBuilder(self);
}

function addSubMenu(p_SubMenuName, p_MainMenuItem: string[80]) : objMenuBuilder;
{
   if (m_Menu != 0)
      AddSubMenuDynamic(m_Menu, p_SubMenuName, p_MainMenuItem, '', '');

   result := objMenuBuilder(self);
}


function getMenu: longint;
{
   result := m_Menu;
}

function isDispose: boolean;
{
   result := m_isDispose;
}

procedure storeAndDispose ;
{
   if (m_Menu != 0)
    {
       StoreMenuHowDynamics (m_Menu, m_MenuName);
       DisposeLoadMenu (m_Menu);
       ReinitHeaderMenu;
       m_isDispose := true;
    }
}
end.
Использование на примере этой темы:

Код: Выделить всё

#include MenuHelper.vih

#Component "L_KATORG"
alter interface KATORG;

Window WKATORG
HandleEvent
cmValue41:
{
  Message('!');
};
end
end;

HandleEvent
cmInit :
{
  if (Inherited::HandleEvent(cmInit) != heOk)
  {
    Abort;
    Exit;
  }
  if (not MenuHelper::DynMenuExist('L_KATORG::mnuKatOrgEdit'))
    if (Message('Изменить меню?', Confirmation + YesNo
               )
         = cmYes
         )
     {
         MenuHelper::GetDynMenuBuilder('L_KATORG::mnuKatOrgEdit')
           .addSeparator()
           .addItem('Дополнительный пункт 1', cmValue41)
           .addItem('Дополнительный пункт 2', cmValue41)
           .storeAndDispose();
     }


};//cmInit

end;
end.
galover
Местный житель
Сообщения: 794
Зарегистрирован: 16 ноя 2007, 13:52

Re: Изменение стандартных менюшек

Сообщение galover »

+ 1. спасибо, пригодится
Dmitry_Sol
Постоянный гость
Сообщения: 76
Зарегистрирован: 07 июн 2007, 12:32
Откуда: Витебск
Контактная информация:

Re: Изменение стандартных менюшек

Сообщение Dmitry_Sol »

Добрый день, уважаемый Vik,
попытались воспользоваться вашей разработкой по меню, и столкнулись со следующей проблемой - Если пользователь системы имеет админские права, то меню добавляется отлично.
Если пользователь - рядовой, обрезанный протектом, то при входе в интерфейс выдается сообщение о том, что у пользователя отсутствуют права на удаление меню, после чего система вылетает по runtime 216.

К сожалению из за этого пользоваться разработкой не получилось, пришлось по старому ловить cmHotKeys
Есть ли у вас мысли по этому поводу?
Vik
Местный житель
Сообщения: 370
Зарегистрирован: 28 сен 2006, 15:43
Откуда: Санкт-Петербург
Контактная информация:

Re: Изменение стандартных менюшек

Сообщение Vik »

Вообще мысль одна. Суть в том, что меню создается только в том случае, если оно еще не создано. Что-то и забыл, что с правами могут быть проблемы. Можно перед изменением меню проверять, если пользователь не админ, то и не изменять меню. В чем проблема запустить один раз под администратором интерфейс, что приведет к созданию меню? А дальше пользователи будут работать уже с измененным меню. Переопределять событие cmHotKeys неправильно, там в некоторых интерфейсах такая логика, что вы просто не сможете правильно все сделать, не нарушив стандартную функциональность.

Код: Выделить всё

if (<меню не существует>)
 if (<пользователь не админ> )
  Message('Для доступа к дополнительному функционалу '#13'' + 
          'требуется изменить стандартное меню. Обратитесь к администратору'           
         )
 else
  {
    < Добавляем свои пункты		 >
  }
Для определения статуса пользователя можно использовать функцию UserID и таблицу x$Users соответственно.
edward_K
Заслуженный деятель интернет-сообщества
Сообщения: 5188
Зарегистрирован: 29 мар 2005, 17:49
Откуда: SPB galaxy spb

Re: Изменение стандартных менюшек

Сообщение edward_K »

пересоздавать в момент обновления настроек мне кажется более универсальным. Надо - изменил дату в своей компоненте и вуаля - новое меню.
Vik
Местный житель
Сообщения: 370
Зарегистрирован: 28 сен 2006, 15:43
Откуда: Санкт-Петербург
Контактная информация:

Re: Изменение стандартных менюшек

Сообщение Vik »

Как вариант. Кому как удобнее. Главное cmHotKeys не трогать))
zna
Местный житель
Сообщения: 552
Зарегистрирован: 29 мар 2005, 17:49
Откуда: Челябинск
Контактная информация:

Re: Изменение стандартных менюшек

Сообщение zna »

При компиляции на строке objMenuBuilder(self) получаю ошибку "Нет такой функции, метода SELF"..
Атлантис 5.4.43.0, репозиторий с ресурсниками подключен. Почему? :-(
edward_K
Заслуженный деятель интернет-сообщества
Сообщения: 5188
Зарегистрирован: 29 мар 2005, 17:49
Откуда: SPB galaxy spb

Re: Изменение стандартных менюшек

Сообщение edward_K »

случайно наткнулся на такую же проблему - в viper нужно указать имя компоненты в параметрах проекта или в самом проекте/интерфейсе, при этом обязательно в верхнем регистре, а перед компиляцией интерфейса должен быть объявлен vipinterface (либо через include vih либо другим способом)
Ответить