Компоненты TListView, TTreeView прекрасны тем, что с ними можно быстро слепить прототип какого то решения задачи. В добавок в них есть реализация собственной отрисовки внешнего вида, которая позволяет подстраивать их под нужды проекта. Некоторые процедуры не работают, если не включить их соответствующей опцией, переориентировав на работу по другой логике. Но есть и такие, которые работают всегда. И иногда позволяют творить магию.
Вот представьте, программа компилируется, все отрабатывает почти идеально. И в какой то момент развития добавив функционал оказывается что TAction не обрабатывает события Update. Странное дело, наверно разработчики FPC не до конца допилили ядро, и через кучу друг в друга вложенных форм, панелек и т.д. не проходит оповещение. Но вот не задача, есть InputQuery, который появляется, но не закрывается при нажатии на его кнопки. Совсем.
Тут можно долго биться головой о стену, доказывая что они идиоты, но на самом деле причина багов в CustomDrawItem класса TListView. Скажем так, если сделать такой код
- Код: Выделить всё
procedure TFReport.lvProjectCustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
rlItem :TReportLogItem;
begin
if Assigned(Item) and Assigned(Item.Data) then
begin
rlItem:=TReportLogItem(Item.Data);
if (DateUtils.DateTimeToUnix(rlItem.CreateDate)+10)>DateUtils.DateTimeToUnix(now) then
begin
(Sender as tlistview).Canvas.Brush.Color := $00FAFFEC;
end;
end;
end;
тот тут нет ничего плохого, но вот если вместо него окажется что то вроде
- Код: Выделить всё
procedure TFCableLayingEditor.lvSubItemsCustomDrawItem(Sender: TCustomListView;
Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
var
TmpItem:TAssiBasicObjectItem;
begin
if Assigned(Item.Data) then
begin
TmpItem :=TAssiBasicObjectItem(Item.Data);
Item.Caption :=TmpItem.GetParameter('LabelName');
Item.SubItems.Strings[0] :='';
Item.SubItems.Strings[1] :=FloatToStr(TmpItem.GetParameter('Count'));
end;
end;
то программа будет работать, медленнее чем может, но будет. И это будет продолжаться до того момента, пока код не разрастется и не перестанет выполнять простые InputQuery.
К сожалению, для обновления на лету ListView нужно использовать либо OwnerData и соответствующую процедуру. Что не очень удобно, либо писать отдельные процедуры завязанные на какие то тригеры, чтобы обновлять все ручками. Попытка обновления содержимого во время рисования вызовет повторное рисование, и в какой то момент внутри системы срабатывает "бан" на происходящее. И хромая собака вовыляет на монитор.