Components for Delphi and C++ Builder.

Перейти в английский форум
Перейти на EhLib.com
Текущее время: 15 апр 2021, 23:01

Часовой пояс: UTC




Начать новую тему Ответить на тему  [ Сообщений: 20 ] 
Автор Сообщение
 Заголовок сообщения: Отрисовка границ ячеек
СообщениеДобавлено: 15 апр 2012, 18:52 
Не в сети

Зарегистрирован: 21 фев 2012, 16:37
Сообщений: 18
Существует ли в Ehlib какой-нибудь штатный способ изменить отрисовку границ у ячеек TDBGridEh? Или только путём рисования на канвасе? Пример конкретной задачи - нужно изменить толщину и цвет правой границы только определённых ячеек (в зависимости от их содержимого, например). Сейчас данную задачу решаем следующим образом - в OnDrawColumnCell засовывается следующий код:
Код:
      if *некое условие* then
      begin
        (Sender as TCustomDBGridEh).Canvas.Pen.Color := clBlack;
        (Sender as TCustomDBGridEh).Canvas.Pen.Width := 2;
        (Sender as TCustomDBGridEh).Canvas.MoveTo(Rect.Right, Rect.Top);
        (Sender as TCustomDBGridEh).Canvas.LineTo(Rect.Right, Rect.Bottom);
      end;

Данный метод работает, но вызывает ряд проблем с отрисовкой грида. Так, например, если включен OptionsEh.dghExtendVertLines, то "продолжения" вертикальных границ ячеек начинают всегда прорисовываться толщиной в 2 пикселя, а при быстрой горизонтальной прокрутке грида появляются артефакты прорисовки. Что можете порекомендовать?


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 22 апр 2012, 22:27 
Не в сети
Администратор

Зарегистрирован: 19 дек 2011, 17:40
Сообщений: 837
Добрый день.

В текущей версии библиотеки можно влиять только на два базовых цвета линий.

DBGridEh1.GridLineColors.DarkColor - цвет линий разделяющей фиксированные ячейки.
DBGridEh1.GridLineColors.BrightColor - цвет линий разделяющей ячейки c данными.

После прорисовки не забывайте возвращать старое значения свойств объектов канваса

Код:
        OldColor := (Sender as TCustomDBGridEh).Canvas.Pen.Color;
        OldWidth := (Sender as TCustomDBGridEh).Canvas.Pen.Width;
        (Sender as TCustomDBGridEh).Canvas.Pen.Color := clBlack;
        (Sender as TCustomDBGridEh).Canvas.Pen.Width := 2;
        (Sender as TCustomDBGridEh).Canvas.MoveTo(Rect.Right, Rect.Top);
        (Sender as TCustomDBGridEh).Canvas.LineTo(Rect.Right, Rect.Bottom);
        (Sender as TCustomDBGridEh).Canvas.Pen.Color := OldColor;
        (Sender as TCustomDBGridEh).Canvas.Pen.Width := OldWidth;

Best regards
Admin

_________________
Best regards
Admin


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 03 мар 2021, 13:36 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Прошло почти 9 лет, очень надеюсь, что в версии 10.x функционал в плане отрисовки линий расширился.

Благодаря примеру выше я могу отрисовать вертикальные линий для заданных строк (чёрные линии на Screen1.png).
Подскажите, пожалуйста, а как задать цвет отрисовки горизонтальных линий (сверху и снизу) для заданных строк (красные линии на Screen1.png)?

И ещё как задать вертикальные и горизонтальные линии для текущей выделенной строки (красные линии на Screen2.png)?

Очень надеюсь на Вашу помощь!
Спасибо

P.S. В документации всё перерыл - не нашёл решения


Вложения:
Screen1.png
Screen1.png [ 16.46 KiB | Просмотров: 426 ]
Screen2.png
Screen2.png [ 9.66 KiB | Просмотров: 426 ]
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 04 мар 2021, 00:29 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1200
Добрый день.

Для отрисовки окантовки ячеек грида вы можете использовать событие TColumnEh.OnAdvDrawDataCell
Обработчик события необходимо присвоить каждой колонке грида.

В событии понадобиться обращения к protected методам грида.
Код:
type
  TDBGridEhCrack = class(TCustomDBGridEh);

а также возможность обращения к следующей записи грида для корректной отрисовки нижней линии для окантовки следующей ячейки.

Код:
  if (AreaCell.Y < Grid.InstantReadRecordCount - 1) then
  begin
    try
      Grid.InstantReadRecordEnter(AreaCell.Y + 1);
      NextRowIsSpecial := MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1;
    finally
      Grid.InstantReadRecordLeave;
    end;
  end;


Полный код обработчика события приведен ниже:

Код:
type
  TDBGridEhCrack = class(TCustomDBGridEh);

procedure TForm1.DBGridEh1Columns0AdvDrawDataCell(Sender: TCustomDBGridEh; Cell,
  AreaCell: TGridCoord; Column: TColumnEh; const ARect: TRect;
  var Params: TColCellParamsEh; var Processed: Boolean);
var
  Grid: TDBGridEhCrack;
  NextRowIsSpecial: Boolean;
begin
  Grid := TDBGridEhCrack(Sender);
  NextRowIsSpecial := False;

  if (MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1) then
  begin
    Params.Background := $006DD3EB;
    Params.Font.Style := [fsBold];
  end;

  Grid.DefaultDrawColumnDataCell(Cell, AreaCell, Column, ARect, Params);

  if (AreaCell.Y < Grid.InstantReadRecordCount - 1) then
  begin
    try
      Grid.InstantReadRecordEnter(AreaCell.Y + 1);
      NextRowIsSpecial := MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1;
    finally
      Grid.InstantReadRecordLeave;
    end;
  end;

  if (MemTableEh1.FieldByName('SpecialBorderState').AsInteger = 1) then
  begin
    Grid.Canvas.Pen.Color := clRed;
    Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right, ARect.Bottom)]);
    Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Right, ARect.Top), Point(ARect.Right, ARect.Bottom+1)]);
    if (AreaCell.X = 0) then
      Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Top), Point(ARect.Left, ARect.Bottom+1)]);
  end else if NextRowIsSpecial then
  begin
    Grid.Canvas.Pen.Color := clRed;
    Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right+1, ARect.Bottom)]);
  end;

  Processed := True;
end;


Демо проект прилагается.
В Демо проекте в Unit2 приведен пример реализации окантовки через наследование грида.


Вложения:
2021-03-03-ColoringGridLines.zip [9.54 KiB]
Скачиваний: 17
sshot-174.png
sshot-174.png [ 31.95 KiB | Просмотров: 404 ]

_________________
Best regards
EhLib support Team
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 04 мар 2021, 08:40 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Просто фантастика!! Это то, что нужно. Спасибо Вам ОГРОМНОЕ!!
Вы всегда находите решение и делаете это оперативно. Отличная поддержка.

Единственный момент, можно ли задавать цвет границ для текущей строки (синим цветом на примере)?
У меня остаются артефакты при перемещении к следующей строке.


Вложения:
Screen3.png
Screen3.png [ 38.32 KiB | Просмотров: 393 ]
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 04 мар 2021, 16:17 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1200
Добрый день.

Чтобы ушли артефакты при перемещении на следующую строку необходимо перерисовывать весь грид.
Добавьте следующее событие

Код:
procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
  DBGridEh1.Invalidate;
end;

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 04 мар 2021, 21:28 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Добрый день.
Это именно то, чего не хватало! Теперь всё работает именно так, как нужно.
Надеюсь только, что постоянные вызовы DBGridEh1.Invalidate при переходе к следующий записи в гриде не сильно скажутся на скорости.

Вы меня очень выручили.
Спасибо вам БОЛЬШОЕ!! :D :D :D


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 09 мар 2021, 20:39 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Добрый день.
Вынужден снова обратиться к Вам за помощью.
Всё отлично работает, благодаря Вам.
Но есть нюанс:
Цитата:
а также возможность обращения к следующей записи грида для корректной отрисовки нижней линии для окантовки следующей ячейки.

Чтобы обратить к следующей записи грида нужно, чтобы он был подключен через MemTableEh. В этом случае всё отлично работает.
Но в нашем проекте очень много форм, где грид подключен напрямую к TFDQuery (FireDAC) и там прочитать значение следующей записи без изменения текущей (как в MemTableEh) нельзя.
По-крайней мере, насколько мне известно.

Чтобы добавить во все формы посредника в виде MemTableEh - это очень большой фронт работы и в разумные сроки сделать это нереально.
Можно ли каким-то образом прочитать из грида значение заданной ячейки?
Например, находясь в колонке 1 и строке 1 получить значение из колонки 1 и строки 2. При этом оставаясь в 1-й строке.

Очень жду ответа.
Спасибо Вам большое!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 10 мар 2021, 02:39 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 52
Откуда: ЗАО БоАЗ
бегать по датасету без генерации событий на свой страх и риск.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 10 мар 2021, 07:28 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
istrebitel писал(а):

Причём здесь датасет.
Цитата:
...прочитать из грида...

К слову, и датасет датасету рознь. Где-то есть подобный функционал. Но это другая тема.
Вопрос по-прежнему открытый.

Из текущей строки без проблем получаю значение любой ячейки функцией:
GetEditText(ACol, ARow: Longint)
Но работает, к сожалению, только для текущей строки.


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 10 мар 2021, 09:16 
Не в сети

Зарегистрирован: 16 фев 2018, 04:13
Сообщений: 52
Откуда: ЗАО БоАЗ
GoldMedium писал(а):
...прочитать из грида...

в гриде данных нет

GoldMedium писал(а):
К слову, и датасет датасету рознь. Где-то есть подобный функционал. Но это другая тема.
Вопрос по-прежнему открытый.

Этот функционал и есть стандартный, грид именно этим функционалом и бежит по датасету когда его отрисовывает.
Код:
procedure TCustomDBGridEh.DrawDataCell(ACol, ARow: Longint;
  AreaCol, AreaRow: Longint; ARect: TRect; AState: TGridDrawState;
  CellAreaType: TCellAreaTypeEh);
///
begin
  ///

  InstantReadRecordEnter(AreaRow);

end.

procedure TCustomDBGridEh.InstantReadRecordEnter(DataRowNum: Integer);
var
  InstReadNode: TGroupDataTreeNodeEh;
begin
  if ViewScroll then
  begin
  end else
  begin
      // всё что не MemTable (все остальные датасеты)
    FOldActiveRecord := DataLink.ActiveRecord;
    DataLink.ActiveRecord := DataRowNum;
  end;
end;



Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 10 мар 2021, 09:36 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Спасибо Вам за участие и желание помочь. Я понимаю, что в гриде данных нет.
Просто отчаянно ищу решение, чтобы избежать большого объёма работ. Дергать каждый раз при отрисовке датасет не лучшее решение


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 10 мар 2021, 15:04 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1200
Если тип датасета не MemTableEh, то следующий обработчик события должен работать.

Код:
procedure TForm1.DBGridEh1Columns0AdvDrawDataCell(Sender: TCustomDBGridEh; Cell,
  AreaCell: TGridCoord; Column: TColumnEh; const ARect: TRect;
  var Params: TColCellParamsEh; var Processed: Boolean);
var
  Grid: TDBGridEhCrack;
  NextRowIsSpecial: Boolean;
  BottomLineIsDrawn: Boolean;
  LinesIsDrawn: Boolean;
  DataSet: TDataSet;
  OldActiveRecord: Integer;
begin
  Grid := TDBGridEhCrack(Sender);
  DataSet := Grid.DataSource.DataSet;
  NextRowIsSpecial := False;

  if (DataSet.FieldByName('SpecialBorderState').AsInteger = 1) then
  begin
    Params.Background := $006DD3EB;
    Params.Font.Style := [fsBold];
  end;

  Grid.DefaultDrawColumnDataCell(Cell, AreaCell, Column, ARect, Params);

  if (AreaCell.Y < Grid.InstantReadRecordCount - 1) then
  begin
    try
      //Grid.InstantReadRecordEnter(AreaCell.Y + 1);
      OldActiveRecord := Grid.DataLink.ActiveRecord;
      Grid.DataLink.ActiveRecord := AreaCell.Y + 1;
      NextRowIsSpecial := DataSet.FieldByName('SpecialBorderState').AsInteger = 1;
    finally
      //Grid.InstantReadRecordLeave;
      Grid.DataLink.ActiveRecord := OldActiveRecord;
    end;
  end;

  LinesIsDrawn := False;
  BottomLineIsDrawn := False;

  if (Params.Row = Grid.Row) or (Params.Row = Grid.Row - 1) then
  begin
    Grid.Canvas.Pen.Color := clBlue;
    if (Params.Row = Grid.Row) then
    begin
      Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right, ARect.Bottom)]);
      Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Right, ARect.Top), Point(ARect.Right, ARect.Bottom+1)]);
      if (AreaCell.X = 0) then
        Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Top), Point(ARect.Left, ARect.Bottom+1)]);
      LinesIsDrawn := True;
      BottomLineIsDrawn := True;
    end else
    begin
      Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right+1, ARect.Bottom)]);
      BottomLineIsDrawn := True;
    end;
  end;

  if (DataSet.FieldByName('SpecialBorderState').AsInteger = 1) and not LinesIsDrawn then
  begin
    Grid.Canvas.Pen.Color := clRed;
    if not (BottomLineIsDrawn) then
      Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right, ARect.Bottom)]);
    Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Right, ARect.Top), Point(ARect.Right, ARect.Bottom+1)]);
    if (AreaCell.X = 0) then
      Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Top), Point(ARect.Left, ARect.Bottom+1)]);
  end else if NextRowIsSpecial and not BottomLineIsDrawn then
  begin
    Grid.Canvas.Pen.Color := clRed;
    Grid.DrawPolyline(Grid.Canvas, [Point(ARect.Left, ARect.Bottom), Point(ARect.Right+1, ARect.Bottom)]);
  end;

  Processed := True;
end;

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 10 мар 2021, 18:38 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Просто подарок! Всё отлично отрабатывает!
Не представляете, как Вы меня выручили. Сэкономили мне вагон времени.
Спасибо ВАМ большое!!!


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 12 мар 2021, 07:48 
Не в сети

Зарегистрирован: 24 дек 2011, 14:04
Сообщений: 237
Откуда: Украина, г. Днепропетровск
GoldMedium писал(а):
Добрый день.
Чтобы добавить во все формы посредника в виде MemTableEh - это очень большой фронт работы и в разумные сроки сделать это нереально.
Можно ли каким-то образом прочитать из грида значение заданной ячейки?
Например, находясь в колонке 1 и строке 1 получить значение из колонки 1 и строки 2. При этом оставаясь в 1-й строке.

FireDAC (FDQuery, FDMemTable) может как и MemTableEh перемещается по записям не меняя текущую позицию курсора

Цитата:
http://www.sql.ru/forum/actualutils.aspx?action=gotomsg&tid=1008012&msg=21419431

TFDDatSRow есть запись. Объект создается для каждой записи.

Скажем пробежаться по внутренностями TFDDataSet

for i := 0 to FDQuery1.SourceView.Rows.Count - 1 do
FDQuery1.SourceView.Rows[i].GetData(0);

http://www.sql.ru/forum/actualutils.asp ... g=21513141
SourceView.Rows - с учетом фильтра и сортировки
Table.Rows - без учета


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 12 мар 2021, 10:30 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Большое спасибо, не знал. Это просто здорово :)

Сравнил у себя скорость отрисовки границ при использовании Grid.DataLink.ActiveRecord и FDQuery1.SourceView.Rows[i].GetData(0).
Оказалось, что вариант Grid.DataLink.ActiveRecord всегда чуть быстрее. Ненамного, но стабильно.
Поэтому остановился пока на первом варианте.

Но за подсказку большое спасибо, буду иметь ввиду


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 12 мар 2021, 11:01 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Что касается скорости, есть вопрос по перерисовке грида.
В таблице с 12 колонками, у большинства из которых цвет фона и шрифта меняется в зависимости от значения ячейки, при прокрутке остаётся шлейф из линий, которым выделяется текущая строка.
Grid.Invalidate выполняется в событии OnDataChange у DataSource.
Вероятнее всего при прокрутке грид прорисоваться не успевает и сообщения Invalidate помещаются в очередь. Отсюда заметные артефакты на экране.
С гридами, где меньше цветной раскраски, всё отрабатывает незаметно.

Грид подключен через FDQuery


Вложения:
Simple.gif
Simple.gif [ 120.32 KiB | Просмотров: 265 ]
Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 12 мар 2021, 12:34 
Не в сети

Зарегистрирован: 21 дек 2011, 18:48
Сообщений: 1200
Добрый день.

Вместо DBGridEh.Invalidate; можно попробовать использовать DBGridEh.Repaint;
Отрисовка должна происходить сразу, в коде Repaint.
Но это может замедлить навигацию по гриду.

_________________
Best regards
EhLib support Team


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 12 мар 2021, 12:52 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
Добрый день.
Спасибо, проверил. Не помогло, шлейф такой же.
Пробовал добавить DBGridEh.Repaint ещё и в событие AfterScroll. Артефакты отрисовки без изменений.
Вероятно, надо искусственно замедлять навигацию, чтобы грид успевал прорисоваться


Вернуться наверх
 Профиль  
 
 Заголовок сообщения: Re: Отрисовка границ ячеек
СообщениеДобавлено: 15 мар 2021, 08:52 
Не в сети

Зарегистрирован: 24 дек 2012, 11:18
Сообщений: 64
В общем, кажется нашёл причину/решение артефактов при прокрутка своего грида. Причина была не в количестве колонок и их отрисовки, а банально в количестве контролов, связанных с тем же DataSource. У меня их было 15-20. Если у всех, кроме грида, обнулить DataSource - прокрутка выполняется быстро и без артефактов.
Похоже нужно при прокрутке отключать обновление (DisableControls) всем контролам, кроме грида.
Иначе Grid.Invalidate в событии TDataSource.OnDataChange просто не успевает


Вернуться наверх
 Профиль  
 
Показать сообщения за:  Сортировать по:  
Начать новую тему Ответить на тему  [ Сообщений: 20 ] 

Часовой пояс: UTC


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB