Показаны сообщения с ярлыком Delphi. Показать все сообщения
Показаны сообщения с ярлыком Delphi. Показать все сообщения

среда, 10 июня 2015 г.

Delphi: как показать окно сообщения над всеми окнами приложения

Все меняется. И это грустно. Долгое время моим наиболее используемым инструментом программирования являлся Delphi. Я специально не говорю "языком", потому что Delphi - это не просто язык программирования. IDE (интегрированная среда разработки) Delphi долгое время оставалась для меня эталоном того, что можно сделать для разработчика. А чего стоила инфраструктура компонентов, Wizard-ов, плагинов?

Но, в последнее время, я все больше сижу на Java, и к Delphi-разработкам возвращаюсь все реже и реже. К тому же, мое активное программирование на этом замечательном средстве застряло на уровне версий Delphi 5, Delphi 6, Delphi 7. Нет, я пробовал что-то писать на новых версиях, например, Delphi XE 3, даже пробовал FireMonkey, но опыт этот был весьма поверхностным и непродолжительным.

Именно поэтому я решил, что буду писать про то, что делаю в Delphi. Вполне возможно, многое из того, что я опишу, покажется современным гуру этого средства детским лепетом, но это меня не останавливает.

Сегодня расскажу вот о чем. Есть у меня программка, которая что-то там делает :) Хотя нет, для полноты картины, напишу о ней несколько слов.

Программа написана с использованием Delphi XE3 (старье, да?), но используемые методы программирования и технологии более подошли бы еще более ранним версиям среды разработки. Например, используется VCL, а не FireMonkey.

Прога сидит в трее и по различным горячим комбинациям клавиш выполняет определенные действия. Большинство этих действий не нуждаются в пользовательском интерфейсе, но есть комбинация горячих клавиш, которая приводит к появлению на экране небольшой формочки.

Я думаю, многие сталкивались с такой проблемой, когда окошко показывается не поверх остальных окон, открытых в Windows, а предательски прячется под каким-нибудь из них. Особенно часто это происходит, когда открываемое окно не является главной формой приложения, а является так называемым toolWindow, да и само приложение представлено только иконкой в трее.

Наверное, я смалодушничал - взял и просто присвоил этой форме стиль fsStayOnTop (ну не форме, конечно, а ее свойству FormStyle). После этого форма стала стабильно появляться поверх всех открытых окон, что не могло не радовать. Но, как часто бывает, такое решение возымело не только положительный, но и отрицательный эффект.

Дело в том, что в окошке этом пользователь может произвести некоторые ошибочные действия, о чем программа должна его уведомить. Как? Как обычно: выдав на экран диалоговое окно с описанием проблемы. Для выдачи таких сообщений я, обычно, использую метод MessageDlg. И этот раз не стал исключением. Вот как вы думаете, где появилось окно сообщения? Я имею в виду, относительно той самой формочки, которая отображается поверх всех окон? Правильно, окно с сообщением отобразилось под формой. Вот такая вот картинка:


А ведь такая безобидная строчка кода:

MessageDlg(Format(rsCoversionError, [Id]), mtError, [mbClose], 0);

Конечно, такой результат не мог меня удовлетворить и я отправился курить мануалы. И уже первые затяжки стали приносить результат!!! В общем, справка Delphi вывела на метод MessageBox. На самом деле, методов два: один объявлен в Vcl.Forms.TApplication, другой - в Winapi.Windows. Нам нужен тот, который описан в Winapi.Windows (то есть, второй), потому что первый (который объявлен в Vcl.Forms.TApplication) является оберткой и как-то сам там все пытается организовать. А нам нужен полный контроль.

Итак, нужный нам MessageBox - обычный метод Win32 API. Он примечателен тем, что первым параметром у него идет дескриптор родительского окна, и, установив его в дескриптор моей формы:

MessageBox(StayOnTopForm.Handle, PWideChar(Format(rsCoversionError, [Id])), 'Error', MB_OK);

я получил желаемый результат:



Однако, этот результат меня тоже не вполне удовлетворил. Дело в том, что я не зря написал, что предпочитаю для выдачи сообщений использовать метод MessageDlg. Ну нравится мне больше внешний вид этого окна, чем того, которое появляется в результате вызова MessageBox. И хотя их и можно сделать абсолютно похожими, но, в случае с MessageBox, придется немного потанцевать с бубном. MessageDlg все-таки более user friendly, на мой взгляд.

И я снова отправился курить мануалы. Сегодня они реально доставляли!!! Довольно быстро нашелся еще один метод: CreateMessageDialog, который создает и возвращает форму сообщения, не показывая ее. Получив эту форму, можно попытаться поколдовать над ней для получения нужного эффекта. А нам нужно, чтобы сообщение появилось над формой, а не под ней.

И тут руководство (не в смысле "начальство", а в смысле "документ") не подкачало. Вернее, на высоте оказался Delphi, ну и online справка, конечно. У формы обнаружилась пара свойств: PopupMode и PopupParent. Изучение документации по обоим свойствам привело меня к следующим выводам: свойство PopupMode можно вообще не трогать, потому что сообщение все равно показывать при помощи метода ShowModal сконструированной формы, а этот метод принудительно выставит значение свойства в pmAuto. А вот в PopupParent, пожалуй, стоит записать мою формочку, чтобы сообщение появилось поверх нее. Я так и сделал:

  dlg := CreateMessageDialog(Format(rsCoversionError, [Id]), 
              mtError, [mbClose]);
  dlg.PopupParent := StayOnTopForm;
  dlg.ShowModal;
  FreeAndNil(dlg);


И результат не заставил себя долго ждать:



Ну и напоследок немного дегтя в бочку... В какой-то момент я подумал, что существует еще один вариант решения моей задачки. Пока я лазил по документации, я набрел на такие методы класса TApplication, как NormalizeAllTopMosts, NormalizeTopMosts и RestoreTopMosts. С их помощью можно написать примерно такой код:

  Application.NormalizeAllTopMosts;
  MessageDlg(Format(rsCoversionError, [Id]), mtError, [mbClose], 0);
  Application.RestoreTopMosts;


после чего, судя по документации, сообщение об ошибке должно появиться над формой. Но не тут-то было. Практика - упрямая вещь, о которую разбиваются многие красивые теории. Запустив приложение и создав предпосылки для появления ошибки, я увидел сообщение о ней под формой. Дальнейшее ковыряние выявило, что для формочек со стилем границ (свойство BorderStyle) bsToolWindow этот метод не работает. Но, например для стиля bsSizeable - все пучком.

Какой же урок я вынес из этого случая? Delphi изменился. Даже в части так хорошо знакомого мне раньше VCL. Больше методов, больше свойств, больше возможностей. Это хорошо. Надо учить. Это тоже хорошо!

понедельник, 30 апреля 2012 г.

FireMonkey. Начало. Предыстория. Впечатления.

Прошло уже достаточно времени с тех пор, как термин FireMonkey стал более менее знаком, если, и не для всех разработчиков, то хотя бы тех, кто использует Delphi. За это время появились книги по FireMonkey, статьи по FireMonkey, записи про FireMonkey в многочисленных блогах. Читать все это очень интересно. Но ведь никакая теория не заменит практику. И у меня, как и у многих ранее, появился зуд попробовать что-нибудь написать с использованием FireMonkey.
При этом, однако, возникла проблема. Я, почему-то, решил, что надо просто реализовать какой-нибудь не очень сложный рабочий проект.

суббота, 5 ноября 2011 г.

Indy 9, SSL и SOCKS Proxy

В предыдущем посте я обещал рассказать о том, как удалось прикрутить SOCKS proxy для отправки писем через защищенный SSL канал. Для тех, кто не в курсе, или подзабыл, напомню, что я, по требованию пользователей, добавлял в старую, добрую прогу возможность отправки писем через SMTP сервер, требующий использования защищенного канала. Для тестов использовался публичный SMTP сервер smtp.gmail.com. Как я решал эту задачку с использованием Delphi 6 и Indy 9, было описано ранее. Но в процессе решения возникла неожиданно еще одна проблема, не имеющая отношения к поставленной задаче.

вторник, 1 ноября 2011 г.

Indy v.9, SMTP и SSL

Производственная необходимость, кто же, как не она, родимая, поставила задачу: надо сделать так, чтобы соединение с SMTP сервером производилось при помощи защищенного SSL канала.

Имеется написанный довольно давно почтовый клиент. Клиент написан на Delphi 6 с использованием набора компонент Indy версии 9.0.18. Таковы начальные условия. Необходимо, не переписывая кардинальным образом программу, расширить ее функционал требуемым образом, то есть, научить клиента общаться с SMTP серверами посредством защищенного SSL канала.

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