Re: как узнать
От: Yozh_Programmer  
Дата: 17.03.06 21:07
Оценка: -1
Здравствуйте, CR-LF, Вы писали:

CL>Hi all, подскажите плиз

CL>При обнаружении, что одна копия моего приложения уже запущена, я делаю
CL>
CL>    ShowWindow(H, SW_RESTORE);
CL>    SetForegroundWindow(H);
CL>

CL>Вопрос: как эта первая копия может узнать, что его отобразили с помощью
CL>ShowWindow ?

А ты не вызывай ShowWindow напрямую. Ты лучше пошли PostMessage'м месагу типа
WM_APP + 100
и отлавливая ее юзай ShowWindow.
как узнать
От: CR-LF Россия  
Дата: 17.03.06 20:28
Оценка:
Hi all, подскажите плиз
При обнаружении, что одна копия моего приложения уже запущена, я делаю
    ShowWindow(H, SW_RESTORE);
    SetForegroundWindow(H);

Вопрос: как эта первая копия может узнать, что его отобразили с помощью
ShowWindow ?
Posted via RSDN NNTP Server 2.0
Re[2]: как узнать
От: CR-LF Россия  
Дата: 18.03.06 03:43
Оценка:
> А ты не вызывай ShowWindow напрямую. Ты лучше пошли PostMessage'м месагу
> типа
> WM_APP + 100
> и отлавливая ее юзай ShowWindow.
А так, чтобы не заводить обработчик сообщений не получится ?
Posted via RSDN NNTP Server 2.0
Re: как узнать
От: Rius Россия  
Дата: 18.03.06 04:30
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Hi all, подскажите плиз

CL>При обнаружении, что одна копия моего приложения уже запущена, я делаю
CL>
CL>    ShowWindow(H, SW_RESTORE);
CL>    SetForegroundWindow(H);
CL>

CL>Вопрос: как эта первая копия может узнать, что его отобразили с помощью
CL>ShowWindow ?
неверный способ обнаружения уже запущенной копии
Re[2]: как узнать
От: CR-LF Россия  
Дата: 18.03.06 04:50
Оценка:
> CL>Hi all, подскажите плиз
> CL>При обнаружении, что одна копия моего приложения уже запущена, я делаю
> CL>
> CL>    ShowWindow(H, SW_RESTORE);
> CL>    SetForegroundWindow(H);
> CL>

> CL>Вопрос: как эта первая копия может узнать, что его отобразили с помощью
> CL>ShowWindow ?
> неверный способ обнаружения уже запущенной копии
С чего ты взял ?
Я кажется вообще не показывал каким образом я это делаю.
Posted via RSDN NNTP Server 2.0
Re[3]: как узнать
От: dania  
Дата: 18.03.06 05:31
Оценка:
Здравствуйте, CR-LF, Вы писали:

>> CL>Вопрос: как эта первая копия может узнать, что его отобразили с помощью

>> CL>ShowWindow ?
>> неверный способ обнаружения уже запущенной копии
CL>С чего ты взял ?
CL>Я кажется вообще не показывал каким образом я это делаю.
Ты это паказал... показал основновную свою функцию.
Вот посмотри на примере. Может перенесёшь. Или Будет полезно.

var
ReturnParam :boolean;
begin
ReturnParam:=false;
StartTimer.Enabled:=false;
WinExec('DBCS.exe GHH-JGHG-HJGH',0);
repeat
Application.ProcessMessages();
if (FindWindow('TPasswordForm','Ограничение доступа "База Данных XXXX" 1.0 (SoftWare Building 2002)') <> 0)
then
begin
ReturnParam:=true;
end;
until (ReturnParam = true);
Close();
end;
Re[4]: как узнать
От: CR-LF Россия  
Дата: 18.03.06 06:02
Оценка:
>>> неверный способ обнаружения уже запущенной копии
> CL>С чего ты взял ?
> CL>Я кажется вообще не показывал каким образом я это делаю.
> Ты это паказал... показал основновную свою функцию.
Когда ?!
Где ?!
У меня вот как делается
const
  MemFileSize = 127;
  MemFileName = 'q_day';

var
  MemHnd:HWND;
  hndl: THandle;

{$R *.res}

begin
  MemHnd := CreateFileMapping(HWND($FFFFFFFF),nil,PAGE_READWRITE,0,
     MemFileSize,MemFileName);
  if GetLastError <> ERROR_ALREADY_EXISTS then begin
    Application.Initialize;
    Application.CreateForm(TQForm, QForm);
    Application.Run;
  end
  else begin
    hndl := FindWindow('TQForm', 'Q-day');
    if hndl <> 0 then begin
      SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);
      SetForegroundWindow(hndl);
    end;
  end;
  CloseHandle(MemHnd);
end.


> Вот посмотри на примере. Может перенесёшь. Или Будет полезно.

Че-то я мало что понял из этого ;(
Зачем там StartTimer, зачем WinExec, зачем ProcessMessages и наконец зачем
repeat ... until ?
Что если FindWindow с первого раза не нашла TPasswordForm, то потом она его
может найти ?

> var
> ReturnParam :boolean;
> begin
> ReturnParam:=false;
> StartTimer.Enabled:=false;
> WinExec('DBCS.exe GHH-JGHG-HJGH',0);
> repeat
>  Application.ProcessMessages();
>  if (FindWindow('TPasswordForm','Ограничение доступа ...)') <> 0)
>   then
>    begin
>     ReturnParam:=true;
>    end;
> until (ReturnParam = true);
> Close();
> end;
Posted via RSDN NNTP Server 2.0
Re[5]: как узнать
От: Leonid Troyanovsky  
Дата: 20.03.06 06:46
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL> MemHnd := CreateFileMapping(HWND($FFFFFFFF),nil,PAGE_READWRITE,0,

CL> MemFileSize,MemFileName);

Если ты уж создал mmf, то почему бы не записать туда что-нибудь
полезное, например, хендл окна, которое должно быть активизировано
(и будет получать, скажем, параметры комстроки путем WM_COPYDATA).

CL> SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);


Это выглядит подозрительно. В соответствие с политикой MS
non-foreground процесс не может стать foreground по своей воле,
а токмо волей foreground процесса.

CL> SetForegroundWindow(hndl);


Это тоже не совсем точно:

var 
  wnd, app: HWND; 
begin 
  wnd := .. // читаем (ищем) хендл активизируемого окна
  if wnd <> 0 then
    begin  
      {Test if app is minimized, if so restore it} 
      app:= GetWindowLong(wnd, GWL_HWNDPARENT); 
      if IsIconic(app) then 
        ShowWindow(app, SW_RESTORE); 
      SetForegroundWindow(wnd);
    end;
end;
--
С уважением, LVT
Re[6]: как узнать
От: CR-LF Россия  
Дата: 20.03.06 10:01
Оценка:
> CL> MemHnd := CreateFileMapping(HWND($FFFFFFFF),nil,PAGE_READWRITE,0,
> CL> MemFileSize,MemFileName);
>
> Если ты уж создал mmf,
Что такое mmf ?
Если честно, я этот код взял с Кулибы и в общем-то не разобрался как он
работает.

>то почему бы не записать туда что-нибудь

> полезное, например, хендл окна, которое должно быть активизировано
> (и будет получать, скажем, параметры комстроки путем WM_COPYDATA).
Так а зачем туда что-то записывать и, главное, как ?

> CL> SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);

>
> Это выглядит подозрительно. В соответствие с политикой MS
> non-foreground процесс не может стать foreground по своей воле,
> а токмо волей foreground процесса.
Дык вторая копия же foreground ...
Она следующей строкой первую и сделает foreground.

>
> var
>  wnd, app: HWND;
> begin
>  wnd := .. // читаем (ищем) хендл активизируемого окна
>  if wnd <> 0 then
>    begin
>      {Test if app is minimized, if so restore it}
>      app:= GetWindowLong(wnd, GWL_HWNDPARENT);
>      if IsIconic(app) then
>        ShowWindow(app, SW_RESTORE);
>      SetForegroundWindow(wnd);
>    end;
> end;
>

Та делал я раньше ShowWindow(app, SW_RESTORE) ...
Тока она потом не хочет обратно в трей заворачиваться.
Не знаю почему.
Posted via RSDN NNTP Server 2.0
Re[7]: как узнать
От: Leonid Troyanovsky  
Дата: 20.03.06 10:59
Оценка:
Здравствуйте, CR-LF, Вы писали:

>> CL> MemHnd := CreateFileMapping(HWND($FFFFFFFF),nil,PAGE_READWRITE,0,

>> Если ты уж создал mmf,
CL>Что такое mmf ?

Оно и есть, memory mapped file.

CL>Так а зачем туда что-то записывать и, главное, как ?


Чтобы там был, например, хендл того окна, который нужно поднять.
Пишем (читаем) так: MapViewOfFile, Move

CL>Дык вторая копия же foreground ...

CL>Она следующей строкой первую и сделает foreground.

Ну, а зачем тогда WM_RESTOREFROMTRAY? Что должна делать первая копия
при получении оного?

CL>Та делал я раньше ShowWindow(app, SW_RESTORE) ...

CL>Тока она потом не хочет обратно в трей заворачиваться.

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

Кроме того, часто для подобных приложений кнопку в таскбаре прячут.
--
С уважением, LVT
Re[8]: как узнать
От: CR-LF Россия  
Дата: 20.03.06 12:57
Оценка:
> CL>Что такое mmf ?
>
> Оно и есть, memory mapped file.
А как это по-русски-то называется ?
И вообще зачем такие файлы нужны ?

> CL>Так а зачем туда что-то записывать и, главное, как ?

>
> Чтобы там был, например, хендл того окна, который нужно поднять.
Так а чем плохо FindWindow ?

> Пишем (читаем) так: MapViewOfFile, Move

Move — это паскалевская процедура ?
И как ей в данном случае воспользоваться ?

>

> CL>Дык вторая копия же foreground ...
> CL>Она следующей строкой первую и сделает foreground.
>
> Ну, а зачем тогда WM_RESTOREFROMTRAY? Что должна делать первая копия
> при получении оного?

TMyForm = class(TForm)
    ....
    procedure WMRestoreFtomTray(var Message: TMessage); message 
WM_RESTOREFROMTRAY;
end;

procedure TMyForm.WMRestoreFtomTray(var Message: TMessage);
begin
  RestoreFromTray(Self);
end;

procedure TMyForm.RestoreFromTray(Sender: TObject);
begin
  TrayIcon.ShowMainForm;
  TrayIcon.IconVisible := False
end;


>

> CL>Та делал я раньше ShowWindow(app, SW_RESTORE) ...
> CL>Тока она потом не хочет обратно в трей заворачиваться.
>
> Не видел, что там не заворачивается.
> В таких вещах каждая мелочь важна, например, действительно ли это app
> (ищешь-то ты другое окно),
Не понял.
А что же это тогда, если не app, если FindWindow его нашел, а ShowWindow
развернул ?

>единственная ли форма у приложения и т.д.

Форма единственная

>

> Кроме того, часто для подобных приложений кнопку в таскбаре прячут.
В смысле, когда програ в трее или когда развернута ?
У меня когда в трее в таскбаре ничего нет, а когда развернута — в таскбаре
кнопка как у всех.
Да и вообще при чем тут таскбар ?
Posted via RSDN NNTP Server 2.0
Re[3]: как узнать
От: Аноним  
Дата: 20.03.06 13:27
Оценка:
CL>А так, чтобы не заводить обработчик сообщений не получится ?

TApplication.OnMessage ?

Или использовать готовые компоненты какие-нибудь
Re[9]: как узнать
От: Leonid Troyanovsky  
Дата: 20.03.06 15:41
Оценка:
Здравствуйте, CR-LF, Вы писали:

>> Оно и есть, memory mapped file.

CL>А как это по-русски-то называется ?
CL>И вообще зачем такие файлы нужны ?

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

CL>Так а чем плохо FindWindow ?


Ничего плохого в ней нет.
Но, если mmf создан, то почему не воспользоваться им по назначению,
вместо поиска по всему списку окон (класс, название этого окна
тоже придется зашивать в код).

CL>Move — это паскалевская процедура ?

CL>И как ей в данном случае воспользоваться ?

Help: Move Example

CL> procedure WMRestoreFtomTray(var Message: TMessage); message

CL>WM_RESTOREFROMTRAY;

Все равно, за бортом осталось много загадочного.
Можно даже предположить, что и порядок вызова SendMessage vs
SetForegroundWindow важен.

CL>А что же это тогда, если не app, если FindWindow его нашел, а ShowWindow

CL>развернул ?

У Application свое окно, которое owner (в MS смысле) окон дельфийских форм.

CL>Да и вообще при чем тут таскбар ?


Потому, как варианты прятать/не прятать имеют свои особенности.
А при управлении окнами (даже своими) нельзя пренебрегать ни одной,
казалось бы, мелочью.

Например, хотим мы показать форму, не активируя ее.
Казалось, чего проще: ShowWindow(Handle, SW_SHOWNA), однако,
для корректной работы этой формы потребуется, кроме того, Visible:= True.
--
С уважением, LVT
Re[10]: как узнать
От: Danchik Украина  
Дата: 20.03.06 15:52
Оценка:
Здравствуйте, Leonid Troyanovsky, Вы писали:

[Skip]

Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя использовать FindWindow для поиска уже запущеной програмы
Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы быстренько накликали на запуск програмы, а она успела создать нужное окно.

Для этого правильно использовать обьекты синхронизации, например мютексы — CreateMutex.
Пример я закидывал давным давно здесь
Автор: Danchik
Дата: 09.08.05


Здесь же можна посмотреть как правильно вызвать SetForegroundWindow через AttachThreadInput.
Re[10]: как узнать
От: CR-LF Россия  
Дата: 20.03.06 16:18
Оценка:
>>> Оно и есть, memory mapped file.
> CL>А как это по-русски-то называется ?
> CL>И вообще зачем такие файлы нужны ?
>
> Файлы, проецируемые в память. Используются, например, для обмена
> данными между процессами.
Припоминается что-то из FreeBSD

> CL>Move — это паскалевская процедура ?

> CL>И как ей в данном случае воспользоваться ?
>
> Help: Move Example
Ну и чего ?
Там стандартный пример, а в данном случае что написать вместо ???? (см.
ниже)
hFile := CreateFileMapping(HWND($FFFFFFFF),nil,PAGE_READWRITE,0, 
MemFileSize,MemFileName);
MapViewOfFile(hFile,  FILE_MAP_WRITE, 0, 0, 4);
move(Application.Handle, ????, SizeOf(HWND));
CloseHandle(hFile);


> CL>Да и вообще при чем тут таскбар ?

> Потому, как варианты прятать/не прятать имеют свои особенности.
> А при управлении окнами (даже своими) нельзя пренебрегать ни одной,
> казалось бы, мелочью.
> Например, хотим мы показать форму, не активируя ее.
> Казалось, чего проще: ShowWindow(Handle, SW_SHOWNA), однако,
> для корректной работы этой формы потребуется, кроме того, Visible:= True.
А я уже здесь как-то спрашивал, как мне узнать, что окно было развернуто с
помощью ShowWindow.
Вопрос остался открытым, вот я и сделал как сейчас, т.е. когда ему
посылается WM_RESTOREFROMTRAY, а оно уже само себя разворачивает.
Пока все работает нормально.
Posted via RSDN NNTP Server 2.0
Re[11]: как узнать
От: Leonid Troyanovsky  
Дата: 20.03.06 16:19
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя использовать FindWindow для поиска уже запущеной програмы


А что дало тебе уверенность в том, что я ее не читал?
Возможность использования FindWindow я не отвергал, бо она есть.

D>Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы быстренько накликали на запуск програмы, а она успела создать нужное окно.


Никто не запрещает сначала убедиться, что окно есть (скажем, из существования
объекта ядра), а затем его искать.

D>Для этого правильно использовать обьекты синхронизации, например мютексы — CreateMutex.


Да, млин, какие еще мьютексы, если у нас готовый mmf (мог бы и почитать сначала)

D>Здесь же можна посмотреть как правильно вызвать SetForegroundWindow через AttachThreadInput.


Не вижу связи между правильностью вызова SFW и AttachThreadInput.
Если же речь идет об обходе запретов MS — даже обсуждать не хочу.
--
С уважением, LVT
Re[11]: как узнать
От: CR-LF Россия  
Дата: 20.03.06 16:30
Оценка:
> Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя
> использовать FindWindow для
>поиска уже запущеной програмы
Оп-п-паньки !!!
А что тогда ? — Использовать FindWindow для поиска незапущенных программ ?!

> Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы

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

>

> Для этого правильно использовать обьекты синхронизации, например мютексы —
> CreateMutex.
> Пример я закидывал давным давно
> здесь<br />
<span class='lineQuote level1'>&gt;</span>
Автор: Danchik
Дата: 09.08.05

Да уж ;(
Очень просто ...
Posted via RSDN NNTP Server 2.0
Re[11]: как узнать
От: Leonid Troyanovsky  
Дата: 20.03.06 16:31
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>MapViewOfFile(hFile, FILE_MAP_WRITE, 0, 0, 4);


Здесь лучше последним 0, т.е. просмотр на весь файл.
А, вообще-то, это функция, возвращающая при удаче
указатель на начало просмотра.

CL>move(Application.Handle, ????, SizeOf(HWND));


move(Application.Handle, p^ {:PLongint}, SizeOf(HWND));

CL>CloseHandle(hFile);


Кроме того, положено делать UnMapViewOfFile.

CL>Пока все работает нормально.


Ну, и слава Богу.
--
С уважением, LVT
Re[12]: как узнать
От: CR-LF Россия  
Дата: 20.03.06 17:05
Оценка:
Короче так пойдет ?
var
  hFile: HWND;
  hndl: THandle;
  p: ^LongInt;

begin
  hFile := 
CreateFileMapping(HWND($FFFFFFFF),nil,PAGE_READWRITE,0,MemFileSize,MemFileName);
  if GetLastError <> ERROR_ALREADY_EXISTS then begin
    p := MapViewOfFile(hFile,  FILE_MAP_WRITE, 0, 0, 0);
    move(Application.Handle, p^, SizeOf(HWND));
    UnMapViewOfFile(p);
    Application.Initialize;
    Application.CreateForm(TMyForm, MyForm);
    Application.Run;
  end
  else begin
    p := MapViewOfFile(hFile,  FILE_MAP_READ, 0, 0, 0);
    move(p^, hndl, SizeOf(HWND));
    UnMapViewOfFile(p);
    SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);
    SetForegroundWindow(hndl);
  end;
  CloseHandle(hFile);
end.


Или
SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);
SetForegroundWindow(hndl);

все же не то ?
Posted via RSDN NNTP Server 2.0
Re[12]: как узнать
От: Danchik Украина  
Дата: 20.03.06 17:26
Оценка:
Здравствуйте, Leonid Troyanovsky, Вы писали:

LT>Здравствуйте, Danchik, Вы писали:


D>>Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя использовать FindWindow для поиска уже запущеной програмы


LT> А что дало тебе уверенность в том, что я ее не читал?

LT> Возможность использования FindWindow я не отвергал, бо она есть.

D>>Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы быстренько накликали на запуск програмы, а она успела создать нужное окно.


LT> Никто не запрещает сначала убедиться, что окно есть (скажем, из существования

LT> объекта ядра), а затем его искать.
Именно об этом и говорилось

D>>Для этого правильно использовать обьекты синхронизации, например мютексы — CreateMutex.


LT> Да, млин, какие еще мьютексы, если у нас готовый mmf (мог бы и почитать сначала)

Да какя разница какой обьект ядра создавать, mmf не заметил.

D>>Здесь же можна посмотреть как правильно вызвать SetForegroundWindow через AttachThreadInput.


LT> Не вижу связи между правильностью вызова SFW и AttachThreadInput.

LT> Если же речь идет об обходе запретов MS — даже обсуждать не хочу.

Да потому что начиная с Win2k SetForegroundWindow перестал работать как ожидалось.
Re[12]: как узнать
От: Danchik Украина  
Дата: 20.03.06 17:36
Оценка:
Здравствуйте, CR-LF, Вы писали:

>> Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя

>> использовать FindWindow для
>>поиска уже запущеной програмы
CL>Оп-п-паньки !!!
CL>А что тогда ? — Использовать FindWindow для поиска незапущенных программ ?!
Просто если критерием запущенности программы считать созданное окно, то у нас могут быть накладки. Поэтому рекомендуется пользоваться обьектами синхронизации в паре с FindWindow

>> Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы

>> быстренько накликали на
>>запуск програмы, а она успела создать нужное окно.
CL>Так я же ищу первую копию, которая была создана давно.
В основном работать будет. Но где гарантия что вы сделали два DblClik по иконке запуска

>>

>> Для этого правильно использовать обьекты синхронизации, например мютексы —
>> CreateMutex.
>> Пример я закидывал давным давно
>> здесь<br />
<span class='lineQuote level2'>&gt;&gt;</span>
Автор: Danchik
Дата: 09.08.05

CL>Да уж ;(
CL>Очень просто ...
Очень просто только в одно место ходят
Я предложил целый работающий юнит, ваше дело пользоваться ли им или нет. Есть еще реализация от Jedi Code Library — JclAppInst.pas. Ту вообще все очень просто. Смотрите как пишут люди и разбирайтесь зачем. Если лень — пользуйтесь готовым.
Re[13]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 06:09
Оценка:
Здравствуйте, Danchik, Вы писали:

D>Да потому что начиная с Win2k SetForegroundWindow перестал работать как ожидалось.


Она работает, как и обещано.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/windows/windowreference/windowfunctions/allowsetforegroundwindow.asp

Т.е., если запускаемое приложение — foreground (а оно и будет таковым, если
его пускает _юзер_: из проводника, командной строки, ярлыка и т.п.),
то оно имеет полное право сделать из требуемого приложения foreground
без всяких ухищрений. Ну, а в противном случае это и не нужно.
--
С уважением, LVT
Re[6]: как узнать
От: Аноним  
Дата: 21.03.06 06:41
Оценка:
Здравствуйте, Leonid Troyanovsky, Вы писали:

CL>> SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);


LT> Это выглядит подозрительно. В соответствие с политикой MS

LT> non-foreground процесс не может стать foreground по своей воле,
LT> а токмо волей foreground процесса.

Тогда — PostMessage ?


Вообще мне нравится unix way — в обговоренном месте создается файлик — либо где зранится PID, либо файл-сокет (аналог Named Pipes).
Вторая прога при старте проверяет существование этого файла, потом или существование процесса с нужным номером и что неомер не reused, а именно другой экземпляр той же проги (напр. откликается на нужные сообщения), или проверяет что сокет открыт и на другом конце дают правлиьный отзыв
Re[7]: как узнать
От: ekamaloff Великобритания  
Дата: 21.03.06 07:23
Оценка:
Здравствуйте, Аноним, Вы писали:

CL>>> SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);


LT>> Это выглядит подозрительно. В соответствие с политикой MS

LT>> non-foreground процесс не может стать foreground по своей воле,
LT>> а токмо волей foreground процесса.

А>Тогда — PostMessage ?


Во-первых, как видно из других сообщений, обработчик WM_RESTOREFROMTRAY ничего противозаконного не делает, в .т.ч. не пытается сделать свое окно foreground-ным. Ну а во-вторых есть AllowSetForegroundWindow.
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[13]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 08:38
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);

CL>SetForegroundWindow(hndl);

CL>все же не то ?


В этом случае сообщение посылается окну приложения.
Менять его оконную процедуру не очень удобно.
С другой стороны, как здесь уже заметили, обработчик
не делает ничего преступного, т.е. можно ограничиться
обработчиком Application.OnMessage, а сообщение посылать
путем PostThreadMessage(tid, WM_RESTOREFROMTRAY, 0, 0),
где tid определяем через GetWindowThreadProcessId.

Т.е.,

SetForegroundWindow(hndl);
PostThreadMessage();
--
С уважением, LVT
Re[7]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 08:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Тогда — PostMessage ?


В данном случае, получается, что, действительно, Post.

А>Вообще мне нравится unix way — в обговоренном месте создается файлик — либо где зранится PID, либо файл-сокет (аналог Named Pipes).


В Windows самый простой способ сделать подобное — именованный file mapping,
связанный не с реальным файлом, а с системным свопом.
--
С уважением, LVT
Re[8]: как узнать
От: Аноним  
Дата: 21.03.06 12:05
Оценка:
А>>Вообще мне нравится unix way — в обговоренном месте создается файлик — либо где зранится PID, либо файл-сокет (аналог Named Pipes).

LT> В Windows самый простой способ сделать подобное — именованный file mapping,

LT> связанный не с реальным файлом, а с системным свопом.

А как потом IPC организовывать ?

С NAmed Pipes понятно.
Если в файл класть Thread ID — то PostThreadMessage.

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

Впрочем, кроме файла ,можно еще в реестре что-нибуждь записать, где-нибудь в DYN DATA
Re[9]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 13:16
Оценка:
Здравствуйте, Аноним, Вы писали:

LT>> В Windows самый простой способ сделать подобное — именованный file mapping,

LT>> связанный не с реальным файлом, а с системным свопом.

А>А как потом IPC организовывать ?


Если нужен полноценный r/w, то нужен еще один (именованный) объект — мьютекс,
который будет отвечать за доступ. Т.е., процессы должны начинать ч/з с захвата
мьютекса, а заканчивать — release.

А>Удаление файла, если процесс упал не удалив файл, мне кажется проще, чем удаление совместно используемого (пусть и крайне недолго) свопа.


Ничего удалять и не надо. Т.е., система удалит маппинг, когда будет закрыт
последний его открытый хендл (с учетом UnMapViewOfFile).
Другими словами, то, что такой маппинг проецируется на системный своп —
забота системы. В жизни может быть так, что данные в своп и не попадут.
--
С уважением, LVT
Re[14]: как узнать
От: CR-LF Россия  
Дата: 21.03.06 13:35
Оценка:
> CL>SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);
> CL>SetForegroundWindow(hndl);
>
> CL>все же не то ?
>
> В этом случае сообщение посылается окну приложения.
> Менять его оконную процедуру не очень удобно.
Не понял...
Кто собирался менять оконную процедуру ?

> С другой стороны, как здесь уже заметили, обработчик

> не делает ничего преступного, т.е. можно ограничиться
> обработчиком Application.OnMessage,
Дык, а чем плохо-то, если у меня этим занимается форма ?
Тем более, что форма ловит только WM_RESTOREFROMTRAY, а
Application.OnMessage — вообще все приходящие сообщения.

>а сообщение посылать

> путем PostThreadMessage(tid, WM_RESTOREFROMTRAY, 0, 0),
> где tid определяем через GetWindowThreadProcessId.
>
> Т.е.,
>
> SetForegroundWindow(hndl);
> PostThreadMessage();
Совсем меня запутали:
SendMessage, PostMessage, PostThreadMessage
Какая разница-то в данном случае ?
Почему PostThreadMessage надо после SetForegroundWindow ?
Posted via RSDN NNTP Server 2.0
Re[15]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 13:50
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Кто собирался менять оконную процедуру ?


А как ты собирался обрабатывать сообщение WM_RESTOREFROMTRAY?

CL>Дык, а чем плохо-то, если у меня этим занимается форма ?

CL>Тем более, что форма ловит только WM_RESTOREFROMTRAY, а
CL>Application.OnMessage — вообще все приходящие сообщения.

Во-первых, не все, а только которые Post.
Во-вторых, какое отношение имеет форма к сообщению
посланному окну приложения.

CL>SendMessage, PostMessage, PostThreadMessage

CL>Какая разница-то в данном случае ?

RTFM: SendMessage, PostMessage, PostThreadMessage

CL>Почему PostThreadMessage надо после SetForegroundWindow ?


Чтобы первая копия стала foreground, и обрабатывала сообщение
уже в этом качестве.
--
С уважением, LVT
Re[16]: как узнать
От: CR-LF Россия  
Дата: 21.03.06 14:47
Оценка:
> CL>Кто собирался менять оконную процедуру ?
>
> А как ты собирался обрабатывать сообщение WM_RESTOREFROMTRAY?
Ну я же показывал:
TMyForm = class(TForm)
    ....
    procedure WMRestoreFtomTray(var Message: TMessage); message 
WM_RESTOREFROMTRAY;
end;

Или в результате компиляции этого кода изменится оконная процедура
приложения ?
Ну и что, собс-сно, если и так ?

> CL>Дык, а чем плохо-то, если у меня этим занимается форма ?

> CL>Тем более, что форма ловит только WM_RESTOREFROMTRAY, а
> CL>Application.OnMessage — вообще все приходящие сообщения.
>
> Во-первых, не все, а только которые Post.
Что значит 'которые Post' ?

> Во-вторых, какое отношение имеет форма к сообщению

> посланному окну приложения.
А главная форма не окно приложения ?

> CL>SendMessage, PostMessage, PostThreadMessage

> CL>Какая разница-то в данном случае ?
>
> RTFM: SendMessage, PostMessage, PostThreadMessage
Ну читал я: SendMessage посылает сообщение и ждет, когда оно будет
обработано.
PostXXXX посылает и не ждет.
А вот какая разница в данном случае между PostMessage и PostThreadMessage
ваще непонятно:
PostMessage посылает сообщение в очередь потока, который создал указанное
окно...
PostThreadMessage посылает сообщение в очередь потока, который нам предстоит
определить с помощью GetWindowThreadProcessId.
GetWindowThreadProcessId получает идентификатор процесса, который создал
указанное окно.
Замкнутый круг, однако.

> CL>Почему PostThreadMessage надо после SetForegroundWindow ?

>
> Чтобы первая копия стала foreground, и обрабатывала сообщение
> уже в этом качестве.
А она (первая копия) знает в каком она качестве находится ?
И есть ли ей разница в каком качестве обрабатывать сообщение ?
Posted via RSDN NNTP Server 2.0
Re[10]: как узнать
От: Аноним  
Дата: 21.03.06 14:50
Оценка:
А>>А как потом IPC организовывать ?

LT>Если нужен полноценный r/w, то нужен еще один (именованный) объект — мьютекс,


...и описанная ниже ручная работа

А мьютексы могут конфликтовать по имени с другими программами, особенно компонентно написанными на Delphi (Mutex1, Mutex2 ии т.д.

А>>Удаление файла, если процесс упал не удалив файл, мне кажется проще, чем удаление совместно используемого (пусть и крайне недолго) свопа.


LT> Ничего удалять и не надо. Т.е., система удалит маппинг, когда будет закрыт

LT> последний его открытый хендл (с учетом UnMapViewOfFile).

Я боюсь что он может оказаться октрыт не только основной программой.
Хотя.. в случае SHARE_DENY_ALL это вряд ли.

Ну, видимо, дело вкуса
Re[17]: как узнать
От: Аноним  
Дата: 21.03.06 14:54
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Или в результате компиляции этого кода изменится оконная процедура

CL>приложения ?

Не должнa IMHO.

>> Во-первых, не все, а только которые Post.

CL>Что значит 'которые Post' ?

То что не те, которые Send.
Send проходят мимо очереди — прямым вызовом оконной процедуры.
Соотв. при этом возхникает (по крайней мере гипотетически) возможность проверять foreground-ли окно отправившее сообщение, права доступа и прочую фигню. Например процессы могут устроить друг другу deadlock

>> Во-вторых, какое отношение имеет форма к сообщению

>> посланному окну приложения.
CL>А главная форма не окно приложения ?

Ни в коем случае!!!

Иначе бы Application.Title == Application.MainForm.Caption


CL>Ну читал я: SendMessage посылает сообщение и ждет, когда оно будет

CL>обработано.

не послыает оно его, на самом деле, примерно как в VCL метод .Perform

CL>PostMessage посылает сообщение в очередь потока, который создал указанное

CL>окно...
CL>PostThreadMessage посылает сообщение в очередь потока, который нам предстоит
CL>определить с помощью GetWindowThreadProcessId.

CL>Замкнутый круг, однако.


Нет. У одного потока может быть 100 окон.
Re[18]: как узнать
От: CR-LF Россия  
Дата: 21.03.06 15:09
Оценка:
>>> Во-первых, не все, а только которые Post.
> CL>Что значит 'которые Post' ?
>
> То что не те, которые Send.
> Send проходят мимо очереди — прямым вызовом оконной процедуры.
> Соотв. при этом возхникает (по крайней мере гипотетически) возможность
> проверять foreground-ли окно
>отправившее сообщение, права доступа и прочую фигню.
А собственно, какая разница первой копии, кто послал ей сообщение ?
Foreground не-foreground.
Че, если не-foreground, то уже и сообщения посылать не моги ?
И какие для этого права нужны ?

>>> Во-вторых, какое отношение имеет форма к сообщению

>>> посланному окну приложения.
> CL>А главная форма не окно приложения ?
>
> Ни в коем случае!!!
Ну хорошо, форма — не окно приложения.
Но она же ловит WM_RESTOREFROMTRAY.

> CL>PostMessage посылает сообщение в очередь потока, который создал

> указанное
> CL>окно...
> CL>PostThreadMessage посылает сообщение в очередь потока, который нам
> предстоит
> CL>определить с помощью GetWindowThreadProcessId.
>
> CL>Замкнутый круг, однако.
>
> Нет. У одного потока может быть 100 окон.
Блин, я самый тупой на этом форуме
Ну и что, что 100 окон ?
Какому бы из них я не посылал сообщение, поток-получатель-то один.
Posted via RSDN NNTP Server 2.0
Re[17]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 15:17
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Ну и что, собс-сно, если и так ?


> move(Application.Handle, p^, SizeOf(HWND));


Записываем хендл окна Application, и далее посылаем
ему сообщение, а ожидаем его получить в обработчике формы,
т.е., в другом окне.

>> Во-первых, не все, а только которые Post.

CL>Что значит 'которые Post' ?

Use OnMessage to trap any or all Windows messages posted
to all windows in the application

CL>А главная форма не окно приложения ?


Окно приложения — это совершенно специальное окно,
не имеющая отношения к окнам форм приложения.
Его ты можешь представить как окно, которое показывает
кнопку на таскбаре.

>> CL>SendMessage, PostMessage, PostThreadMessage

>> CL>Какая разница-то в данном случае ?

CL>А вот какая разница в данном случае между PostMessage и PostThreadMessage

CL>ваще непонятно:

В данном случае, это не так и важно, т.е. можно и так PostMessage(hndl,..).
Просто, сообщения посылаемые потоку не будут передаваться окну,
т.е., обработка его закончится в OnMessage.

CL>И есть ли ей разница в каком качестве обрабатывать сообщение ?


Можно представить и такое.
--
С уважением, LVT
Re[11]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 15:30
Оценка:
Здравствуйте, Аноним, Вы писали:

LT>>Если нужен полноценный r/w, то нужен еще один (именованный) объект — мьютекс,


А>...и описанная ниже ручная работа


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

А>А мьютексы могут конфликтовать по имени с другими программами, особенно компонентно написанными на Delphi (Mutex1, Mutex2 ии т.д.


В конкретных случаях можно организовать работу и с анонимными объектами,
хоть anonymous pipe. Только, необходим дополнительный способ IPC —
для значения хендла (4 байта).

А>Я боюсь что он может оказаться октрыт не только основной программой.


Если он открыт еще кем-то, значит у кого-то есть его открытый хендл.
Когда будет закрыт последний — система и удалит маппинг.
--
С уважением, LVT
Re[18]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 15:37
Оценка:
Здравствуйте, Аноним, Вы писали:

CL>>Ну читал я: SendMessage посылает сообщение и ждет, когда оно будет

CL>>обработано.

А>не послыает оно его, на самом деле, примерно как в VCL метод .Perform


На самом деле посылает. На самом деле у GUI потока есть и такая очередь —
синхронных сообщений. Подробности можно посмотреть у Джефа Рихтера.
--
С уважением, LVT
Re[19]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 15:44
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Какому бы из них я не посылал сообщение, поток-получатель-то один.


Те, что посланы конкретному окну попадут в его оконную процедуру.
Те, что посланы потоку имеют в параметре msg.Hwnd = 0,
ну и никуда далее не попадут.
--
С уважением, LVT
Re[18]: как узнать
От: CR-LF Россия  
Дата: 21.03.06 15:45
Оценка:
>> move(Application.Handle, p^, SizeOf(HWND));
>
> Записываем хендл окна Application, и далее посылаем
> ему сообщение, а ожидаем его получить в обработчике формы,
> т.е., в другом окне.
А-а-а, ну да, ну да

>>> Во-первых, не все, а только которые Post.

> CL>Что значит 'которые Post' ?
>
> Use OnMessage to trap any or all Windows messages posted
> to all windows in the application
А ниже:
Caution: Thousands of messages per second flow though this event. Be careful
when coding the handler, because it can affect the performance of the entire
application.
Хотя, в свете изложенного выше, наверное, все-таки придется писать
Application.OnMessage.
А пока у меня остается
    hndl := FindWindow('TMyForm', 'My form's caption');
    if hndl <> 0 then begin
      SendMessage(hndl,WM_RESTOREFROMTRAY,0,0);
      SetForegroundWindow(hndl);
    end;

И мы вновь возвращаемся к началу нашего увлекательного разговора


> CL>А вот какая разница в данном случае между PostMessage и

> PostThreadMessage
> CL>ваще непонятно:
>
> В данном случае, это не так и важно, т.е. можно и так
> PostMessage(hndl,..).
> Просто, сообщения посылаемые потоку не будут передаваться окну,
> т.е., обработка его закончится в OnMessage.
Ну понял, понял.
Не перестаю я дивиться этому форуму.
Вот если бы в институте так объясняли
Posted via RSDN NNTP Server 2.0
Re[12]: как узнать
От: CR-LF Россия  
Дата: 21.03.06 15:52
Оценка:
> Для совместного доступа, скажем, к физическому файлу ручной работы не
> меньше.
Кстати, а мне идея с физическим файлом нравится.
Главное все просто и понятно
Posted via RSDN NNTP Server 2.0
Re[19]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 15:58
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Caution: Thousands of messages per second flow though this event. Be careful

CL>when coding the handler, because it can affect the performance of the entire
CL>application.

Если требуется подобная осторожность, то можно назначать нужный
обработчик в Application.OnDeactivate, а OnActivate — его обнилить.
Неактивным окнам достается немного из этих тысяч.
Насколько при этом улучшиться performance мне трудно судить

CL>И мы вновь возвращаемся к началу нашего увлекательного разговора


Ну, надеюсь уже на другом уровне
--
С уважением, LVT
Re[13]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 16:05
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Кстати, а мне идея с физическим файлом нравится.


На худой конец можно и так.
Если с флагом FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY.
--
С уважением, LVT
Re[11]: как узнать
От: Rius Россия  
Дата: 21.03.06 16:21
Оценка:
Здравствуйте, Аноним, Вы писали:

А>...и описанная ниже ручная работа


А>А мьютексы могут конфликтовать по имени с другими программами, особенно компонентно написанными на Delphi (Mutex1, Mutex2 ии т.д.


а GUID для чего придумали?
Re[12]: как узнать
От: Leonid Troyanovsky  
Дата: 21.03.06 16:31
Оценка:
Здравствуйте, Rius, Вы писали:

R>а GUID для чего придумали?


Видимо, для того чтобы через наиболее полюбившиеся экзамплы
они проникали в широкие компьютерные массы.
--
С уважением, LVT
Re[14]: как узнать
От: CR-LF Россия  
Дата: 21.03.06 16:32
Оценка:
> CL>Кстати, а мне идея с физическим файлом нравится.
>
> На худой конец можно и так.
> Если с флагом FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY.

Это откуда ?
Я вообще-то имел ввиду
if FileExists('somefile.pid') then // это вторая копия
else begin // это первая копия
  AssignFile(F, 'somefile.pid');
  Rewrite(F);
  CloseFile(F);
end;

Posted via RSDN NNTP Server 2.0
Re[15]: как узнать
От: Leonid Troyanovsky  
Дата: 22.03.06 05:42
Оценка:
Здравствуйте, CR-LF, Вы писали:

CL>Это откуда ?


RTFM: CreateFile.

CL>Я вообще-то имел ввиду


Нужно предусмотреть терминирование процесса, т.е., случаи,
когда он не сможет удалить файл при завершении.
--
С уважением, LVT
Re[19]: как узнать
От: Аноним  
Дата: 22.03.06 06:23
Оценка:
CL>Не перестаю я дивиться этому форуму.

Ага, обсуждение WINAPI вопросов в форуме Delphi

CL>Вот если бы в институте так объясняли


Ну не знаю, нас в школе мучали Win16 + BorlandC++ + OWL

Не то чтобы сильно объясняли — но доки читать рекомендовали :D
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.