windows 7, списки переходов и delphi #2
В прошлый раз мое изучение использование категории tasks (задач) в списках переходов остановилось на том, что можно использовать элементы списка переходов для переключения статуса приложения. В реализации данного пункта была одна маленькая проблема, решение которой оказалось простым, но поскольку с подобным я раньше не работал, то данное решение пришло не сразу, а после прочтения заметки на delphi.about.com итак, мы сформировали список задач в списке переходов. каждый элемент представляет возможный статус приложения, имеет команду запуска приложения, и соответственно параметр командной строки, равный нужному статусу. Далее алгоритм работы нашего приложения должен быть следующий. 1. при нажатии на элемент списка запускается новый экземпляр приложения 2. новый экземпляр проверяет, а не запущено ли уже данное приложение. 3. если приложение запущено то осуществляется передача windows сообщения о смене статуса и выход. 4. запущенный экземпляр должен обработать полученное сообщение. модифицируем исходный код проекта. Для контроля того запущен ли уже экземпляр приложения воспользуемся так называемым Mutex Object. Данный объект создается с уникальным именем, и сигнализирует о том, создан ли в системе уже подобный экземпляр с таким именем. Таким образом, перед запуском основной программы, создадим подобный объект с помощью CreateMutex, если получили ошибочный или нулевой результат, значит копия приложения уже запущена. Тогда далее нам следует отправить сообщение нашей копии, и завершить работу. Для того что бы отправить сообщение существующему экземпляру приложения можно пойти двумя способами: либо отправить сообщение всем окнам, либо найти нужное нам и отправить только ему. мы пойдем первым путем, поскольку он гораздо проще. при отправке широковещательного сообщения, надо убедиться, что данное сообщение будет уникально в системе. Поэтому код сообщения сгенерируем предварительно с помощью RegisterWindowMessage по нашему уникальному имени. Для отправки сообщения воспользуемся функцией SendMessage, где параметром обработчика окна назначения будет HWND_BROADCAST, в качестве кода сообщения мы передадим наше зарегистрированное сообщение, и в качестве параметра передадим нужный нам статус из параметра командной строки. по окончании работы приложения следует также освободить наш Mutex Object. следуя данной логике, код запуска приложения, получается следующий:
var setState : integer; mutex : THandle; begin statusMsg := RegisterWindowMessage('My_Application_Message_Name'); mutex := CreateMutex(nil, True, 'My_Application_Mutex_Name'); if (Mutex = 0) or (getLastError() = ERROR_ALREADY_EXISTS) then begin if paramCount > 0 then setState := strToInt(paramStr(1)); SendMessage(HWND_BROADCAST, statusMsg, taskStates[setState].value, 0); end else begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TMainForm, MainForm); Application.Run; if mutex <> 0 then closeHandle(mutex); end; end.
Далее (в чем в прошлый раз была загвоздка) следует обработать полученное сообщение смены статуса в нашем приложении. и загвоздка была в том, что обработку сообщения я хотел провести в обработчике application.onMessage. однако выяснилось что данный обработчик не обрабатывает сообщения отправленные с помощью sendMessage, поэтому обработку сообщения проведем в методе DefaultHandler главной формы приложения. И если приложение получило сообщение с нашим зарегистрированным значением, то следует изменить статус, иначе вызвать родительский обработчик сообщения.
TMainForm = class(TForm) ... private procedure DefaultHandler(var Msg);override; ... end; var statusMsg : Cardinal; {код сообщения} procedure TMainForm.defaultHandler(var msg); begin if TMessage(msg).Msg = statusMsg then begin stateSelect.ItemIndex := TMessage(msg).WParam; exit; end else inherited; end;
как вариант можно использовать уже упомянутый выше обработчик onMessage, только в данном случае сообщение надо отправлять с помощью PostMessage.