Чтение онлайн

на главную

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

События относятся к именованным объектам, поэтому с их помощью можно синхронизировать разные процессы. В нашем случае первая копия приложения с помощью

CreateEvent
создает событие, а последующие копии с помощью
OpenEvent
получают дескриптор этого события и взводят его. чтобы послать сигнал о появлении данных в почтовом ящике. Для обнаружения этого момента в первой копии приложения создается отдельная нить, которая ожидает событие и, дождавшись, посылает главной форме сообщение (эта нить практически не требует процессорного времени, потому что почти все время находится в режиме ожидания, т.е. квант времени планировщик задач ей не выделяет, по крайней мере, проверка наличие
данных в главной нити по таймеру отняла бы больше ресурсов). Это сообщение определяется пользователем и берется из диапазона
WM_USER
, т.к. его широковещательной рассылки не будет. При получении этого сообщения форма выполняет код, приведенный в листинге 1.49.

Листинг 1.49. Реакция формы на поступление данных в почтовый ящик

// Реакция на получение команд от других экземпляров приложения

procedure TDKSViewMainForm.WMCommandArrived(var Message: TMessage);

var

 Letter: string;

begin

 // Переводим приложение на передний план

 GoToForeground;

 // Пока есть команды, читаем их и выполняем

 Letter := ReadStringFromMailslot;

 while Letter <> '' do

 begin

// Анализируем и выполняем команду.

// Команда "s" не требует никаких действий, кроме перевода

// приложения на передний план, поэтому здесь мы ее не учитываем

case Letter[1] of

'e': OpenFile(Copy(Letter, 2, MaxInt), False);

'v': OpenFile(Copy(Letter, 2, MaxInt), True);

end;

Letter := ReadStringFronMailslot;

 end;

end;

// Чтение очередного сообщения из почтового ящика

function TDksViewMainForm.ReadStringFromMailslot: string;

var

 MessageSize: DWORD;

begin

 // Получаем размер следующего сообщения в почтовом ящике

 GetMailslotInfo(ServerMailslotHandle, nil, MessageSize, nil, nil);

 // Если сообщения нет, возвращаем пустую строку

 if MessageSize = MAILSLOT_NO_MESSAGE then

 begin

Result := '';

Exit;

 end;

 // Выделяем для сообщения буфер и читаем его в этот буфер

 SetLength(Result, MessageSize);

 ReadFile(ServerMailslotHandle, Result[1], MessageSize, MessageSize, nil);

end;

Примечание

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

1.3.2.4.

Перевод приложения на передний план

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

SetForegroundWindow
мы можем вывести туда любое окно. Однако так было только до Windows 95 и NT 4. В более поздних версиях введены ограничения, и теперь программа не может вывести себя на передний план по собственному усмотрению. Функция
SetForegroundWindow
просто заставит мигать соответствующую кнопку на панели задач.

Тем не менее, если программа свернута, команда

Application.Restore
не только восстанавливает окно, но и выводит его на передний план, что нам и требуется. Ну а если программа не свернута, то "выливаем из чайника воду и тем самым сводим задачу к предыдущей": сначала сворачиваем приложение с помощью
Application.Minimize
, а потом разворачиваем его. Цели мы добились — главное окно на переднем плане.

Дело портит только то, что изменение состояния окна сопровождается анимацией: видно, как главное окно сначала сворачивается, а потом разворачивается. Чтобы убрать этот неприятный эффект, можно на время сворачивания/разворачивания окна запретить анимацию, а потом восстановить ее. С учетом этого метод

GoToForeground
выглядит так, как показано в листинге 1.50.

Листинг 1.50. Перевод приложения на передний план

// Перевод приложения на передний план

procedure TDKSViewMainForm.GoToForeground;

var

 Info: TAnimationInfo;

 Animation: Boolean;

begin

 // Проверяем, включена ли анимация для окон

 Info.cbSize := SizeOf(TAnimationInfo);

 Animation := SystemParametersInfo(SPI_GETANIMATION,

SizeOf(Info), @Info, 0 and (Info.iMinAnimate <> 0);

 // если включена, отключаем, чтобы не было ненужного мерцания

 if Animation then

 begin

Info.iMinAnimate := 0;

SysteParametersInfo(SPI_SETANIMATION, SizeOf(Info), @Info, 0);

 end;

 // Если приложение не минимизировано, минимизируем

 if not IsIconic(Application.Handle) then Application.Minimize;

 // Восстанавливаем приложение. При этом оно автоматически выводится

 // на передний план

 Application.Restorе;

 // Если анимация окон была включена, снова включаем ее

 if Animation than

 begin

Info.iMinAnimate := 1;

SystemParametersInfo(SPI_SETANIMATION, SizeOf(Info), @Info, 0);

 end;

end;

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

Поделиться:
Популярные книги

Последний Паладин

Саваровский Роман
1. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин

Идущий в тени 8

Амврелий Марк
8. Идущий в тени
Фантастика:
фэнтези
рпг
5.00
рейтинг книги
Идущий в тени 8

Все еще не Герой!. Том 2

Довыдовский Кирилл Сергеевич
2. Путешествие Героя
Фантастика:
боевая фантастика
юмористическое фэнтези
городское фэнтези
рпг
5.00
рейтинг книги
Все еще не Герой!. Том 2

Совпадений нет

Безрукова Елена
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Совпадений нет

Муж на сдачу

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Муж на сдачу

На границе империй. Том 7. Часть 4

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
5.00
рейтинг книги
На границе империй. Том 7. Часть 4

Довлатов. Сонный лекарь

Голд Джон
1. Не вывожу
Фантастика:
альтернативная история
аниме
5.00
рейтинг книги
Довлатов. Сонный лекарь

СД. Восемнадцатый том. Часть 1

Клеванский Кирилл Сергеевич
31. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
6.93
рейтинг книги
СД. Восемнадцатый том. Часть 1

Темный Охотник

Розальев Андрей
1. КО: Темный охотник
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный Охотник

Назад в СССР: 1985 Книга 3

Гаусс Максим
3. Спасти ЧАЭС
Фантастика:
попаданцы
альтернативная история
5.50
рейтинг книги
Назад в СССР: 1985 Книга 3

Целитель. Книга вторая

Первухин Андрей Евгеньевич
2. Целитель
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Целитель. Книга вторая

Сумеречный стрелок 8

Карелин Сергей Витальевич
8. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Сумеречный стрелок 8

Огненный князь 3

Машуков Тимур
3. Багряный восход
Фантастика:
фэнтези
боевая фантастика
попаданцы
5.00
рейтинг книги
Огненный князь 3

Магия чистых душ

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.40
рейтинг книги
Магия чистых душ