Как создать тот же стиль tMenuItem с AdvancedDrawItem?

Я хотел бы добавить линию с определенным цветом для каждого MenuItem всплывающего меню в приложении Tokyo VCL. Стиль "Аметист Камри".

Я вызываю событие AdvancedDrawItem каждого MenuItem, как показано ниже. Тем не менее, выделенный блок плоский и не имеет такой же трехмерной формы, как внешний вид без Ownerdraw.

Плоский фон (оранжевый): введите описание изображения здесь Пока я хотел бы получить его: введите здесь описание изображения Как это лучше реализовать? Делфи 10.2, VCL.

procedure TForm1.mnuColorAdvancedDrawItem(Sender: TObject; ACanvas: TCanvas;
  ARect: TRect; State: TOwnerDrawState);
var
  MenuItem : tMenuItem;
  LStyles  : TCustomStyleServices;
  LDetails : TThemedElementDetails;
begin
  MenuItem := (Sender as TMenuItem);
  LStyles  := StyleServices;

  ACanvas.Brush.Style := bsClear;

  ACanvas.Font.Color  := LStyles.GetStyleFontColor(sfPopupMenuItemTextNormal);

  //check the state
  if odSelected in State then
    begin
      ACanvas.Brush.Color := LStyles.GetSystemColor(clHighlight);
      ACanvas.Font.Color  := LStyles.GetSystemColor(clHighlightText);
    end;

  ACanvas.FillRect(ARect);
  ARect.Left := ARect.Left + 2;
  //draw the text
  ACanvas.TextOut(ARect.Left + 2, ARect.Top, MenuItem.Caption);

end;

Спасибо, Рерон.


person Reron    schedule 20.08.2018    source источник
comment
Возможно, вы могли бы добавить фрагмент изображения к своему вопросу для точного указания того, что вы хотите и что вы получаете в настоящее время (это может не стать видимым сразу, но кто-то здесь с достаточным числом повторений включит изображение). Используете ли вы стандартный стиль Windows или какие-либо специальные стили, поставляемые с Delphi?   -  person Tom Brunberg    schedule 20.08.2018
comment
Привет, Том, Стиль - это Аметист Камри, но это случается и с другими. Я не знаю, как захватить всплывающее окно. С моим кодом фон выбранного элемента представляет собой просто однородный прямоугольник оранжевого цвета, в то время как не-OwnerDraw имеет рамку вокруг него, и я думаю, что это какой-то градиентный оранжевый прямоугольник.   -  person Reron    schedule 21.08.2018
comment
С помощью инструмента Windows Snipping Tool вы можете делать снимки меню (также с наведенным на него элементом). Посмотрите в справке: Чтобы сделать снимок меню   -  person Tom Brunberg    schedule 21.08.2018
comment
Спасибо, Том, мне нравится! Моя ошибка в коде заключалась в использовании FillRect. Однако моя борьба за реализацию всплывающего элемента со стилем и флажком с AdvancedDrawItem все еще открыта.   -  person Reron    schedule 21.08.2018


Ответы (1)


Я более или менее нашел решение. Проблема заключалась в использовании Canvas FillRect. Предположим, есть три пункта всплывающего меню: красный, зеленый и синий. Цвет линии для каждого из них хранится в каждом поле тега. Каждая строка меню состоит из трех элементов: галочки, цветной строки и заголовка. Все три элемента имеют общее событие ColorAdvancedDrawItem.

Все методы рисования Owner основаны на стилях, а не на прямом рисовании Canvas, за исключением новых линий. См. код:

procedure TForm1.ColorAdvancedDrawItem(Sender: TObject; ACanvas: TCanvas;
  ARect: TRect; State: TOwnerDrawState);
const
  CheckBoxWidth = 20;
  LineLen       = 25;
var
  MenuItem : tMenuItem;
  LStyles  : TCustomStyleServices;
  LDetails : TThemedElementDetails;
  CheckBoxRect, LineRect, TextRect: TRect;
  Y: integer;
begin
  MenuItem := (Sender as TMenuItem);
  LStyles  := StyleServices;

  // Draw Check box
  if MenuItem.Checked then
    begin
      LDetails := StyleServices.GetElementDetails(tmPopupCheckNormal);
      CheckBoxRect := ARect;
      CheckBoxRect.Width := CheckBoxWidth;
      LStyles.DrawElement(ACanvas.Handle, LDetails, CheckBoxRect);
    end;

  // Draw text
  // Check the state
  if odSelected in State then
    LDetails := StyleServices.GetElementDetails(tmPopupItemHot)
  else
    LDetails := StyleServices.GetElementDetails(tmPopupItemNormal);

  TextRect      := ARect;
  TextRect.Left := CheckBoxWidth + LineLen;
  LStyles.DrawText(ACanvas.Handle, LDetails, MenuItem.Caption, TextRect, [tfLeft, tfSingleLine, tfVerticalCenter]);

  // Draw Line
  ACanvas.Pen.Color := tColor(MenuItem.Tag);
  ACanvas.Pen.Width := 2;
  LineRect := ARect;
  LineRect.Left := CheckBoxWidth;
  LineRect.Width:= LineLen;
  Y := LineRect.Top + (LineRect.Height div 2);
  ACanvas.MoveTo(LineRect.Left+2, Y);
  ACanvas.LineTo(LineRect.Left + LineRect.Width - 2, Y);
end;

Результат выглядит следующим образом: введите здесь описание изображения

person Reron    schedule 21.08.2018