Многоуровневые заголовки TDBGrid

Prot_XT
Дата: 13.07.2019 07:45:28
В общем реализовал у себя рисование многоуровневых заголовков... основу взял отсюда: НеОбычный TDBGrid.

Вот основные процедуры рисования заголовков оттуда:
+
  Procedure DrawSubHeader(ACol : Integer; Canvas : TCanvas);
  Var HRect : TRect;
  Begin				   
    // Получаем прямоугольник, объединяющий несколько колонок,
    // для которых рисуем сложный заголовок
    HRect:=GetHeaderRect(ACol);
    // По высоте берем только часть прямоугольника 
    // так как вторая часть — обычный заголовок
    HRect.Bottom:=RectHeight(HRect) div TITLE_SUBHEADER;
    Canvas.FillRect(HRect);

    // Вписываем текст,
    // который получаем методом GetHeaderText
    InflateRect(HRect,-1,-1);
    WriteText(Canvas, HRect, GetHeaderText(ACol) , taCenter);
	
    // Рисуем 3D-окантовку 
    Paint3dRect(Canvas.Handle,HRect);
  End; 

Function TexDBGrid.GetHeaderRect(ACol : Integer) : TRect;
Var MasterCol   : TColumn;
    Index,Shift ,
    Count,i     : Integer;
Begin		   
  // Если в опциях отключен показ сетки, это нужно учесть при расчете 
  // общего прямоугольника
  IF [dgColLines] * Options = [dgColLines] Then Shift:=1
  Else Shift:=0;

  Index:=ACol;
  Count:=1;				
  // получаем информацию для текущей колонки грида:
  // в какой объединяющий блок она входит 
  // Index — с какой колонки начинается объединяющий блок
  // Count — сколько колонок он включает
  IF Assigned(FOnGetHeaderRect) Then FOnGetHeaderRect(ACol, Index, Count);

  IF Index+Count-1 > Columns.Count-1 Then
  Begin
    Index:=ACol;
    Count:=1;
  End;
  
  // В результате нужно получить прямоугольник, состоящий из
  // всех, включенных в объединенный блок колонок
  Result:=CalcTitleRect(Columns[Index],0,MasterCol);

  For i:=Index+1 To Index + Count -1 Do
  Result.Right:=Result.Right + RectWidth(CalcTitleRect(Columns[i] ,0,MasterCol)) + Shift;

End;

Const
   GeoColumns   = 3;
   ParamColumns = 2;
...   
//----------------------------------------------------------------------------------------
// Получить для текущей колонки информацию о том, в какое объеденение колонок она попадает
//----------------------------------------------------------------------------------------
procedure TfExDBG.GetHeaderRect(ACol: Integer; var IndexStart,  Count: Integer);
begin
  IF ACol < GeoColumns
  Then Begin
         IndexStart:=0;
         Count:=GeoColumns;
       End
  Else Begin
         IndexStart:=GeoColumns;
         Count:=ParamColumns;
       End
end;

То есть заголовок рисуется с индекса колонки и количество колонок, которые туда входят, в принципе все работает. Однако есть существенный недостаток... при горизонтальном скроллинге, когда часть таблицы уходит влево, объединенный заголовок перерисовывается заново и считает, что колонка от которой должен быть старт рисования прямоугольника всегда остается у края... никуда не смещаясь за границы экрана. В итоге визуально заголовок плывет и перемещается вместе со скроллом, "оставаясь" на месте и потом пытаясь "наползти" и перерисоваться в ячейках, где он вообще не должен быть. Заголовок должен уйти за пределы отображаемого грида.

Не могу понять, как можно поправить, чтобы объединенный заголовок отрисовался нормально.
Prot_XT
Дата: 13.07.2019 13:41:44
Ну... скорее всего вряд ли в этом коде, кто разбираться будет... )))
Для себя набросок как это сделать набросал... не знаю правда на сколько он грамотен.
В идеале заголовки рисуются правильно только когда они все видны и на канве можно без проблем рисовать.
Если начинаем скроллить, пошла каша... скроллинг в обычном гриде осуществляется скачками по одной колонке.
Там где скролл переписан и плавный... такое конечно не пойдет.
Соответственно можно узнать каких колонок нет, посчитать их ширину и указать TRect рисуемого прямоугольника в заголовке смещение на ширину отсутствующих колонок.
Теперь вопрос... а как определить индекс первой, визуально видимой колонки?
L_argo
Дата: 14.07.2019 21:11:26
Возьмите нормальный грид и не морочьте себе голову. Тот же ehlib.
ДБГрид - полнейший отстой, который можно только выкинуть.
Док
Дата: 14.07.2019 21:25:44
L_argo
ДБГрид - полнейший отстой, который можно только выкинуть.

Почему же? На нем хорошо тренироваться, что выше упомянутая статья и показала. Может, ТС потом свой компонент напишет?

зы. Кстати, ЭхЛиб грид изначально наследовался от дбгрида, лишь потом Большаков его заново от CustomControl переписал.
ёёёёё
Дата: 14.07.2019 22:39:46
L_argo
Возьмите нормальный грид и не морочьте себе голову. Тот же ehlib.
ДБГрид - полнейший отстой, который можно только выкинуть.


+100, "стандартный" только для демок годится.
Мигалка
Дата: 15.07.2019 08:29:04
в стандартном дбгриде есть всякие сложные заголовки. но нужен специально обученный датасет. в д5 есть демка alchtest.dpr
Prot_XT
Дата: 15.07.2019 09:52:10
Большое спасибо конечно, но я не ставил вопрос, а какой грид обладает той или иной фичей...
Я и так знаю... Меня интересует правильная реализация рисования компонентов самому.
Зачем мне это нужно... оставим это мне )))
Инфы просто об этом нуль...
white_nigger
Дата: 15.07.2019 12:19:18
Prot_XT
Инфы просто об этом нуль...
... или кто-то не умеет искать. Целые книги есть по созданию компонентов.
Мигалка
Дата: 15.07.2019 13:24:01
а вообще, это идеологически неправильно - рисовать в других ячейках. надо чтоб каждая из объединённых ячеек могла отрисовать на себе кусочек общей ячейки. тогда при скроллинге всё автоматом правильно нарисуется
Prot_XT
Дата: 16.07.2019 10:07:56
Мигалка,
Уф... спасибо за мысль... а то я что-то в дебри полез. Хотел сдвиг вычислять и т.д.
Короче обрабатываю исключительно ячейку, если визуально все ячейки входящие в блок видны, то рисую полный многоугольник (объединяю ячейки которые входят в блок),
если часть ячеек уехала... выкидываю эту часть из большого многоугольника и рисую его на оставшихся частях...
Все идеально работает!
Теперь еще одна проблема осталась... текст в объединенной ячейке...
Я его вписываю в прямоугольник:
 WriteText(Canvas, Rect, Caption, taCenter);

Однако... ну он всегда тупо по центру... гы гы
А надо то эмулировать, что он уезжает влево при скролле.
Есть какие-нить мысли, что можно придумать?