OwnerDraw TMenu

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

OwnerDraw TMenu

Сообщение Hyper » 31.08.2016 11:22:06

Здравствуйте! Как сделать OwnerDraw Menu? Версия Lazarus: 1.6
Событий OnMeasureItem и OnDrawItem нет, в Google практически ничего не нашел по данному вопросу, только changelog Lazarus 1.8, где это реализовано.
Есть ли временное решение(любое, хоть готовый компонент) для собственной прорисовки меню? Спасибо.
Hyper
новенький
 
Сообщения: 19
Зарегистрирован: 31.08.2016 11:15:06

Re: OwnerDraw TMenu

Сообщение zub » 31.08.2016 14:15:02

ЕМНИП в транке это есть. насколько работает - хз.
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: OwnerDraw TMenu

Сообщение Hyper » 31.08.2016 14:50:09

Здравствуйте, zub! Спасибо за ответ! А что Вы можете сказать о CodeTyphon 5.8, базированной на Lazarus?
Скомпилировал её, у TMainMenu есть свойства OwnerDraw.
Hyper
новенький
 
Сообщения: 19
Зарегистрирован: 31.08.2016 11:15:06

Re: OwnerDraw TMenu

Сообщение zub » 31.08.2016 14:59:57

Ничего хорошего - суррогат. Лучше один раз заморочиться и научиться ставить транк
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: OwnerDraw TMenu

Сообщение Снег Север » 01.09.2016 08:19:58

CodeTyphon хорош для всех, кто хочет работать, а не заниматься "сексом в гамаке" с установкой транков и дополнительных компонентов.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2997
Зарегистрирован: 27.11.2007 16:14:47

Re: OwnerDraw TMenu

Сообщение alexs » 01.09.2016 09:11:13

Снег Север писал(а):CodeTyphon хорош для всех, кто хочет работать, а не заниматься "сексом в гамаке" с установкой транков и дополнительных компонентов.

У меня с ним сложилось противоположние впечатление.
Подтирать глюки, которые внесли эти горе сборщики - сомнительное удовольствие.
Проще работать с транком. И гораздо легче.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4054
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: OwnerDraw TMenu

Сообщение pupsik » 01.09.2016 11:29:31

Скомпилировал её, у TMainMenu есть свойства OwnerDraw.
оно есть и в транке лазаря. А вот работает ли и необходимо ли... х.з.

п.с.
по поводу "полезности" тифона.... Пробуйте.
Если что к Снег Север в личку. Походу у него одного одни приятные ощущения от его использования :lol:

Из замеченных багов:
1. Не всегда собирается скриптами.
2. Возможны баги при работе (последний у меня - только англ. фейс, предпоследний - не работали диалоги ("Пареметры проекта", "Настройки")).
3. Некоторые пакеты "узкие". Т.е. под определенную систему.
4. Бывают вылеты при работе.

Единственный плюс для меня - ORCA. Но..о она частично рабочая. Особенно её 3д часть. Хотя, возможно, в винде она адекватна.
pupsik
энтузиаст
 
Сообщения: 1154
Зарегистрирован: 20.08.2014 16:20:13

Re: OwnerDraw TMenu

Сообщение Hyper » 01.09.2016 13:15:53

Собрал я, значит, Lazarus 1.7 из транков, однако OwnerDraw "порадовал", то ли я уже подзабыл, как это делается, либо недоработка компонента - меню закрашивается не до конца. Прикрепил скриншот и код. На скриншоте стрелкой указал область, где не закрашивается меню.
Код: Выделить всё
const
  DefaultHighLightColor = $00ED9564; 

procedure TMainForm.MainMenuDrawItem(Sender: TObject; ACanvas: TCanvas;
  ARect: TRect; AState: TOwnerDrawState);
var
  MenuItem: TMenuItem;
begin
  MenuItem := Sender as TMenuItem;
  if (odSelected in AState) or (odHotLight in AState) then
  begin
    ACanvas.Font.Color := clWhite;
    ACanvas.Brush.Color := DefaultHighLightColor;
    ACanvas.FillRect(ARect);
    if not MenuItem.IsInMenuBar then
    begin
      if MenuItem.Caption <> '-' then
        ACanvas.TextOut(ARect.Left + 25, ARect.Top + 3, MenuItem.Caption);
    end
    else
    begin
      ACanvas.TextOut(ARect.Left + 9, ARect.Top + 2, MenuItem.Caption);
    end;
  end
  else
  begin
    ACanvas.Font.Color := clBlack;
    ACanvas.Brush.Color := clWhite;
    ACanvas.FillRect(ARect);
    if not MenuItem.IsInMenuBar then
    begin
      if MenuItem.Caption <> '-' then
        ACanvas.TextOut(ARect.Left + 25, ARect.Top + 3, MenuItem.Caption);
    end
    else
    begin
      ACanvas.TextOut(ARect.Left + 9, ARect.Top + 2, MenuItem.Caption);
    end;
  end;
  if MenuItem.Caption = '-' then
  begin
    ACanvas.Pen.Color := DefaultHighLightColor;
    ACanvas.Line(ARect.Left + 25, ARect.Top + 12, ARect.Right, ARect.Top + 12);
  end;
end;           

procedure TMainForm.MainMenuMeasureItem(Sender: TObject; ACanvas: TCanvas;
  var AWidth, AHeight: integer);
var
  MenuItem: TMenuItem;
begin
  ACanvas.FillRect(ACanvas.ClipRect);
  MenuItem := Sender as TMenuItem;
  if not MenuItem.IsInMenuBar then
  begin
    AWidth := aCanvas.TextWidth(MenuItem.Caption) + 25;
    AHeight := aCanvas.TextHeight(MenuItem.Caption) + 8;
  end
  else
  begin
    AWidth := aCanvas.TextWidth(MenuItem.Caption) + 3;
    AHeight := aCanvas.TextHeight(MenuItem.Caption) + 4;
  end;
end;


Изображение
Hyper
новенький
 
Сообщения: 19
Зарегистрирован: 31.08.2016 11:15:06

Re: OwnerDraw TMenu

Сообщение alexs » 01.09.2016 16:49:04

Насколько я помню - эта область в винде уже не относится к меню. Там надо событие ловить виндовое на отрисовку не клиентской области.
Хотя могу и ошибаться.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4054
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: OwnerDraw TMenu

Сообщение Hyper » 02.09.2016 14:51:22

Долго искал решение и наконец-то! По запросу в Яндексe "MIM_BACKGROUND delphi" нашел код. Оставлю код здесь, может кому-нибудь пригодится.
Фон меню полностью закрасился в белый цвет, что и требовалось. :D
Код: Выделить всё
var
  MenuBarBackground: TBrush;
  MenuBarBackgroundOld: HBrush; 

procedure TMainForm.FormCreate(Sender: TObject);
var
  lpcmi: TMenuInfo;
begin
  MenuBarBackground:= TBrush.Create;
  MenuBarBackground.Color:= clWhite;  //Цвет фона - белый
  lpcmi.cbSize:= SizeOf(TMenuInfo);
  lpcmi.fMask:= MIM_BACKGROUND;
  GetMenuInfo(MainMenu.Handle, @lpcmi);
  MenuBarBackgroundOld:= lpcmi.hbrBack;
  lpcmi.fMask:= MIM_BACKGROUND or MIM_APPLYTOSUBMENUS;
  lpcmi.hbrBack:= MenuBarBackground.Handle;
  SetMenuInfo(MainMenu1.Handle, @lpcmi);
end;

procedure TMainForm.FormDestroy(Sender: TObject);
var
  lpcmi: TMenuInfo;
begin
  ZeroMemory(@lpcmi, SizeOf(TMenuInfo));
  lpcmi.cbSize:= SizeOf(TMenuInfo);
  lpcmi.fMask:= MIM_BACKGROUND;
  lpcmi.hbrBack:= MenuBarBackgroundOld;
  SetMenuInfo(MainMenu1.Handle, @lpcmi);
  MenuBarBackground.Free;
end; 
Hyper
новенький
 
Сообщения: 19
Зарегистрирован: 31.08.2016 11:15:06

Re: OwnerDraw TMenu

Сообщение Alex2013 » 07.09.2016 15:11:39

У меня в Лазарусе 1.4.2 второй вариант вызвал эффект из разряда "мистического кода" ...
Ставлю в начале FormCreate меню просто исчезает ставлю после всех моих инициализаций ничего не делает.
(Возможно из Аэро и Вин 7 ? )
Ps
Добавил в конце DrawMenuBar(Handle);

Получилось вот что (вместо "радикально красного меню" красная рамка ) :
ИзображениеИзображение
А это режим совместимости с XP...
ИзображениеИзображение
То есть нужно применять оба метода вместе ?
Ps.Ps.

Кстати для компиляция этой заплатки нужно подключить в Uses модуль Windows причем первым ... :idea:
Alex2013
долгожитель
 
Сообщения: 2963
Зарегистрирован: 03.04.2013 11:59:44

Re: OwnerDraw TMenu

Сообщение Hyper » 07.09.2016 20:20:27

Приветствую, Alex2013!
Да, нужно применять оба метода вместе - первый метод прорисовывает непосредственно меню и его пункты, а второй код - заливает белым цветом оставшуюся полоску меню (которая в моем скриншоте выше - серая).

:idea: У компонента TMainMenu в свойствах должно быть проставлено OwnerDraw = true, это свойство есть в компоненте, начиная с Lazarus 1.7, у Вас версия 1.4.2

(Возможно из Аэро и Вин 7 ? )

Нет, у меня на Windows 7 с включенным Aero всё нормально, на Windows 10 тоже все работает.
:idea: Версия Lazarus 1.4.2, скорее всего, не позволит реализовать корректно. Последняя версия Lazarus 1.6, моя версия Lazarus 1.7 собрана из транков.

OnDrawItem и OnMeasureItem находятся на вкладке "События" в TMainMenu, проверьте, есть ли такие свойства в Вашем Lazarus.

P.S. Если Вам понадобится Lazarus 1.7, пишите мне в ЛС, я могу отправить сборку.
Последний раз редактировалось Hyper 07.09.2016 22:03:00, всего редактировалось 1 раз.
Hyper
новенький
 
Сообщения: 19
Зарегистрирован: 31.08.2016 11:15:06

Re: OwnerDraw TMenu

Сообщение Лекс Айрин » 07.09.2016 20:32:49

Hyper, проще дать SVN svn co http://svn.freepascal.org/svn/lazarus/trunk ./new (я сначала кидаю в отдельную папку, а потом раскидываю по компам, поэтому такая странная папка получатель).
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: OwnerDraw TMenu

Сообщение Hyper » 07.09.2016 20:37:56

Лекс Айрин писал(а):Hyper, проще дать SVN svn co http://svn.freepascal.org/svn/lazarus/trunk ./new (я сначала кидаю в отдельную папку, а потом раскидываю по компам, поэтому такая странная папка получатель).

Здравствуйте! Еще можно дать инструкцию, как собрать Lazarus :)
http://wiki.freepascal.org/Installing_L ... 28Win32.29
Hyper
новенький
 
Сообщения: 19
Зарегистрирован: 31.08.2016 11:15:06

Re: OwnerDraw TMenu

Сообщение Лекс Айрин » 07.09.2016 20:47:38

Hyper, можно, конечно,.. но на форуме она легко доступна, а ссылку на сорцы могут и не заметить... хотя все есть.

ЗЫ: давать англоязычный вариант, если есть русский как-то странновато.

Кстати, иногда, по крайней мере в винде, выравнивают один пункт меню по правой стороне (справку). Если удастся подобное, то проблема исчезнет сама собой.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 10

Рейтинг@Mail.ru
cron