Не знаю как у вас, а у меня коде (vcl приложение) полным-полно таких конструкций:
var tmpOldCursor: TCursor; begin tmpOldCursor := Screen.Cursor; try Screen.Cursor := crHourglass; // код который может работать относительно долго // например, выполнять запрос в БД finally Screen.Cursor := tmpOldCursor; end; end;
И мне это надоело. По двум причинам:
- увеличение размера модулей - по 8 строк кода на каждый такой случай
- разбухание секции uses, ведь чтобы это работало нужно в каждый модуль работающий с курсором добавить uses Forms, Controls;
Поэтому давайте уже воспользуемся механизмом подсчёта ссылок в интерфейсах, и реализуем маленький класс избавляющий нас написания лишнего кода. Так чтобы вышеприведённый пример можно было упростить до 1й строки.
begin TLazyCursorHelper.ChangeToHourglass; // код который может работать относительно долго // например, выполнять запрос в БД end; // а здесь курсор должен восстановиться
Дайте мне знать, если вы знаете в каких случаях это не будет работать как задумывалось, или столкнётесь с такой ситуацией. В последнем случае, укажите пожалуйста в комментарии версию Delphi, платформу и была ли включена оптимизация при сборке.
update: в комментариях дали ссылку на более универсальное и элегантное решение от Barry Kelly (который долгое время занимался разработкой компилятора dcc32 в Borland/Embarcadero). Barry уверяет, что такой способ весьма надёжен.
У Barry Kelly более универсальный способ описан:
ОтветитьУдалитьhttp://blog.barrkel.com/2010/01/one-liner-raii-in-delphi.html
Да, спасибо! У Барри действительно очень изящный способ описан.
УдалитьНе могли бы вы пожалуйста выложить пример с изменением курсора основанный на методе барри?
УдалитьАнонимный, примерно как-то так: https://gist.github.com/tdelphi/99c4c847fd91da59ea97
УдалитьПримерно этот же способ нашёл тут: http://habrahabr.ru/post/147575
ОтветитьУдалитьДля себя видоизменил его до передачи курсора в конструктор.
Теперь же, благодаря, комментарию выше, видоизменил снова, убрав ненужный интерфейс и оставив снаружи только функцию, возвращающую IInterface.
На хабре imho довольно кривенькая реализация.
УдалитьА по поводу оставления снаружи только функции. В моём случае - функций несколько, по одной для каждого типа курсора(чтобы не добавлять uses Controls только ради курсорной константы). А в последнее время я стараюсь не оставлять глобальных функций, и все функции группировать (либо внутри класса как class methods) либо внутри record-a - как статичные методы. Мне проще иметь одна точку доступа (класс или record) ко всем моим функциям работающим с курсором, чем несколько глобальных функций. К тому же это меньше засоряет Autocomplete в редакторе.
bq. не добавлять uses Controls только ради курсорной константы
УдалитьЭто правильно :-)
@Александр - недавно начал использовать DevExpress. На фоне того количества "используемых юнитов", которое добавляют DX компоненты (кладёшь на форму 1, получаешь + 7 uses), эти Controls оказались такими мелочами.
УдалитьМожно же лямбды (анонимные функции) использовать.
ОтветитьУдалитьhttp://programmingmindstream.blogspot.ru/2015/09/blog-post_4.html
Можно, можно. У Барри в журнале (ссылкка в первом комментарии) как раз на лямбдах описан способ.
УдалитьЯ просто (по старой привычке), на публику пишу код работающий в версиях Delphi 6 и моложе.
Понятно. Ну я на самом деле так и подумал. Да и с лямбдами - многословнее получается.
УдалитьЯ вот что ещё вспомнил - http://programmingmindstream.blogspot.ru/2015/09/1163.html
Может полезно будет.