Неправильно нарисованный тематический флажок в TVirtualStringTree

Обработка флажков в VirtualTrees.pas версии 5.0.0 не работает, если включен toThemeAware. Узлы csUncheckedNormal отображаются как отмеченные + горячие.

Чтобы правильно нарисовать неотмеченный тематический флажок с помощью DrawElement, запись Details должна быть: Element = teButton, Part = 3 и State = 5. Однако VirtualTrees.pas в конечном итоге вызывает DrawElement с State = 1, когда для узла установлено значение csUncheckedNormal. .

Кажется, что в VirtualTrees объявлено много косвенных и дополнительных констант, поэтому я не уверен, как лучше всего это исправить. Приветствуются идеи...

(Даже минимальный код для вывода TVirtualStringTree на экран и заполнения некоторыми данными слишком длинный для размещения здесь. Помимо основ, все, что необходимо для воспроизведения этого, — это включить toCheckSupport в TreeOptions.MiscOptions и установить Node.CheckType : = ctTriStateCheckBox в обратном вызове InitNode.)


person DaveS_Lifeway    schedule 18.04.2012    source источник
comment
Я сделал следующее прямо сейчас; поместил VirtualStringTree v.5.0.0 на форму, сохранил toThemeAware в PaintOptions, включил toCheckSupport в MiscOptions, добавил следующую строку кода в определенный обработчик событий VirtualStringTree1.AddChild(nil).CheckType := ctTriStateCheckBox;, запустил приложение из моего Delphi 2009 на Windows 7 и посмотрел у флажков вплотную; они были не в горячем состоянии. Итак, я вернулся сюда, чтобы написать этот комментарий, спросить вас, включены ли стили VCL (прежде чем заглянуть в код), проголосовал за ваш вопрос и нажал клавишу ENTER :-)   -  person TLama    schedule 18.04.2012
comment
Да, извините, это приложение с включенными стилями в Delphi XE2.   -  person DaveS_Lifeway    schedule 19.04.2012
comment
@TLama: если вы видите, что он рисуется правильно, мне было бы очень интересно узнать, что вы видите в паре мест в коде. А именно, значение ImageInfo.Index в TBaseVirtualTree.PaintCheckImage. У меня 9, что соответствует второму регистру, поэтому State := 9 - 8, что неверно. Индекс 9 исходит из TBaseVirtualTree.GetCheckImage, а константа ckCheckUncheckedNormal, которая является константой 9, находится в строке 122 VirtualTrees.pas. что-то должно быть другим, если вы видите, что оно отображается правильно. Спасибо!   -  person DaveS_Lifeway    schedule 19.04.2012
comment
Разница в том, что на момент проведения теста у меня была доступна только Delphi 2009, и у них не было стилей VCL. Одна общая вещь для обеих версий: флажок с тремя состояниями не является тремя состояниями (но это могут быть некоторые настройки). Теперь я проверил, что в Delphi XE2 и без включенных стилей VCL это работает, как и ожидалось (кроме трех состояний). Если вы используете стиль VCL, Node.CheckState равно csUncheckedNormal, но он также отображает проверенное горячее состояние, что, безусловно, неправильно. Я посмотрю на это, но это требует времени, и я должен работать над чем-то сейчас.   -  person TLama    schedule 19.04.2012


Ответы (1)


Что ж, поскольку я думаю, что VirtualTreeView не учитывает стили VCL при переносе на delphi XE2, это может помочь решить вашу проблему. Вы должны получить информацию об элементе, прежде чем рисовать его, иначе вы получите что-то вроде этого (это симуляция того, как устанавливается флажок рисования VirtualTreeView). Обратите внимание на другой порядок и артефакты; это результат того же кода один раз с отключенными стилями VCL, второй раз включенными:

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

Довольно странно, я знаю, но я не могу вам ответить, почему это происходит. Я могу просто сказать вам, что вы должны вызвать TThemeServices.GetElementDetails или, опционально, вычислите индекс состояния самостоятельно, чтобы обеспечить правильную работу рендеринга элемента. Вы можете попробовать использовать следующее исправление:

procedure TBaseVirtualTree.PaintCheckImage(Canvas: TCanvas; 
  const ImageInfo: TVTImageInfo; Selected: Boolean);
var
  // add a new variable for calculating TThemedButton state from the input
  // ImageInfo.Index; I hope ImageInfo.Index has the proper state order
  State: Integer;
begin
...
  case Index of
    0..8: // radio buttons
    begin
      // get the low index of the first radio button state and increment it by 
      // the ImageInfo.Index and get details of the button element
      State := Ord(TThemedButton(tbRadioButtonUncheckedNormal)) + Index - 1;
      Details := StyleServices.GetElementDetails(TThemedButton(State));
    end;
    9..20: // check boxes
    begin
      // get the low index of the first check box state and increment it by 
      // the ImageInfo.Index and get details of the button element
      State := Ord(TThemedButton(tbCheckBoxUncheckedNormal)) + Index - 9;
      Details := StyleServices.GetElementDetails(TThemedButton(State));
    end;
    21..24: // buttons
    begin
      // get the low index of the first push button state and increment it by 
      // the ImageInfo.Index and get details of the button element
      State := Ord(TThemedButton(tbPushButtonNormal)) + Index - 21;
      Details := StyleServices.GetElementDetails(TThemedButton(State));
    end;
  else
    Details.Part := 0;
    Details.State := 0;
  end;
...
end;

Я проверил это для всех типов проверки, и это работает для меня.

person TLama    schedule 19.04.2012
comment
Да, это действительно решает проблему. Интересно, однако, если бы это был тот же подход, который использовали бы авторы древовидной структуры. В частности, я думаю, что должна быть причина для всего массива CheckStateToCheckImage в GetCheckImage(), хотя я не знаю, что это такое, и мне кажется, что это еще один уровень констант, добавленный поверх уже существующего константы В любом случае это работает, спасибо! - person DaveS_Lifeway; 19.04.2012