> А ты не вызывай ShowWindow напрямую. Ты лучше пошли PostMessage'м месагу > типа > WM_APP + 100 > и отлавливая ее юзай ShowWindow.
А так, чтобы не заводить обработчик сообщений не получится ?
> CL>Вопрос: как эта первая копия может узнать, что его отобразили с помощью > CL>ShowWindow ? > неверный способ обнаружения уже запущенной копии
С чего ты взял ?
Я кажется вообще не показывал каким образом я это делаю.
Здравствуйте, 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;
>>> неверный способ обнаружения уже запущенной копии > 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;
Здравствуйте, 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;
> 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) ...
Тока она потом не хочет обратно в трей заворачиваться.
Не знаю почему.
Здравствуйте, 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
(ищешь-то ты другое окно), единственная ли форма у приложения и т.д.
Кроме того, часто для подобных приложений кнопку в таскбаре прячут.
> CL>Что такое mmf ? > > Оно и есть, memory mapped file.
А как это по-русски-то называется ?
И вообще зачем такие файлы нужны ?
> CL>Так а зачем туда что-то записывать и, главное, как ? > > Чтобы там был, например, хендл того окна, который нужно поднять.
Так а чем плохо FindWindow ?
> Пишем (читаем) так: MapViewOfFile, Move
Move — это паскалевская процедура ?
И как ей в данном случае воспользоваться ?
> > CL>Дык вторая копия же foreground ... > CL>Она следующей строкой первую и сделает foreground. > > Ну, а зачем тогда WM_RESTOREFROMTRAY? Что должна делать первая копия > при получении оного?
> > 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>А так, чтобы не заводить обработчик сообщений не получится ?
Здравствуйте, 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.
Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя использовать FindWindow для поиска уже запущеной програмы
Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы быстренько накликали на запуск програмы, а она успела создать нужное окно.
Для этого правильно использовать обьекты синхронизации, например мютексы — CreateMutex.
Пример я закидывал давным давно здесь
>>> Оно и есть, memory mapped file. > CL>А как это по-русски-то называется ? > CL>И вообще зачем такие файлы нужны ? > > Файлы, проецируемые в память. Используются, например, для обмена > данными между процессами.
Припоминается что-то из FreeBSD
> CL>Move — это паскалевская процедура ? > CL>И как ей в данном случае воспользоваться ? > > Help: Move Example
Ну и чего ?
Там стандартный пример, а в данном случае что написать вместо ???? (см.
ниже)
> CL>Да и вообще при чем тут таскбар ? > Потому, как варианты прятать/не прятать имеют свои особенности. > А при управлении окнами (даже своими) нельзя пренебрегать ни одной, > казалось бы, мелочью. > Например, хотим мы показать форму, не активируя ее. > Казалось, чего проще: ShowWindow(Handle, SW_SHOWNA), однако, > для корректной работы этой формы потребуется, кроме того, Visible:= True.
А я уже здесь как-то спрашивал, как мне узнать, что окно было развернуто с
помощью ShowWindow.
Вопрос остался открытым, вот я и сделал как сейчас, т.е. когда ему
посылается WM_RESTOREFROMTRAY, а оно уже само себя разворачивает.
Пока все работает нормально.
Здравствуйте, Danchik, Вы писали:
D>Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя использовать FindWindow для поиска уже запущеной програмы
А что дало тебе уверенность в том, что я ее не читал?
Возможность использования FindWindow я не отвергал, бо она есть.
D>Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы быстренько накликали на запуск програмы, а она успела создать нужное окно.
Никто не запрещает сначала убедиться, что окно есть (скажем, из существования
объекта ядра), а затем его искать.
D>Для этого правильно использовать обьекты синхронизации, например мютексы — CreateMutex.
Да, млин, какие еще мьютексы, если у нас готовый mmf (мог бы и почитать сначала)
D>Здесь же можна посмотреть как правильно вызвать SetForegroundWindow через AttachThreadInput.
Не вижу связи между правильностью вызова SFW и AttachThreadInput.
Если же речь идет об обходе запретов MS — даже обсуждать не хочу.
> Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя > использовать FindWindow для >поиска уже запущеной програмы
Оп-п-паньки !!!
А что тогда ? — Использовать FindWindow для поиска незапущенных программ ?!
> Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы > быстренько накликали на >запуск програмы, а она успела создать нужное окно.
Так я же ищу первую копию, которая была создана давно.
> > Для этого правильно использовать обьекты синхронизации, например мютексы — > CreateMutex. > Пример я закидывал давным давно > здесь<br />
<span class='lineQuote level1'>></span>
Здравствуйте, CR-LF, Вы писали:
CL>MapViewOfFile(hFile, FILE_MAP_WRITE, 0, 0, 4);
Здесь лучше последним 0, т.е. просмотр на весь файл.
А, вообще-то, это функция, возвращающая при удаче
указатель на начало просмотра.
CL>move(Application.Handle, ????, SizeOf(HWND));
Здравствуйте, 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 перестал работать как ожидалось.
Здравствуйте, CR-LF, Вы писали:
>> Я бы сначала посоветовал почитать ветку где обговаривается почему нельзя >> использовать FindWindow для >>поиска уже запущеной програмы CL>Оп-п-паньки !!! CL>А что тогда ? — Использовать FindWindow для поиска незапущенных программ ?!
Просто если критерием запущенности программы считать созданное окно, то у нас могут быть накладки. Поэтому рекомендуется пользоваться обьектами синхронизации в паре с FindWindow
>> Если вкратце в двух словах, то просто мы не сможем гарантировать то что мы >> быстренько накликали на >>запуск програмы, а она успела создать нужное окно. CL>Так я же ищу первую копию, которая была создана давно.
В основном работать будет. Но где гарантия что вы сделали два DblClik по иконке запуска
>> >> Для этого правильно использовать обьекты синхронизации, например мютексы — >> CreateMutex. >> Пример я закидывал давным давно >> здесь<br />
<span class='lineQuote level2'>>></span>
CL>Да уж ;( CL>Очень просто ...
Очень просто только в одно место ходят
Я предложил целый работающий юнит, ваше дело пользоваться ли им или нет. Есть еще реализация от Jedi Code Library — JclAppInst.pas. Ту вообще все очень просто. Смотрите как пишут люди и разбирайтесь зачем. Если лень — пользуйтесь готовым.
Т.е., если запускаемое приложение — 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, а именно другой экземпляр той же проги (напр. откликается на нужные сообщения), или проверяет что сокет открыт и на другом конце дают правлиьный отзыв
Здравствуйте, Аноним, Вы писали:
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
Здравствуйте, CR-LF, Вы писали:
CL>SendMessage(hndl,WM_RESTOREFROMTRAY,0,0); CL>SetForegroundWindow(hndl);
CL>все же не то ?
В этом случае сообщение посылается окну приложения.
Менять его оконную процедуру не очень удобно.
С другой стороны, как здесь уже заметили, обработчик
не делает ничего преступного, т.е. можно ограничиться
обработчиком Application.OnMessage, а сообщение посылать
путем PostThreadMessage(tid, WM_RESTOREFROMTRAY, 0, 0),
где tid определяем через GetWindowThreadProcessId.
Здравствуйте, Аноним, Вы писали:
А>Тогда — 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
Здравствуйте, Аноним, Вы писали:
LT>> В Windows самый простой способ сделать подобное — именованный file mapping, LT>> связанный не с реальным файлом, а с системным свопом.
А>А как потом IPC организовывать ?
Если нужен полноценный r/w, то нужен еще один (именованный) объект — мьютекс,
который будет отвечать за доступ. Т.е., процессы должны начинать ч/з с захвата
мьютекса, а заканчивать — release.
А>Удаление файла, если процесс упал не удалив файл, мне кажется проще, чем удаление совместно используемого (пусть и крайне недолго) свопа.
Ничего удалять и не надо. Т.е., система удалит маппинг, когда будет закрыт
последний его открытый хендл (с учетом UnMapViewOfFile).
Другими словами, то, что такой маппинг проецируется на системный своп —
забота системы. В жизни может быть так, что данные в своп и не попадут.
> 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 ?
Здравствуйте, 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, и обрабатывала сообщение
уже в этом качестве.
Или в результате компиляции этого кода изменится оконная процедура
приложения ?
Ну и что, собс-сно, если и так ?
> 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>Замкнутый круг, однако.
>>> Во-первых, не все, а только которые Post. > CL>Что значит 'которые Post' ? > > То что не те, которые Send. > Send проходят мимо очереди — прямым вызовом оконной процедуры. > Соотв. при этом возхникает (по крайней мере гипотетически) возможность > проверять foreground-ли окно >отправившее сообщение, права доступа и прочую фигню.
А собственно, какая разница первой копии, кто послал ей сообщение ?
Foreground не-foreground.
Че, если не-foreground, то уже и сообщения посылать не моги ?
И какие для этого права нужны ?
>>> Во-вторых, какое отношение имеет форма к сообщению >>> посланному окну приложения. > CL>А главная форма не окно приложения ? > > Ни в коем случае!!!
Ну хорошо, форма — не окно приложения.
Но она же ловит WM_RESTOREFROMTRAY.
> CL>PostMessage посылает сообщение в очередь потока, который создал > указанное > CL>окно... > CL>PostThreadMessage посылает сообщение в очередь потока, который нам > предстоит > CL>определить с помощью GetWindowThreadProcessId. > > CL>Замкнутый круг, однако. > > Нет. У одного потока может быть 100 окон.
Блин, я самый тупой на этом форуме
Ну и что, что 100 окон ?
Какому бы из них я не посылал сообщение, поток-получатель-то один.
Здравствуйте, 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>И есть ли ей разница в каком качестве обрабатывать сообщение ?
Здравствуйте, Аноним, Вы писали:
LT>>Если нужен полноценный r/w, то нужен еще один (именованный) объект — мьютекс,
А>...и описанная ниже ручная работа
Для совместного доступа, скажем, к физическому файлу ручной работы не меньше.
А>А мьютексы могут конфликтовать по имени с другими программами, особенно компонентно написанными на Delphi (Mutex1, Mutex2 ии т.д.
В конкретных случаях можно организовать работу и с анонимными объектами,
хоть anonymous pipe. Только, необходим дополнительный способ IPC —
для значения хендла (4 байта).
А>Я боюсь что он может оказаться октрыт не только основной программой.
Если он открыт еще кем-то, значит у кого-то есть его открытый хендл.
Когда будет закрыт последний — система и удалит маппинг.
Здравствуйте, Аноним, Вы писали:
CL>>Ну читал я: SendMessage посылает сообщение и ждет, когда оно будет CL>>обработано.
А>не послыает оно его, на самом деле, примерно как в VCL метод .Perform
На самом деле посылает. На самом деле у GUI потока есть и такая очередь —
синхронных сообщений. Подробности можно посмотреть у Джефа Рихтера.
>> 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.
Ну понял, понял.
Не перестаю я дивиться этому форуму.
Вот если бы в институте так объясняли
> Для совместного доступа, скажем, к физическому файлу ручной работы не > меньше.
Кстати, а мне идея с физическим файлом нравится.
Главное все просто и понятно
Здравствуйте, 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>И мы вновь возвращаемся к началу нашего увлекательного разговора
Здравствуйте, Аноним, Вы писали:
А>...и описанная ниже ручная работа
А>А мьютексы могут конфликтовать по имени с другими программами, особенно компонентно написанными на Delphi (Mutex1, Mutex2 ии т.д.
> 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;