Вчера начал разбираться с чужим проектом на Delphi 7. Система весьма сложная – несколько взаимосвязанных АРМов по 20-50 форм (а может и больше, точно не считал). Усложняет все то, что она разрабатывается уже давно и пережила смену нескольких команд разработчиков. Каждая команда приносила в проект свои инновации. Например, одна из них перевела доступ к БД Oracle с BDE на ADO. При этом все старые объекты для работы с базами через BDE (TDatabase, TTable, TQuery и TStoredProc) продолжают лежать на формах рядом с их копиями для работы через ADO (TADOConnection, TADOTable, TADOQuery и TADOStoredProc). Они даже клонировали объекты TDataSource для ADODataSet'ов. Все замеченные беглым взглядом "интересные" моменты перечислять не буду, а вернусь к заголовку этой заметки. Одна из команд добавила в проект DBGridEh из EhLib 6.0 в компанию к стандартному DBGrid'у. Хороший выбор grid'а, одобряю ;-) Хочу поделится с вами их реализацией сортировки по клику на заготовке колонки. К каждому DBGridEh'у, подчеркиваю - к каждому DBGridEh'у, был написан обработчик OnSortMarkingChanged:
Еще, как зануда, отмечу, что вещи в стиле
Так, что господа, те кто считает себя программистом, дружите с Try...Finally...End и главное - ИЗУЧАЙТЕ ИСПОЛЬЗУЕМЫЙ ИНСТРУМЕНТАРИЙ!!!
В одном из АРМ'ов только на главной форме больше 20 DBGridEh'ов лежащих на страницах TNotebook. И на каждый был написан свой обработчик! Если говорить о Delphi, или о объектно-ориентированном программировании в целом, то почему бы все эти десятки одинаковых обработчиков не заменить на один, где вместо gridXYZ использовать TDBGridEh(Sender) (или (Sender as TDBGridEh)), а вместо dsXYZ.DataSet использовать TDBGridEh(Sender).DataSet? Но самое интересное, что для сортировки в DBGridEh и такого обработчика писать не надо. EhLib для автоматической сортировки данных в DataSet'е имеет набор специальных объектов и от программиста требуется только добавить в раздел "uses" любого модуля в проекте один из модулей EhLibXXX (EhLibBDE, EhLibADO, EhLibCDS... в зависимости от подключенного к grid'у DataSet'а). Таким образом, вместо написания и копипаста десятков обработчиков OnSortMarkingChanged нужно было всего лишь подключить к проекту небольшую юниту EhLibADO.... dsXYZ: TDataSource; gridXYZ: TDBGridEh; ... procedure TfmMain.gridXYZSortMarkingChanged(Sender: TObject); var i: Integer; s: String; b: TBookmark; begin Screen.Cursor := crHourGlass; b := dsXYZ.DataSet.GetBookmark; s := ''; for i := 0 to gridXYZ.SortMarkedColumns.Count - 1 do begin s := s + gridXYZ.SortMarkedColumns[i].FieldName; if (gridXYZ.SortMarkedColumns[i].Title.SortMarker = smDownEh) then s := s + ' DESC'; s := s + ';'; end; TADODataSet(dsXYZ.DataSet).IndexFieldNames := s; dsXYZ.DataSet.GotoBookmark( b ); Screen.Cursor := crDefault; end;
Еще, как зануда, отмечу, что вещи в стиле
необходимо использовать совместно с конструкцией Try...Finally...End, т.к. если между этими строчками во время выполнения программы произойдет ошибка, то курсор не будет восстановлен. Т.е. нужно было написать так:Screen.Cursor := crHourGlass; ... Screen.Cursor := crDefault;
А еще к восстановлению курсора в блок Finally...End было бы неплохо, для высвобождения памяти распределенной при вызове GetBookmark, добавить DataSet.FreeBookmark(b). Это же элементарно – для всех изменяемых или создаваемых ресурсов, на случай ошибки, нужно гарантировать возвращение их к исходному состоянию или высвобождению занимаемой ими памяти.Screen.Cursor := crHourGlass; Try ... Finally Screen.Cursor := crDefault; End
Так, что господа, те кто считает себя программистом, дружите с Try...Finally...End и главное - ИЗУЧАЙТЕ ИСПОЛЬЗУЕМЫЙ ИНСТРУМЕНТАРИЙ!!!
Насчет восстановления курсора по выходу из функции, недавно была статья: http://www.tdelphiblog.com/2015/09/LazyCursorHelper.html
ОтветитьУдалитьЯ использую фибы у себя - там FreeBookmark ничего не делает, его можно не использовать.
У меня тоже есть подобный случай и тоже с EhLib связан. У меня в проекте оказался EhLib 3~, со своими правками в коде грида и еще каких то файлов. Правки были для черезстрочной раскраски и для сортировки (оба вопроса решаются и без таких правок конечно же :) ). Причем для сортировки использовались прямые ссылки на модули (формы справочников например).
В итоге при переходе на ХЕ2, самым сложным оказался не какой то там юникод, а перевод программы на новый EhLib.
TLazyCursorHelper :) у меня подобный класс называется TScreenCursor :)
ОтветитьУдалитьВ Delphi 7 FreeBookmark не пустой, о его пустоте в следующих версиях я писал в заметке "Delphi 2010: TDataSet.FreeBookmark – рудимент" http://it-blackcat.blogspot.com.by/2010/03/delphi-2010-tdatasetfreebookmark.html