Delphi - TTreeView: множественный корень не рисуется хорошо, если он был пуст ранее
Я использую TTreeView в Delphi.
Если
- TreeView был пуст до первого Items.BeginUpdate AND
- Теперь есть несколько корневых узлов И
- Я установил Выбранный элемент между BeginUpdate(s) и EndUpdate(s) AND
- После отрисовки последнего Items.EndUpdate вертикальная полоса прокрутки не будет отображаться (все узлы будут помещаться в клиентской области)
первый нарисованный элемент будет последним корневым узлом. (Выбранный элемент правильно настроен.)
Если я поднимусь на 1 шаг вверх со стрелкой вверх на клавиатуре (от этого последнего корневого узла, теперь первого в списке), то обнаружатся скрытые узлы.
Я перепробовал много вещей, таких как:
If Assigned(Selected)
Then SendMessage(Handle, TVM_SELECTITEM, TVGN_CARET, LPARAM(Selected.ItemId))
Else SendMessage(Handle, TVM_SELECTITEM, TVGN_CARET, LPARAM(0));
Refresh; //=Repaint
RedrawWindow(Handle, 0, 0, RDW_ERASE Or RDW_FRAME Or RDW_INVALIDATE Or RDW_ALLCHILDREN Or RDW_UPDATENOW Or RDW_INTERNALPAINT);
RedrawWindow(Handle, 0, 0, RDW_NOERASE Or RDW_VALIDATE Or RDW_ALLCHILDREN Or RDW_UPDATENOW Or RDW_INTERNALPAINT);
RedrawWindow(Handle, 0, 0, RDW_ERASE Or RDW_VALIDATE Or RDW_ALLCHILDREN Or RDW_UPDATENOW Or RDW_INTERNALPAINT);
UpdateWindow(Handle);
Refresh; //=Repaint
и так далее... Кажется, ошибка не в Delphi, а в Windows.
Этот код исправляет проблему:
Я не знаю, был ли я между BeginUpdate и EndUpdate, поэтому мне нужно увеличить счетчик обновлений: (без этого, если я НЕ нахожусь между BeginUpdate и EndUpdate, установка WM_SETREDRAW=0 заморозит дерево навсегда) (4)
Items.BeginUpdate;
Это устраняет проблему: (2)
SendMessage(Handle, WM_SETREDRAW, 1, 0);
Выбор: (1)
PrSelected := SelectNode;
Обратное WM_SETREDRAW: (без этого позже дерево рисует, даже если я останусь между BeginUpdate и EndUpdate после EndUpdate здесь) (3)
SendMessage(Handle, WM_SETREDRAW, 0, 0);
Напротив моего настоящего BeginUpdate (5)
Items.EndUpdate;
(Числа - это порядок причинности)
Вопросы:
- Почему / что это за ошибка?
- Есть более приятный / легкий ремонт? Например, одно сообщение или процедура (вместо BeginUpdate -> WM_SETREDRAW=1 ---> WM_SETREDRAW=0 -> EndUpdate)
- Могу ли я сказать TreeView "прокрутить вверх, даже если у вас нет полосы прокрутки"?
- Могу ли я получить состояние Items.BeginUpdate/EndUpdate/FUpdateCount?
- Могу ли я получить состояние WM_SETREDRAW?
На самом деле я создаю потомка из TTreeView, поэтому я могу использовать защищенные методы или подобные вещи.