Nano Hash - криптовалюты, майнинг, программирование

Отображать дополнительный текст в узлах дерева, а не только node.text

У меня есть TTreeView в Delphi с узлами на трех уровнях.

Я использую данные узла для хранения другой метки помимо текста узла.

Type
  TNodeData = class
    ExtraNodeLabel: WideString;
    //... other members
  end;

У меня есть событие OnAdvancedCustomDrawItem, где я хочу отобразить это ExtraNodeLabel перед текстом узла. Я хочу добиться этого:

  • Синий текст будет дополнительной меткой.
  • выделенный элемент: первые два слова также являются дополнительной меткой

введите здесь описание изображения

То, что я получил до сих пор, это:

введите здесь описание изображения

Проблемы:

  1. По какой-то причине я не могу рисовать текст другим стилем, если использую DrawText/drawTextW (мне нужен drawtextW из-за данных юникода)
  2. Другая проблема заключается в том, что все, что находится за пределами пунктирного прямоугольника фокуса, недоступно для щелчка.

Что нужно решить:

  1. Как я могу рисовать текст в другом стиле, используя DrawText/DrawtextW
  2. Как сделать кликабельным весь текст?

Код:

procedure TMainForm.TntTreeView1AdvancedCustomDrawItem(
  Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
  Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean);
var
  txtrect, fullrect : TRect;
  DC: HDC;
  fs: integer;
  fc: TColor;
  ExtralabelRect: TRect;
  nData: TNodeData;
begin
  nData := nil;

  if assigned(Node.Data) then begin
    nData := TNodeData(Node.Data);
  end;

  DC := TntTreeView1.canvas.Handle;
  txtRect := Node.DisplayRect(True);    
  fullrect := Node.DisplayRect(False);

  if stage = cdPostPaint then begin
    TntTreeView1.Canvas.FillRect(txtRect);
    if (cdsFocused In State) And (cdsSelected in State) then begin
      DrawFocusRect(DC,txtRect);
    end;

    txtRect.Left := txtRect.Left + 1;
    txtRect.Top := txtRect.Top + 1;
    txtRect.Right := txtRect.Right - 1;
    txtRect.Bottom := txtRect.Bottom - 1;

    ExtralabelRect := txtRect;

    fs := TntTreeView1.Canvas.Font.size;
    fc := TntTreeView1.Canvas.Font.Color;

    if (nData <> nil) And (nData.ExtraNodeLabel <> '') then begin
      TntTreeView1.Canvas.Font.Size := 7;
      TntTreeView1.Canvas.Font.color := clBlue;
      DrawTextW(
        DC,
        PWideChar(nData.ExtraNodeLabel),
        Length(nData.ExtraNodeLabel),
        ExtraLabelRect,
        DT_LEFT or DT_CALCRECT or DT_VCENTER
      );

      DrawTextW(
        DC,
        PWideChar(nData.ExtraNodeLabel),
        Length(nData.ExtraNodeLabel),
        ExtraLabelRect,
        DT_LEFT or DT_VCENTER
      );

      txtRect.right := txtRect.Right + ExtraLabelRect.Right + 5;
      txtRect.Left := ExtraLabelRect.Right + 5;
    end;

    TntTreeView1.Canvas.Font.Size := fs;
    TntTreeView1.Canvas.Font.color := fc;

    DrawTextW(
      DC,
      PWideChar((Node as TTntTreeNode).Text),
      -1,
      txtRect,
      DT_LEFT or DT_VCENTER
    );
  end;
end;

  • Ваш номер 2, вероятно, связан с тем фактом, что дерево измеряет ширину текста своего узла, чтобы определить прямоугольник фокуса, и это не принимает во внимание ваш дополнительный текст. Чтобы решить эту проблему, вам нужно либо добавить текст в Text узла, либо создать свой собственный потомок TTreeview и найти способ переопределить/подключиться к измерению ширины для прямоугольника фокуса (быстрое чтение документация не приводит к каким-либо очевидным событиям). 05.07.2013
  • Как говорит @Marjan. Нет ничего похожего на TVM_SETITEMRECT или TVM_SETITEMHEIGHT, сообщение уведомления или макрос для установки ширины узла. Я бы сказал, вам нужно будет установить значение свойства TTreeNode.Text для правильного увеличения ширины узла. 05.07.2013
  • К сожалению, я не могу установить свойство TTreeNode.Text, так как это значение не должно сохраняться вместе с текстом узла. 05.07.2013
  • Кроме того, первая проблема более важна, так как если ее можно решить, вторая может не понадобиться (я мог бы поиграть с высотой элемента и использовать 2 разных размера шрифта). 05.07.2013
  • как насчет VirtualTreeView? 05.07.2013
  • @TLama Да, но мне нужно использовать разные стили, поэтому этап предварительной покраски не сработает. 05.07.2013
  • @Arioch 'VirtualTreeview не вариант, так как эта программа представляет собой большой проект, разрабатываемый в течение многих лет. Я хотел бы использовать его, но замена элемента управления займет слишком много времени, и есть экономические соображения. 05.07.2013
  • Пользовательское рисование в элементе управления древовидным представлением comctl32 очень сложно сделать правильно. Удачи! 05.07.2013
  • То же самое для TreeNT? не пробовал, так что не знаю, сильно ли его APi отличается от TreeView... 05.07.2013
  • @Arioch 'The: Я хотел сказать вам, что замена элемента управления здесь не вариант, у меня связаны руки. 05.07.2013

Ответы:


1

Решение от ОП

Мне удалось частично решить пользовательский рисунок, определив переменную TFont и используя SelectObject и setTextColor. Настройка цвета и стиля шрифта работает, но установка размера шрифта не работает.

var 
  nFont: TFont;
begin
  DC := TntTreeView1.Canvas.Handle;
  NFont := TFont.Create;

  // rest of the code here ...

  // i tried to set nFont.Size, but it doesn't seem to work
  nFont.Size := 7;
  nFont.Color := colorToRGB(clBlue);
  nFont.Style := TntTreeview1.Font.Style + [fsBold];

  SelectObject(DC,NFont.Handle);
  SetTextColor(DC,colortoRGB(clBlue));

  DrawTextW(
    DC,
    PWideChar(nData.nodeLabel),
    Length(nData.nodeLabel),
    ExtraLabelRect,
    DT_LEFT or DT_VCENTER
  );

  // rest of the code here
end;

Источник: я использовал идею отсюда


Обновление 2

Я решил вторую проблему, установив для свойства RowSelect дерева значение true. Чтобы это работало, мне пришлось установить для свойства ShowLines значение false, а также нарисовать линии и кнопки. Теперь это работает.


Обновление 3

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

// set font size for the canvas font (font style can be set the same time)
TntTreeView1.Canvas.Font.Size := 7;

// select canvas font for DC
SelectObject(DC,TntTreeView1.Canvas.Font.Handle);

// set font color
SetTextColor(DC,colortoRGB(clBlue));
15.05.2014
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..