Читать книгу Delphi. Трюки и эффекты - Александр Чиртик - Страница 4

Глава 1
Окна
1.1. Привлечение внимания к приложению

Оглавление

Начнем с простых примеров, позволяющих привлечь внимание пользователя к определенному окну приложения. Это может пригодиться в различных ситуациях: от уведомления пользователя об ошибке программы до простой сигнализации ему, какое окно в данный момент времени ожидает пользовательского ввода.

Инверсия заголовка окна

Вероятно, вы не раз могли наблюдать, как некоторые приложения после выполнения длительной операции или при возникновении ошибки как бы подмигивают. При этом меняется цвет кнопки приложения на Панели задач, а также состояние окна с активного на неактивное. Такой эффект легко достижим при использовании API-функции FlashWindow или ее усовершенствованного, но более сложного варианта – функции FlashWindowEx.

Примечание

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

Первая из этих функций позволяет один раз изменить состояние заголовка окна и кнопки на Панели задач (листинг 1.1).

Листинг 1.1. Простая инверсия заголовка окна

procedure TForm1.cmbFlashOnceClick(Sender: TObject);

begin

FlashWindow(Handle, True);

end;

Как видите, функция принимает дескриптор нужного окна и параметр (тип BOOL) инверсии. Если значение флага равно True, то состояние заголовка окна изменяется на противоположное (из активного становится неактивным и наоборот). Если значение флага False, то состояние заголовка окна восстанавливается в свое первоначальное значение (активно или неактивно).

Более сложная функция FlashWindowEx в качестве дополнительного параметра (кроме дескриптора окна) принимает структуру FLASHWINFO, заполняя поля которой, можно настроить параметры мигания кнопки приложения и/или заголовка окна.

В табл. 1.1 приведено описание полей структуры FLASHWINFO.

Таблица 1.1. Поля структуры FLASHWINFO

Значение параметра dwFlags формируется из приведенных ниже флагов с использованием операции побитового ИЛИ:

• FLASHW_CAPTION – инвертирует состояние заголовка окна;

• FLASHWTRAY—заставляет мигать кнопку на Панели задач;

• FLASHW_ALL – сочетание FLASHW_CAPTION И FLASHW_TRAY;

• FLASHW_TIMER – периодическое изменение состояния заголовка окна и/или кнопки на Панели задач вплоть до того момента, пока фyнкцияFlashWindowEx не будет вызвана с флагом FLASHW_STOP;

• FLASHW_TIMERNOFG – периодическое изменение состояния заголовка окна и/или кнопки на Панели задач до тех пор, пока окно не станет активным;

• FLASHWSTOP – восстанавливает исходное состояние окна и кнопки на Панели задач.

Далее приведены два примера использования функции FlashWindowEx.

В первом – состояние заголовка окна и кнопки на Панели задач изменяется десять раз каждые 0,2 секунды (листинг 1.2).

Листинг 1.2. Десятикратная инверсия заголовка окна

procedure TForm1.cmbInverse10TimesClick(Sender: TObject);

var

fl: FLASHWINFO;

begin

fl.cbSize:= SizeOf(fl);

fl.hwnd:= Handle;

fl.dwFlags:= FLASHW_CAPTION or FLASHW_TRAY; // аналогично

FLASHW_ALL

fl.uCount:= 10;

fl.dwTimeout:= 200;

FlashWindowEx(fl);

end;

Второй пример демонстрирует использование флаговРЬАЗШ_Т1МЕРч и FLASHW_STOP для инверсии заголовка окна в течение заданного промежутка времени (листинг 1.3).

Листинг 1.3. Инверсия заголовка окна в течение определенного промежутка времени

//Запуск процесса периодической инверсии заголовка

procedure TForm1.cmbFlashFor4SecClick(Sender: TObject);

var

fl: FLASHWINFO;

begin

fl.cbSize:= SizeOf(fl);

fl.hwnd:= Handle;

fl.dwTimeout:= 200;

fl.dwFlags:= FLASHW_ALL or FLASHW_TIMER;

fl.uCount:= 0;

FlashWindowEx(fl);

Timer1.Enabled:= True;

end;

//Остановка инверсии заголовка

procedure TForm1.Timer1Timer(Sender: TObject);

var

fl: FLASHWINFO;

begin

fl.cbSize:= SizeOf(fl);

fl.hwnd:= Handle;

fl.dwFlags:= FLASHW_STOP;

FlashWindowEx(fl);

Timer1.Enabled:= False;

end;

В данном примере подразумевается использование таймера, срабатывающего каждые четыре секунды. Таймер первоначально неактивен. Конечно, можно было бы не использовать его, а просто посчитать количество инверсий, попадающих в нужный интервал времени (в данном случае четыре секунды), и задать его в поле uCount. Но приведенный пример рассчитан именно на демонстрацию использования флагов FLASHW_TIMERH flashw_stop.

Активизация окна

Рассмотрим другой, гораздо более гибкий способ привлечение внимания к окну приложения. Он базируется на использовании API-функции SetForegroundWindow. Функция принимает один единственный параметр – дескриптор окна. Если выполняется ряд условий, то окно с заданным дескриптором будет выведено на передний план и пользовательский ввод будет направлен в это окно. Функция возвращает нулевое значение, если не удалось сделать окно активным.

В приведенном ниже примере окно активизируется при каждом срабатывании таймера (листинг 1.4).

Листинг 1.4. Активизация окна

procedure TForm1.Timer1Timer(Sender: TObject);

begin

SetForegroundWindow(Handle);

end;

В операционных системах старше Windows 95 и Windows NT 4.0 введен ряд ограничений на действие функции SetForegroundWindow. Так, приведенный выше пример как раз и является одним из случаев недружественного использования активизации окна, но это всего лишь пример.

Чтобы активизировать окно, процесс должен быть не фоновым либо должен иметь право устанавливать активное окно, назначенное ему другим процессом с таким правом, и т. п. Все возможные нюансы в пределах одного трюка рассматривать не имеет смысла. Стоит отметить, что в случае, когда окно не может быть активизировано, автоматически вызывается функция FlashWindow для окна приложения (заставляет мигать кнопку этого приложения на Панели задач). Поэтому даже при неудачном вызове функции SetForegroundWindow приложение, нуждающееся во внимании, не останется незамеченным.

Delphi. Трюки и эффекты

Подняться наверх