Что такое код getmessage


Какая разница между GetMessage и PeekMessage

Я так понимаю что обе функции берут сообщении из очереди и отправляют их на обработку оконной функции. Но работают они немного по разному. Знаю, их описания есть в Win SDK но я мало че понял. Какая функцмя и чему передает управление?

GetMessage ждет сообщение и выходит только если окно получило сообщение. PeekMessage выходит сразу в не зависимости от того есть сообщение или нет

GetMessage ждёт сообщение, возвращает его, и удаляет из очереди.
PeekMessage не ждёт, и не удаляет из очереди.

Nikopol
>GetMessage ждёт сообщение, возвращает его, и удаляет из очереди.
>PeekMessage не ждёт, и не удаляет из очереди.
Не совсем так. Во первых, есть PM_NOREMOVE/PM_REMOVE
Во вторых, можно задавать опции — сообщения какого типа надо выбирать из очереди.

Ну я просто обобщил и упростил :)

Вопрос в тему. Есть случаи в моей практике, когда у меня не использует обработка в цикле. Например работает один GUI, при этом использовать PeekMessage не рационально — потому что он грузит на 100 % проц. В таком случае рациональне было бы юзать, как мне кажется, GetMessage.

Собственно вопрос можно ли это как-нить совместить и рационально ли это? Делает ли так кто-нить или мне забить?

Osiris
ну посмотри исходники того же квейка — там все это есть.

1. Обе функции — не отправляют сообщение оконной процедуре. Это делает DispatchMessage.
2. PeekMessage в любом случае (независимо от PM_REMOVE / PM_NOREMOVE) не ждет прихода сообщений, если их нет — она возвращает ложь. GetMessage — ждет.
3. PeekMessage не обязательно будет грузить на 100%. Можно обрабатывать сообщения, пока они есть — примерно так:
while (PeekMessage (. ))
<
if (msg.message == WM_QUIT)
break;
DispatchMessage (. );
>;
К тому же есть такие функции, как MsgWaitForMultipleObjects.

Вот упрощенный отрывок кода из моей игрушки:

Какой безопасный способ использовать GetMessage или PeekMessage в Java-коде с помощью JNA?

Я пытаюсь получить события WM_HOTKEY в своем Java-коде. Я успешно получил отработавший код, но я знаю, что интеграция кода Java GUI с коннетом сообщений Windows следует проявлять осторожность.

Из примеров Windows видно, что User32.INSTANCE.GetMessage является ключевой функцией для уведомления о событиях WM_HOTKEY, которые я зарегистрировал для использования User32.INSTANCE.RegisterHotKey

Итак. Я хотел бы знать:

  • Правильно ли я понял, что RegisterHotKey и мой цикл сообщений должны работать в одном потоке Java?
  • Правильно ли я понял, что функция GetMessage Windows должна вызываться из того же потока, который я использую для создания Windows, который является Java Swing Event Dispatch Thread?
  • Если это так, я не могу создать цикл сообщений в Thread Dispatch Thread, поскольку он блокирует другие события. Должен ли я использовать PeekMessage?
  • Если это так, у меня будет код для голосования, который не является моим любимым. Как часто я могу позвонить PeekMessage? Является ли PeekMessage легко и быстро?

Большое спасибо за помощь программисту Java в том, что он задумался над концепциями Win API.

Правильно ли я понял, что RegisterHotKey и мой цикл сообщений должны работать в одном потоке Java?

Да. Это упоминается в документации RegisterHotKey() :

Эта функция не может связывать горячую клавишу с окном, созданным другим потоком

Правильно ли я понял, что функция GetMessage Windows должна вызываться из того же потока, который я использую для создания Windows, который является Java Swing Event Dispatch Thread?

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

Если это так, я не могу создать цикл сообщений в Thread Dispatch Thread, поскольку он блокирует другие события. Должен ли я использовать PeekMessage?

Если это так, у меня будет код для голосования, который не является моим любимым. Как часто я могу позвонить PeekMessage? Является ли PeekMessage легко и быстро?

Я бы предложил создать выделенный поток, который создает свое собственное окно и использует GetMessage() для своего цикла сообщений.

Поток с GetMessage

01.09.2012, 10:15

Скопировать поток и добавить ошибки в поток
Здорова господа! Есть задачка: «Скопируйте поток объектов типа Name_and_address и вставьте в.

Скопировать поток в поток
Есть ли возможность скопировать один поток в другой. Например int main() < ofstream.

Qt+WinAPI. Бесконечный GetMessage
Пишу программу, потребовалось глоабльно перехватывать клавиши. Пытался использовать qxt, но под qt.

01.09.2012, 11:01 2 01.09.2012, 11:02 [ТС] 3

вот так я запускаю поток

01.09.2012, 11:32 4
01.09.2012, 11:32
01.09.2012, 11:40 5
01.09.2012, 13:11 [ТС] 6

Черт, там я внизу написал, я решил эту проблему. Теперь всё норм с циклом.

Другая проблема, как получать сообщения от консоли в отдельном потоке?

Добавлено через 51 секунду

Да-да, именно так и сделал

Просто через CreateThread почему с таким циклом, как у вас, зависало.

Вот,кстати, с таким циклом у меня никак сообщения в функции WndProc, отвечающей за их обработку, не обрабатываются

Как будто бы, GetMessage не работает в другом потоке

msg.hwnd пустым остается, хотя я кликаю например правой кнопкой по консоли

01.09.2012, 13:41 7
01.09.2012, 13:51 [ТС] 8

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

Поэтому я могу сделать это при помощи цикла в отдельном потоке. Затолкать же саму процедуру для записи звука в отдельный поток геморно

GetMessage function

Retrieves a message from the calling thread’s message queue. The function dispatches incoming sent messages until a posted message is available for retrieval.

Unlike GetMessage, the PeekMessage function does not wait for a message to be posted before returning.

Syntax

Parameters

A pointer to an MSG structure that receives message information from the thread’s message queue.

A handle to the window whose messages are to be retrieved. The window must belong to the current thread.

If hWnd is NULL, GetMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread’s message queue whose hwnd value is NULL (see the MSG structure). Therefore if hWnd is NULL, both window messages and thread messages are processed.

If hWnd is -1, GetMessage retrieves only messages on the current thread’s message queue whose hwnd value is NULL, that is, thread messages as posted by PostMessage (when the hWnd parameter is NULL) or PostThreadMessage.

The integer value of the lowest message value to be retrieved. Use WM_KEYFIRST (0x0100) to specify the first keyboard message or WM_MOUSEFIRST (0x0200) to specify the first mouse message.

Use WM_INPUT here and in wMsgFilterMax to specify only the WM_INPUT messages.


If wMsgFilterMin and wMsgFilterMax are both zero, GetMessage returns all available messages (that is, no range filtering is performed).

The integer value of the highest message value to be retrieved. Use WM_KEYLAST to specify the last keyboard message or WM_MOUSELAST to specify the last mouse message.

Use WM_INPUT here and in wMsgFilterMin to specify only the WM_INPUT messages.

If wMsgFilterMin and wMsgFilterMax are both zero, GetMessage returns all available messages (that is, no range filtering is performed).

Return Value

Type: Type: BOOL

If the function retrieves a message other than WM_QUIT, the return value is nonzero.

If the function retrieves the WM_QUIT message, the return value is zero.

If there is an error, the return value is -1. For example, the function fails if hWnd is an invalid window handle or lpMsg is an invalid pointer. To get extended error information, call GetLastError.

Because the return value can be nonzero, zero, or -1, avoid code like this:

The possibility of a -1 return value in the case that hWnd is an invalid parameter (such as referring to a window that has already been destroyed) means that such code can lead to fatal application errors. Instead, use code like this:

Remarks

An application typically uses the return value to determine whether to end the main message loop and exit the program.

The GetMessage function retrieves messages associated with the window identified by the hWnd parameter or any of its children, as specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and wMsgFilterMax parameters. Note that an application can only use the low word in the wMsgFilterMin and wMsgFilterMax parameters; the high word is reserved for the system.

Note that GetMessage always retrieves WM_QUIT messages, no matter which values you specify for wMsgFilterMin and wMsgFilterMax.

During this call, the system delivers pending, nonqueued messages, that is, messages sent to windows owned by the calling thread using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. Then the first queued message that matches the specified filter is retrieved. The system may also process internal events. If no filter is specified, messages are processed in the following order:

  • Sent messages
  • Posted messages
  • Input (hardware) messages and system internal events
  • Sent messages (again)
  • WM_PAINT messages
  • WM_TIMER messages

To retrieve input messages before posted messages, use the wMsgFilterMin and wMsgFilterMax parameters.

GetMessage does not remove WM_PAINT messages from the queue. The messages remain in the queue until processed.

If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not responding and replaces it with a ghost window that has the same z-order, location, size, and visual attributes. This allows the user to move it, resize it, or even close the application. However, these are the only actions available because the application is actually not responding. When in the debugger mode, the system does not generate a ghost window.

Что такое безопасный способ использования GetMessage или PeekMessage в Java-коде с использованием JNA?

Я пытаюсь получить события WM_HOTKEY в своем Java-коде. Я успешно получил отработавший код, но я знаю, что интеграция кода Java GUI с коннетом сообщений Windows следует проявлять осторожность.

Из примеров Windows видно, что User32.INSTANCE.GetMessage является ключевой функцией для уведомления о событиях WM_HOTKEY, которые я зарегистрировал для использования User32.INSTANCE.RegisterHotKey

Итак . Я хотел бы знать:

  • Правильно ли я понял, что RegisterHotKey и мой цикл сообщений должны работать на одном и том же потоке Java?
  • Правильно ли я понял, что функция GetMessage Windows должна быть вызвана из того же потока, который я использую для создания Windows, который представляет собой событие Java Swing Dispatch Thread?
  • Если это так, я не могу создать цикл сообщений в Thread Dispatch Thread, поскольку он блокирует другие события. Должен ли я использовать PeekMessage вместо этого?
  • Если да, у меня будет код опроса, который не является моим любимым. Как часто я могу позвонить PeekMessage? Является ли PeekMessage легким и быстрым?

Большое спасибо за помощь программисту Java в том, что он задумался над концепциями Win API.

Какая разница между GetMessage и PeekMessage

Я так понимаю что обе функции берут сообщении из очереди и отправляют их на обработку оконной функции. Но работают они немного по разному. Знаю, их описания есть в Win SDK но я мало че понял. Какая функцмя и чему передает управление?

GetMessage ждет сообщение и выходит только если окно получило сообщение. PeekMessage выходит сразу в не зависимости от того есть сообщение или нет

GetMessage ждёт сообщение, возвращает его, и удаляет из очереди.
PeekMessage не ждёт, и не удаляет из очереди.

Nikopol
>GetMessage ждёт сообщение, возвращает его, и удаляет из очереди.
>PeekMessage не ждёт, и не удаляет из очереди.
Не совсем так. Во первых, есть PM_NOREMOVE/PM_REMOVE
Во вторых, можно задавать опции — сообщения какого типа надо выбирать из очереди.

Ну я просто обобщил и упростил :)

Вопрос в тему. Есть случаи в моей практике, когда у меня не использует обработка в цикле. Например работает один GUI, при этом использовать PeekMessage не рационально — потому что он грузит на 100 % проц. В таком случае рациональне было бы юзать, как мне кажется, GetMessage.

Собственно вопрос можно ли это как-нить совместить и рационально ли это? Делает ли так кто-нить или мне забить?

Osiris
ну посмотри исходники того же квейка — там все это есть.

1. Обе функции — не отправляют сообщение оконной процедуре. Это делает DispatchMessage.
2. PeekMessage в любом случае (независимо от PM_REMOVE / PM_NOREMOVE) не ждет прихода сообщений, если их нет — она возвращает ложь. GetMessage — ждет.
3. PeekMessage не обязательно будет грузить на 100%. Можно обрабатывать сообщения, пока они есть — примерно так:
while (PeekMessage (. ))
<
if (msg.message == WM_QUIT)
break;
DispatchMessage (. );
>;
К тому же есть такие функции, как MsgWaitForMultipleObjects.

Вот упрощенный отрывок кода из моей игрушки:

Какой безопасный способ использовать GetMessage или PeekMessage в Java-коде с помощью JNA?

Я пытаюсь получить события WM_HOTKEY в своем Java-коде. Я успешно получил отработавший код, но я знаю, что интеграция кода Java GUI с коннетом сообщений Windows следует проявлять осторожность.

Из примеров Windows видно, что User32.INSTANCE.GetMessage является ключевой функцией для уведомления о событиях WM_HOTKEY, которые я зарегистрировал для использования User32.INSTANCE.RegisterHotKey

Итак. Я хотел бы знать:

  • Правильно ли я понял, что RegisterHotKey и мой цикл сообщений должны работать в одном потоке Java?
  • Правильно ли я понял, что функция GetMessage Windows должна вызываться из того же потока, который я использую для создания Windows, который является Java Swing Event Dispatch Thread?
  • Если это так, я не могу создать цикл сообщений в Thread Dispatch Thread, поскольку он блокирует другие события. Должен ли я использовать PeekMessage?
  • Если это так, у меня будет код для голосования, который не является моим любимым. Как часто я могу позвонить PeekMessage? Является ли PeekMessage легко и быстро?

Большое спасибо за помощь программисту Java в том, что он задумался над концепциями Win API.

Правильно ли я понял, что RegisterHotKey и мой цикл сообщений должны работать в одном потоке Java?

Да. Это упоминается в документации RegisterHotKey() :

Эта функция не может связывать горячую клавишу с окном, созданным другим потоком

Правильно ли я понял, что функция GetMessage Windows должна вызываться из того же потока, который я использую для создания Windows, который является Java Swing Event Dispatch Thread?

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

Если это так, я не могу создать цикл сообщений в Thread Dispatch Thread, поскольку он блокирует другие события. Должен ли я использовать PeekMessage?

Если это так, у меня будет код для голосования, который не является моим любимым. Как часто я могу позвонить PeekMessage? Является ли PeekMessage легко и быстро?

Я бы предложил создать выделенный поток, который создает свое собственное окно и использует GetMessage() для своего цикла сообщений.

Объедините GetMessage и PeekMessage

Я намерен создать небольшое приложение с двумя окнами, обычным окном с элементами управления и трехмерным окном, визуализированным с помощью DirectX. Для 3D окна PeekMessage() рекомендуется, потому что он не ждет после проверки сообщений, но для обычных окон (без 3D-рендеринга) GetMessage() Функция используется, чтобы избежать бессмысленного использования процессора.
Итак, когда 3D-окно активно ( WM_ACTIVE сообщение получено) хочу использовать PeekMessage() и когда нормальное окно активно, я хочу использовать GetMessage() ,

Основной цикл будет выглядеть так:

В обработчике сообщений этих окон у меня есть WM_ACTIVATE сообщение:

Я ожидаю, что TaskManager покажет, что приложение занято (

50% использования процессора), когда 3D-окно активно, и не так занято, когда активно обычное окно (

5% загрузки процессора). Я вижу только 50% использования процессора, когда оба окна потеряли фокус, но я вижу 0-5% использования процессора, когда любое из них активно. Я считаю, что должна быть разница, поэтому я не уверен, действительно ли это работает (или даже возможно). Отображается трехмерное окно, и обычное окно тоже реагирует на события, но использование процессора смущает меня. Я просто не хочу, чтобы это влияло на FPS 3D-окна.


Решение

Вместо того, чтобы проверять, является ли нормальное окно активным, вы должны проверить, является ли 3D-окно неактивным. Вы также можете использовать WaitMessage вместо GetMessage потому что это спасает вас от дублирования кода.

Кажется, ваша проблема в том, что когда обычное окно неактивно, цикл обработки сообщений не ждет, даже если 3D-окно неактивно.

Если вы решили использовать WaitMessage Вы должны также зацикливаться на PeekMessage потому что может быть более одного сообщения в очереди и WaitMessage не возвращается, пока не придет новое сообщение.

исключение.getMessage () вывод с именем класса

Я пытаюсь решить проблему, в моем приложении есть этот код

и object1 сделает что-то подобное:

Я получаю сообщение на панели параметров, например: Error: java.lang.RuntimeException: Cannot move file

но я использовал getMessage , а не toString

Что я делаю не так? Я уже пробовал со множеством исключений, даже Exception . Я пытаюсь решить эту проблему без необходимости реализации собственного подкласса Exception

ПРОБЛЕМА РЕШЕНА — спасибо всем!

Try и catch действительно вызывались в методе get () из SwingWorker, который создает ExecutionException с моим исключением, брошенным из doInBackground () Я исправил это:

2 ответа

Я думаю, вы заключили свое исключение в другое исключение (которого нет в вашем коде выше). Если вы попробуете этот код:

. вы увидите всплывающее окно, которое говорит именно то, что вы хотите.

Однако, чтобы решить вашу проблему (исключение в оболочке), вам нужно перейти к «корневому» исключению с «правильным» сообщением. Для этого вам нужно создать собственный рекурсивный метод getRootCause :

Примечание. Развертывание исключений, подобных этой, как бы разбивает абстракции. Я рекомендую вам выяснить, почему исключение обернуто, и спросить себя, имеет ли оно смысл.

Я предполагаю, что в method1 есть что-то, что оборачивает одно исключение в другое и использует toString() вложенного исключения в качестве сообщения оболочки. Я предлагаю вам взять копию вашего проекта и удалить как можно больше, сохраняя проблему, до тех пор, пока у вас не появится короткая, но полная программа, демонстрирующая ее — в какой момент либо будет понятно, что происходит, либо мы будем в лучшем положении, чтобы помочь исправить это.

Что такое код getmessage

В отдельном потоке (TThread) создаю форму:

procedure TTest.Execute;
var
msg:TMsg;
wnd:HWND;
wc:WNDCLASS;
begin
wc.style:=0;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=hInstance;
wc.hIcon:=0;
wc.hCursor:=0;
wc.hbrBackground:=GetStockObject(LTGRAY_BRUSH);
wc.lpszMenuName:=nil;
wc.lpsz ;
wc.lpfnWndProc:=@WndProc;

Windows.RegisterClass(wc);
wnd:=CreateWindow(
«asdasd»,
«Hello world»,
WS_CAPTION,
10,
10,
200,
80,
HWND_DESKTOP,
0,
hInstance,
nil
);

while GetMessage(Msg,wnd,0,0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;

DestroyWindow(wnd);
Windows.UnRegisterClass(«asdasd», hInstance);
end;

WndProc выглядит примерно так:

function WndProc(wnd:HWND; msg:UINT; w:UINT; l:UINT):UINT;stdcall;
var
begin
Result:=0;
case msg of
WM_QUIT: ;
WM_PAINT: ;
else
Result:=DefWindowProc(wnd,msg,w,l);
end;
end;

В основном потоке создаю отдельный поток:

var
T: TTest;
procedure TForm1.Button1Click(Sender: TObject);
begin
T := TTest.Create(true);
with T do
begin
FreeOnTerminate:=true;
Resume;
end;
end;

и посылаю сообщение:

procedure TForm1.Button2Click(Sender: TObject);
var
h:hWnd;
begin
h := FindWindow(«asdasd», nil);
SendMessage(h, WM_QUIT, 0, 0);
end;

GetMessage ни в какую не желает принимать сообщение, даже если написать GetMessage(Msg,0,0,0), в то же время WndProc сообщение принимает. Я так понимаю, что посланные мной сообщения принимает обработчик главного потока. Так ли это? И нужен ли вообще, в таком случае, GetMessage в отдельном потоке?


> GetMessage ни в какую не желает принимать сообщение

RTFM, RTFM и еще раз RTFM, как завещал великий Ленин, про отличия SendMessage от PostMessage


> GetMessage ни в какую не желает принимать сообщение

Цитата из справки :

If the function retrieves the WM_QUIT message, the return value is zero

Zero — это False

При этом произойдет выход из while-цикла.


> Я так понимаю, что посланные мной сообщения принимает обработчик
> главного потока. Так ли это?

Нет, не так.
Поток, создавший некое окно, ответственен за прием сообщений, адресованных этому окну.


> нужен ли вообще, в таком случае, GetMessage в отдельном
> потоке?

> RTFM, RTFM и еще раз RTFM, как завещал великий Ленин, про отличия SendMessage от PostMessage

SendMessage ждет ответ, PostMessage нет, впр не о том обсалютно.

> Цитата из справки :

само собой, мне это известно и справку я читать умею. А GetMessage все равно не вызывается, ну никак и из цикла не выходит.

>Нет, не так.
>Поток, создавший некое окно, ответственен за прием сообщений, адресованных этому окну.

Вот и я всегда так думал.


> GetMessage все равно не вызывается

Бред сивой кобылы несешь.


> Вот и я всегда так думал

Что тут думать ? Это — реальность .. концепция, придуманная не мной и не тобой.


> SendMessage ждет ответ, PostMessage нет, впр не о том обсалютно.

Не ту справку читаешь, почитай еще. Сообщения по SendMessage никогда не будут выбраны вызовом GetMessage


> Сообщения по SendMessage никогда не будут выбраны вызовом
> GetMessage

Бред сивой кобылы.

Сергей М. © (09.03.06 16:12) [6]

Да ну ? Будут ? И дальше провалятся в TranslateMessage|DispatchMessage ?

А ты код напиши для примера, вместе посмотрим.


> Crash Coredump © (09.03.06 16:23) [7]

Ты облажался.
По полной программе.


Сергей М. © (09.03.06 16:44) [8]

Ругаться я не хуже тебя умею, поверь.

Пример кода, в котором GetMessage выбирает сообщения, посланные по SendMessage будет ?

Речь идет об интерпоточном взаимодействии.

В пределах одногго и того же кодового потока понятие «очередь» не имеет смысла.

Сергей М. © (09.03.06 16:46) [10]


> В пределах одногго и того же кодового потока понятие «очередь»
> не имеет смысла

Ты это разработчикам Windows расскажи, а мы вместе посмеемся над их ответом тебе. Заодно посмотри реализацию TCustomForm.Release, в котором понятие «очередь» в пределах одного потока весьма уместно используется.


> Речь идет об интерпоточном взаимодействии.

А какая разница ? GetMessage как занимался выборкой сообщений из очереди сообщений, так и занимается, хоть в одном потоке, хоть в десяти.


> Crash Coredump © (09.03.06 16:52) [12]

Бегом штудировать MSN !

Сергей М. © (09.03.06 16:55) [13]

А ты скажи, какой именно раздел надо штудировать ?

А то вот я один проштудировал, а там написано:

«The GetMessage function retrieves a message from the calling thread»s message queue and places it in the specified structure. This function can retrieve both messages associated with a specified window and thread messages posted via the PostThreadMessage function.»

и еще один раздел проштудировал:

«he SendMessage function sends the specified message to a window or windows. The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread»s message queue and returns immediately«

Или у тебя есть секретное издание MSDN ?

> GetMessage как занимался выборкой сообщений из очереди сообщений,
> так и занимается

Так точно.
Кодовый поток процесса, используя WinAPI, занимается либо ожиданием/выборкой, либо синхронной отправкой/ожиданием рез-та. Есть иное мнение ?

> msg (09.03.06 16:00) [3]

Сообщения, посылаемые окну потока с помощью SendMessage, называются синхронными, а сообщения, посылаемые функцией PostMessage — асинхронными.

Вызванная функция GetMessage потока-приёмника вначале определяет по особому флагу в структуре потока, посланы ли потоку синхронные сообщения, и, если да, поочерёдно передаёт эти сообщения непосредственно оконным процедурам нужных окон. После этого GetMessage не возвращает управление (что мы и наблюдаем), а проверяет наличие асинхронных сообщений. И до тех пор, пока в очереди не будет обнаружено асинхронное сообщение или в структуре потока не будет обнаружен один из специальных флагов, GetMessage ничего не возвратит.

> И нужен ли вообще, в таком случае, GetMessage в отдельном
> потоке?

Нужен. Без вызова GetMessage WM_QUIT не передалось бы оконной процедуре.

Сергей М. © (09.03.06 17:00) [15]

Так какой раздел мне надо штудировать ?

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

Сергей М. © (09.03.06 17:05) [18]

Ты, Серега, повежливее малость, а то опять чтением займешься.

И заодно почитай первый пост из темы:

«GetMessage ни в какую не желает принимать сообщение, даже если написать GetMessage(Msg,0,0,0), в то же время WndProc сообщение принимает»

«GetMessage ни в какую не желает принимать сообщение, даже если написать GetMessage(Msg,0,0,0), в то же время WndProc сообщение принимает»


> Crash Coredump © (09.03.06 17:01) [17]

Читать ремарки ! До полного просветления !

If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine.


> GetMessage ни в какую не желает принимать сообщение

Бред сивой кобылы.

Эта ф-ция не занимается каким-то там «приемом».

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

> Сергей М. © (09.03.06 17:09) [20]

> If the specified window was created by the calling thread,
> the window procedure is called immediately as a subroutine.

Это к чему? В вопросе потоки разные, вообще-то.

Сергей М. © (09.03.06 17:09) [20]


> If the specified window was created by the calling thread,
> the window procedure is called immediately as a subroutine

Кто бы спорил ? И через GetMessage не проходит, об чем я и говорю.

GetMessage сработает на WM_QUIT только если в очереди потока будет стоять флаг QUIT. А если WM_QUIT послано через SendMessage, то в очередь оно не попадет. Недаром придумали вызов PostQuitMessage


> Ты, Серега, повежливее малость, а то опять чтением займешься

О да) .. тебе ли не знать) .. За дурика не держи.


> в то же время WndProc сообщение принимает.

Сергей М. © (09.03.06 17:23) [24]

Ну и этим все сказано — сообщение, посланное по SendMessage, обрабатывается оконной процедурой, а не появляется в результате вызова GetMessage.


> Crash Coredump © (09.03.06 17:27) [25]


> Ну и этим все сказано — сообщение, посланное по SendMessage,
> обрабатывается оконной процедурой, а не появляется в результате
> вызова GetMessage.

Что значит «появляется в результате вызова»?
а кто оконную процедуру вызывает, если сообщение из другово потока?


> Что значит «появляется в результате вызова»?

Значит, что
а) GetMessage возвращает результат (и заполненную структуру MSG при ненулевом результате)
б) Выполнение переходит на команду, следующую за вызовом GetMessage


> Crash Coredump © (09.03.06 18:22) [27]


> Значит, что
> а) GetMessage возвращает результат (и заполненную структуру
> MSG при ненулевом результате)
> б) Выполнение переходит на команду, следующую за вызовом
> GetMessage

так точно.
А второй вопрос?


> а кто оконную процедуру вызывает, если сообщение из другово
> потока?

Вызывает ее GetMessage, PeekMessage, WaitMessage, при этом не прерывая своего исполнения до тех пор, пока в очереди нет сообщений.

Напиши пример с окном, которое реагирует на два разных сообщения, из другого потока посылай ему сообщения первого типа через SendMessage, а второго через PostMessage, посмотри, как будет происходить выполнение цикла
while GetMessage . do begin
// в этом месте можешь сигнализировать каким-то образом, что GetMessage отработал
TranslateMessage
DispatchMessage
end;



> Crash Coredump © (09.03.06 18:32) [29]


> Вызывает ее GetMessage, PeekMessage, WaitMessage

ну вот! правильно. Об чём спор тогда.
а вот это

> Crash Coredump © (09.03.06 17:27) [25]


> Ну и этим все сказано — сообщение, посланное по SendMessage,
> обрабатывается оконной процедурой, а не появляется в результате
> вызова GetMessage.

не верно, что ты и доказал сам.
без Get/PeekMessage никуда.


> без Get/PeekMessage никуда.


> не верно, что ты и доказал сам

Мы сабж будем читать или как ?


> Crash Coredump © (09.03.06 18:22) [27]

> Значит, что
> а) GetMessage возвращает результат (и заполненную структуру
> MSG при ненулевом результате)
> б) Выполнение переходит на команду, следующую за вызовом
> GetMessage

Никуда оно не перейдет, т.е., выхода из GetMessage при
обработке nonqueued message не будет.

В общем-то, картина не так уж проста, поэтому Рихтер и
писал о том, что у потока целых четыре очереди сообщений,
включая и такие, как очередь синхронных сообщений
и очередь ответных сообщений.

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

to Crash Coredump © (09.03.06 18:42) [31]

> msg (09.03.06 12:11)
> И нужен ли вообще, в таком случае, GetMessage в отдельном
> потоке?

нужен.

> MsgWaitForMultipleObjects

в данном случае применять эту функцию — извращение.

> WaitMessage

не осуществляет выборку.

так что нормальную очередь сообщений можно построить только на Get/PeekMessage . остальное — стёб.. imho.

Leonid Troyanovsky © (09.03.06 18:45) [32]


> Никуда оно не перейдет, т.е., выхода из GetMessage при
> обработке nonqueued message не будет.

Об том и речь. С самого начала.


> Ну, а собщения, которые SendMessage из другого потока
> обрабатываются в оконной процедуре потоком-получателем.
> А для того, чтобы оный смог обработать сообщение, он
> должен находится в состоянии ожидания, достигаемого,
> например, той же GetMessage.

Или другими функциями ожидания, связанными с очередью сообщений потока. Вот честно, не проверял, будут ли обрабатываться сообщения, если поток будет ждать какого-нибудь объекта ядра функцией WaitForSingleObject, а что Рихтер на эту тему писал, не помню.

Eraser © (09.03.06 18:48) [33]

Из какой очереди сообщений ? Их несколько у потока.

Eraser © (09.03.06 18:52) [36]

Очередь сообщений, куда помещаются сообщения, посланные по SendMessage, WaitMessage тоже не обрабатывает, доставляя их оконной процедуре ?


> Crash Coredump © (09.03.06 18:56) [37]

проспись пойди.

Eraser © (09.03.06 18:57) [38]

Это надо понимать, как отсутствие иных аргументов ?

Eraser © (09.03.06 18:57) [38]

Мне не хочешь верить, может, Рихтеру поверишь, который Джеффри:

«When a worker thread sends a message to your window, the SendMessage function internally queues up the message for the window, and then the worker thread suspends itself. The next time the user-interface thread calls GetMessage, PeekMessage, or WaitMessage, it sees the queued sent message, pulls it from the queue, and processes the window»s window procedure. «


> Crash Coredump © (09.03.06 18:51) [34]

> потока. Вот честно, не проверял, будут ли обрабатываться
> сообщения, если поток будет ждать какого-нибудь объекта
> ядра функцией WaitForSingleObject, а что Рихтер на эту тему
> писал, не помню.

Я, конечно, тоже не помню, но работоспособный цикл
можно построить на основе MsgWaitForMultipleObjects + PeekMessage.
Или WaitMessages + PeekMessage.


> Crash Coredump © (09.03.06 19:12) [40]

к чему ты вообще тут WaitMessage приплёл. сабж не про это.

> Leonid Troyanovsky © (09.03.06 19:28) [41]

именно. обычно WaitMessage применяют балансировки нагрузки. И то довольно редко. видел применение только один раз — в WinVNC.

Eraser © (09.03.06 21:02) [42]


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

Это как ? Расскажи, интересно.

Совет — спорь кодом, аргумент неубиенный. И эта. «будьте вежливы».


> Игорь Шевченко © (09.03.06 21:14) [43]


> Совет — спорь кодом, аргумент неубиенный.

vncDesktopThread::run_undetached(void *arg)
<
// Save the thread»s «home» desktop, under NT (no effect under 9x)
HDESK home_desktop = GetThreadDesktop(GetCurrentThreadId());

// Attempt to initialise and return success or failure
if (!m_desktop->Startup())
<
vncService::SelectHDESK(home_desktop);
ReturnVal(FALSE);
return NULL;
>

// Grab the initial display contents
// *** m_desktop->m_buffer.GrabRegion(m_desktop->m_bmrect);
// *** m_desktop->m_buffer.Clear(m_desktop->m_bmrect);

// Succeeded to initialise ok
ReturnVal(TRUE);

// START PROCESSING DESKTOP MESSAGES

// We set a flag inside the desktop handler here, to indicate it»s now safe
// to handle clipboard messages
m_desktop->SetClipboardActive(TRUE);

// All changes in the state of the display are stored in a local
// UpdateTracker object, and are flushed to the vncServer whenever
// client updates are about to be triggered
rfb::SimpleUpdateTracker clipped_updates;
rfb::ClippedUpdateTracker updates(clipped_updates, m_desktop->m_bmrect);
clipped_updates.enable_copyrect(true);

// Incoming update messages are collated into a single region cache
// The region cache areas are checked for changes before an update
// is triggered, and the changed areas are passed to the UpdateTracker
rfb::Region2D rgncache = m_desktop->m_bmrect;

// The previous cursor position is stored, to allow us to erase the
// old instance whenever it moves.
rfb::Point oldcursorpos;

// Set the hook thread to a high priority
// *** set_priority(omni_thread::PRIORITY_HIGH);

//
// CHECK SCREEN FORMAT
// First, we must check that the screen hasnt changed too much.
if (m_desktop->m_displaychanged || !vncService::InputDesktopSelected())
<
rfbServerInitMsg oldscrinfo = m_desktop->m_scrinfo;
m_desktop->m_displaychanged = FALSE;

// Attempt to close the old hooks
if (!m_desktop->Shutdown())
<
m_server->KillAuthClients();
break;
>

// Now attempt to re-install them!
if (!m_desktop->Startup())
<
m_server->KillAuthClients();
break;
>

// Check that the screen info hasn»t changed
vnclog.Print(LL_INTINFO, VNCLOG(«SCR: old screen format %dx%dx%d\n»),
oldscrinfo.framebufferWidth,
oldscrinfo.framebufferHeight,
oldscrinfo.format.bitsPerPixel);
vnclog.Print(LL_INTINFO, VNCLOG(«SCR: new screen format %dx%dx%d\n»),
m_desktop->m_scrinfo.framebufferWidth,
m_desktop->m_scrinfo.framebufferHeight,
m_desktop->m_scrinfo.format.bitsPerPixel);
if ((m_desktop->m_scrinfo.framebufferW > (m_desktop->m_scrinfo.framebufferHeight != oldscrinfo.framebufferHeight))
<
m_server->KillAuthClients();
break;
> else if (memcmp(&m_desktop->m_scrinfo.format, &oldscrinfo.format, sizeof(rfbPixelFormat)) != 0)
<
m_server->UpdateLocalFormat();
>

// Adjust the UpdateTracker clip region
updates.set_clip_region(m_desktop->m_bmrect);

// Add a full screen update to all the clients
rgncache = rgncache.union_(rfb::Region2D(m_desktop->m_bmrect));
m_server->UpdatePalette();
>

if (m_desktop->m_server->UpdateWanted())
<
// POLL PROBLEM AREAS
// We add specific areas of the screen to the region cache,
// causing them to be fetched for processing.
if (m_desktop->m_server->PollFullScreen())
<
rfb::Rect rect = m_desktop->m_qtrscreen;
rect = rect.translate(rfb::Point(0, m_desktop->m_pollingcycle * m_desktop->m_qtrscreen.br.y));
rgncache = rgncache.union_(rfb::Region2D(rect));
m_desktop->m_pollingcycle = (m_desktop->m_pollingcycle + 1) % 4;
>
if (m_desktop->m_server->PollForeground())
<
// Get the window rectangle for the currently selected window
HWND hwnd = GetForegroundWindow();
if (hwnd != NULL)
PollWindow(rgncache, hwnd);
>
if (m_desktop->m_server->PollUnderCursor())
<
// Find the mouse position
POINT mousepos;
if (GetCursorPos(&mousepos))
<
// Find the window under the mouse
HWND hwnd = WindowFromPoint(mousepos);
if (hwnd != NULL)
PollWindow(rgncache, hwnd);
>
>

// PROCESS THE MOUSE POINTER
// Some of the hard work is done in clients, some here
// This code fetches the desktop under the old pointer position
// but the client is responsible for actually encoding and sending
// it when required.
// This code also renders the pointer and saves the rendered position
// Clients include this when rendering updates.
// The code is complicated in this way because we wish to avoid
// rendering parts of the screen the mouse moved through between
// client updates, since in practice they will probably not have changed.

// Re-render the mouse»s old location if it»s moved
BOOL cursormoved = FALSE;
POINT cursorpos;
if (GetCursorPos(&cursorpos) &&
((cursorpos.x != oldcursorpos.x) ||
(cursorpos.y != oldcursorpos.y))) <
cursormoved = TRUE;
oldcursorpos = rfb::Point(cursorpos);
>
if (cursormoved) <
if (!m_desktop->m_cursorpos.is_empty())
rgncache = rgncache.union_(rfb::Region2D(m_desktop->m_cursorpos));
>

<
// Prevent any clients from accessing the Buffer
omni_mutex_lock l(m_desktop->m_update_lock);

// CHECK FOR COPYRECTS
// This actually just checks where the Foreground window is
m_desktop->CalcCopyRects(updates);

// GRAB THE DISPLAY
// Fetch data from the display to our display cache.
m_desktop->m_buffer.GrabRegion(rgncache);
// Render the mouse
m_desktop->m_buffer.GrabMouse();
if (cursormoved) <
// Inform clients that it has moved
m_desktop->m_server->UpdateMouse();
// Get the buffer to fetch the pointer bitmap
if (!m_desktop->m_cursorpos.is_empty())
rgncache = rgncache.union_(rfb::Region2D(m_desktop->m_cursorpos));
>

// SCAN THE CHANGED REGION FOR ACTUAL CHANGES
// The hooks return hints as to areas that may have changed.
// We check the suggested areas, and just send the ones that
// have actually changed.
// Note that we deliberately don»t check the copyrect destination
// here, to reduce the overhead & the likelihood of corrupting the
// backbuffer contents.
rfb::Region2D checkrgn = rgncache.subtract(clipped_updates.get_copied_region());
rgncache = clipped_updates.get_copied_region();
rfb::Region2D changedrgn;
m_desktop->m_buffer.CheckRegion(changedrgn, checkrgn);

// FLUSH UPDATES TO CLIENTS
// Add the bits that have really changed to their update regions
// Note that the cursor is NOT included — they must do that
// themselves, for the reasons above.
// This call implicitly kicks clients to update themselves

// Clear the update tracker and region cache
clipped_updates.clear();
>

// Now wait for more messages to be queued
if (!WaitMessage()) <
vnclog.Print(LL_INTERR, VNCLOG(«WaitMessage() failed\n»));
break;

весь код VNC приводить не буду . много там )

> И эта. «будьте вежливы».

я и так вежлив, особенно когда со мной спорят не ради спора, а по сабжу )


Eraser © (09.03.06 21:29) [44]
Eraser © (09.03.06 21:29) [45]


> весь код VNC приводить не буду

Надо приводить код Windows.

А этот код ты зачем привел ?

А по сабжу все сказано в посте [1]

С потоком в данной ситуации надо обмениваться через Post[Thread]Message


> Игорь Шевченко © (09.03.06 21:55) [46]

в [1] автор прав насчёт RTFM — согласен — это никогда не лишнее )
PostThreadMessage однако он не упаминул.. ну да Бог с ним с PostThreadMessage.
Далее ведь тов. Crash Coredump начал доказывать, что Get/PeekMessage не нужна в доп. потоке.

Crash Coredump © (09.03.06 16:08) [5]
Не ту справку читаешь, почитай еще. Сообщения по SendMessage никогда не будут выбраны вызовом GetMessage

на что Сергей М. вполне резонно заметил
Бред сивой кобылы.

вот по этой теме хорошая ветка
http://www.rsdn.ru/Forum/Message.aspx?m >

Eraser © (09.03.06 22:03) [47]


> Сообщения по SendMessage никогда не будут выбраны вызовом
> GetMessage

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

А про то, как обрабатываются сообщения на самом деле, и автор поста [1] и я знаем довольно неплохо :)

Впрочем, окончательную точку ставит MSDN (VS 2005 beta 2)

«The GetMessage function retrieves a message from the calling thread»s message queue. The function dispatches incoming sent messages until a posted message is available for retrieval.

During this call, the system delivers pending messages that were sent to windows owned by the calling thread using the SendMessage, SendMessageCallback, SendMessageTimeout, or SendNotifyMessage function. The system may also process internal events. Messages are processed in the following order:

Sent messages
Posted messages
Input (hardware) messages and system internal events
Sent messages (again)
WM_PAINT messages
WM_TIMER messages «

в отличие от Win32.Hlp

«he GetMessage function retrieves a message from the calling thread»s message queue and places it in the specified structure. This function can retrieve both messages associated with a specified window and thread messages posted via the PostThreadMessage function. The function retrieves messages that lie within a specified range of message values. GetMessage does not retrieve messages for windows that belong to other threads or applications»


> Игорь Шевченко © (09.03.06 22:18) [48]


> GetMessage does not retrieve messages for windows that belong
> to other threads or applications»

странно.. не обращал внимание на этот ляп )
пользуюсь тоже MSDN.

> А про то, как обрабатываются сообщения на самом деле, и
> автор поста [1] и я знаем довольно неплохо :)

ну что ж. раз вы говорите, что тот товарисч вкурсе — приму на веру.
однако с формулировками по осторожнее быть надо.. а то тов. Crash Coredump раза 3 упамянул, что
> Сообщения по SendMessage никогда не будут выбраны вызовом
> GetMessage

.

Eraser © (09.03.06 22:31) [49]

Они будут, согласно MSDN, отдиспетчированы — непосредственно переданы оконной процедуре нужного окна. Но при этом GetMessage не закончит своего выполнения как того ожидает автор. Поэтому ему в данном случае лучше выполнять PostMessage, а для конкретного примера в [0] и вовсе PostQuitMessage.

Я советую кроме MSDN еще исходниками пользоваться. Например, ReactOS. Поскольку они ставят своей целью совместимость с Windows, то их исходники можно рассматривать, как отправную точку для углубленных знаний.

Из их исходников видно, что GetMessage (NtUserGetMessage), если в очереди потока нет сообщений, вызывает внутреннюю функцию WaitMessage, которая и осуществляет диспетчеризацию Sent-сообщений — это к спору о WaitMessage :)


> Игорь Шевченко © (09.03.06 22:42) [50]


> Из их исходников видно, что GetMessage (NtUserGetMessage),
> если в очереди потока нет сообщений, вызывает внутреннюю
> функцию WaitMessage, которая и осуществляет диспетчеризацию
> Sent-сообщений — это к спору о WaitMessage :)

ну я подозоевал, что-то вроде

while(true)
<
WaitMessage();
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)
<
if(msg.message==WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);
>

а исходники ReactOS доступны всем для скачивания?
ссылочку можно? )

Eraser © (09.03.06 22:50) [51]

Сначала проверка очереди, если пусто, то проверка, доставка и очистка Sent-сообщений, затем WaitMessage


> а исходники ReactOS доступны всем для скачивания?
> ссылочку можно? )


> Игорь Шевченко © (09.03.06 23:05) [52]

выделю трафик.. скачаю.
интересно однако:)

Eraser © (09.03.06 23:27) [53]

На самом деле интересно, так как дает представление о том, как реализуется поведение тех или иных функций Windows. Кроме того, если по механизмам ядра написана отличная книжка Руссиновича и Соломона, то по части оконной подсистемы довольно большое белое пятно. Даже по механизмам GDI написана книжка Фэня Юаня, а по USER и его ядерной части в Win32k.sys я ничего не видел.


> Eraser © (09.03.06 22:50) [51]

Скорее уж while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)

Ага, GetMessage действительно нужен, потому, что если

while GetMessage(Msg,wnd,0,0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;

while true do
sleep(1);

в оконную процедуру сообщение не передается, понял.

ранее SendMessage пытался заменить на PostMessage, но GetMessage управление всеравно не возвращала, щас возвращает. фиг с ним, спишем на собственную невнимательность.

С поведением GetMessage при PostMessage и SendMessage более менее разобрался.

Заметил еще одну интересную особенность, оконная процедура, при SendMessage(WM_QUIT) получает сообщение с кодом 18(WM_QUIT), а при PostMessage(WM_QUIT) оконная процедура получает два сообщения 2(WM_DESTROY) и 130(WM_NCDESTROY).

Теперь есть непонятки с PostQuitMessage, если ее вызываю в оконной процедуре в ответ на WM_DESTROY(PostMessage) или WM_QUIT(SendMessage), GetMessage возвращает управление, мы выходим из цикла.
Если же написать:

type
TTest=class(TThread)
.
public
Procedure ExitTest;
.

procedure TTest.ExitTest;
begin
PostQuitMessage(0);
end;

и из основного потока вызвать ExitTest:

то мы вываливаемся из программы (т.е. завершает работу основной поток), почему? в справке написано:
Функция PostQuitMessage указывает Windows, что ПОТОК (в нашем случае не основной) послал запрос на завершение (выход).


> ПОТОК (в нашем случае не основной)

Ну как же не основной-то ?

Сам же говоришь , что


> и из основного потока вызвать ExitTest


> и из основного потока вызвать ExitTest:
>
> T.ExitTest;

То процедура будет выполнена в контексте основного потока, что неудивительно.

msg (10.03.06 12:45) [56]

А что ты вообще хочешь сделать, если не секрет, в связи с чем вопрос ?
Может есть готовое решение.

Сергей М., Crash Coredump
а, да, точно, понял. этот вопрос снят.

Crash Coredump
Если вы спрашиваете о T.ExitTest;, то это просто эксперимент.

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

const
WM_ASDASD_COMMAND = WM_USER + 3;
_ASDASD_TEST = 1;

h := FindWindow(«asdasd», nil);
SendMessage(h, WM_ASDASD_COMMAND, _ASDASD_TEST, 0);

Насколько принципиален при решении этой задачи отказ от борландовских классов в пользу «чистого WinAPI» ?


Ведь так или иначе классы ты задействуешь, коль скоро задействовал TThread ..

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

Для взаимодействия с консольным приложением можно взять, например,
pipes, memory mapped files, APC & etc.

Ну, а если уж так хочется GUI-thread можно, например,

http://www.rsdn.ru/Forum/?m >
только, пользы от конгуевых гибридов значительно меньше.

msg (10.03.06 14:58) [59]


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

Не обязательно консольное:

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TfWorker = class(TForm)
procedure FormCreate(Sender: TObject);
public
procedure DefaultHandler(var Message); override;
end;

var
fWorker: TfWorker;

procedure TfWorker.DefaultHandler(var Message);
begin
with TMessage(Message) do
if Msg = UM_WORKER1 then
MessageBeep (0)
else if Msg = UM_WORKER2 then
MessageBox(0, «message 2», «Worker», MB_OK)
else
inherited;
end;

procedure TfWorker.FormCreate(Sender: TObject);
begin
Application.ShowMainForm := false;
ShowWindow (Application.Handle, SW_HIDE);
end;

const
UM_WORKER1 = WM_USER + 100;
UM_WORKER2 = WM_USER + 101;

Это один EXEшник.

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ActnList;

type
TfWorkerControl = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
ActionList: TActionList;
actMessage1: TAction;
actMessage2: TAction;
actTerminate: TAction;
procedure FormCreate(Sender: TObject);
procedure ActionListUpdate(Action: TBasicAction; var Handled: Boolean);
procedure actMessage1Execute(Sender: TObject);
procedure actMessage2Execute(Sender: TObject);
procedure actTerminateExecute(Sender: TObject);
private
FWorkerWnd: HWND;
end;

var
fWorkerControl: TfWorkerControl;

procedure TfWorkerControl.FormCreate(Sender: TObject);
begin
FWorkerWnd := FindWindow («TfWorker», «fWorker»);
end;

procedure TfWorkerControl.ActionListUpdate(Action: TBasicAction;
var Handled: Boolean);
begin
actMessage1.Enabled := IsWindow(FWorkerWnd);
actMessage2.Enabled := IsWindow(FWorkerWnd);
actTerminate.Enabled := IsWindow(FWorkerWnd);
end;

procedure TfWorkerControl.actMessage1Execute(Sender: TObject);
begin
SendMessage(FWorkerWnd, UM_WORKER1, 0, 0);
end;

procedure TfWorkerControl.actMessage2Execute(Sender: TObject);
begin
SendMessage(FWorkerWnd, UM_WORKER2, 0, 0);
end;

procedure TfWorkerControl.actTerminateExecute(Sender: TObject);
begin
PostMessage(FWorkerWnd, WM_CLOSE, 0, 0);
end;

Это второй EXEшник — та самая стороняя программа

Сергей М.
несомненно, VCL-ные библиотеки используются, но дело все в том, что само приложение мало по килобайтам, поэтому просто не хотелось бы его «утяжелять» использованием к примеру таких модулей как: Controls, Forms, Menus, Dialogs .

Leonid Troyanovsky
В данном случае команды оч. простые и даже если будет какое-то расширение команд, ничего сложного не будет, максимум передача строки(пути), но эта проблема решается в моем случае с помощью CopyDataStruct, так же ни когда не потребуется удаленное управление. В связи с этим есть желание cделать все настолько просто, насколько это возможно (легче отлаживать, писать приложение(я) отдающее(ие) команды, модифицировать. ).

а к примеру с тем же MMF надо решать проблему отслеживания изменившейся/пополнившейся информации, проблему синхронизации приложений, структуры размещаемой информации и пр.

AllocateHWND, ага, что может быть проще, вот только бы еще класс окна можно было бы определять самому.

Crash Coredump
Это понятно. Так бы и сделал если бы было бы гуишное приложение, но у консоли то ведь нет своей очереди оконных сообщений.

> В данном случае команды оч. простые и даже если будет какое-
> то расширение команд, ничего сложного не будет, максимум
> передача строки(пути), но эта проблема решается в моем случае
> с помощью CopyDataStruct, так же ни когда не потребуется
> удаленное управление. В связи с этим есть желание cделать
> все настолько просто, насколько это возможно (легче отлаживать,
> писать приложение(я) отдающее(ие) команды, модифицировать.
> ..).

С помощью mmf оно решается не сложней.
Дополнительно потребуется лишь (тоже именованные) mutex и, возможно,
event (CreateEvent).
Читатель ждет (периодически проверяет) состояние event, и при
сигнале читает проекцию файла. Писатель пишет и устанавливает
событие по окончанию. Всякое чтение-запись в проекцию начинается
с захвата мьютекса и завершается его release. Вот, собс-но, и все.
Отладить оное взамодействие можно в обычном гуевом приложении
с кодом консоли, вынесенным в поток.

Т.е., для консольного приложения — это самое то, ничего лишнего
и громоздкого (включая TThread ;).

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

Особенной нужды в этом нет. Для того, чтобы его можно было проще
найти среди дельфирожденных окон ему можно сделать SetWindowText
or SetProp с уникальным идентификатором.

Хотя, конечно, возможно, что лучше его сделать Message-Only Window
(see SetParent with HWND_MESSAGE)


> Так бы и сделал если бы было бы гуишное приложение, но у
> консоли то ведь нет своей очереди оконных сообщений.

А что, консоль является необходимым внешним условием ?

>Читатель ждет (периодически проверяет) состояние event, и при
>сигнале читает проекцию файла. Писатель пишет и устанавливает
>событие по окончанию. Всякое чтение-запись в проекцию начинается
>с захвата мьютекса и завершается его release. Вот, собс-но, и все.
>Отладить оное взамодействие можно в обычном гуевом приложении
>с кодом консоли, вынесенным в поток.

Здесь плохо, что «Читатель ждет (периодически проверяет)», потому как происходит дополнительная нагрузка на процессор (ни кто не спорт, она не значительна) и в зависимости от частоты проверки, получение сообщения у нас может занять какое-то время. Так же увеличение частоты проверки, ради сокращения времени получения сообщения, все больше увеличивает нагрузку на процессор.

Если же использовать WaitForSingleObject, то нужен дополнительный поток. Хотя в принципе, ожидание сообщений консольного буфера у меня построено на WaitForSingleObjectEx, можно попробовать объединить ожидание event и буфера функцией WaitForMultipleObjects, как считаете? Оба события же должны ожидаться бесконечно (INFINITE).

>Хотя, конечно, возможно, что лучше его сделать Message-Only Window
>(see SetParent with HWND_MESSAGE)

Кстати, действительно замечательный флаг. Благодарю.

>А что, консоль является необходимым внешним условием ?

Основное приложение: да. Приложение отдающее команды: нет, хотя оно и не важно от куда SendMessage слать.

msg (10.03.06 21:23) [69]

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

> Игорь Шевченко © (10.03.06 21:29) [70]

Я, возможно, глупость сморожу, но у консоли разве затруднительно организовать цикл с GetMessage подобно тому, как это делается в GUI? Я, собсно, к тому, что не совсем понятно, зачем ещё окно создавать :)

begin. end © (10.03.06 21:54) [71]

А насколько я знаю, этот цикл уже организовывает тот, кто поддерживает ConsoleWindowClass для окна консоли, то есть, winsrv.dll

Я вот не знаю (если ты попробуешь, напиши, интересно), как интерференция с ним себя покажет, поэтому и спросил автора о необходимости именно консольного приложения.

У консольного приложения же как такового нет своего окна, консольное окно создаеться вызовом AllocConsole и заним следит система, к консольному окну может «приотачится» сколь угодо процессов (AttachConsole), и уничтожается оно после того, как все процессы от него отключатся вызвав FreeConsole.

Ну покрайней мере вот такой код не дает ни каких результатов:
в таймере (timeSetEvent):
h := FindWindow(«ConsoleWindowClass», nil);
PostMessage(h, WM_PAINT, 0, 0);
или
SetConsoleTitle(«<9f0c9451-118f-4a3e-9170-6c1989797463>«);
h := FindWindow(nil, «<9f0c9451-118f-4a3e-9170-6c1989797463>«);
PostMessage(h, WM_PAINT, 0, 0);

в цикле:
if PeekMessage(Mess,0,0,0,PM_REMOVE) then
begin
case Mess.message of
WM_PAINT: beep;
end;
end;

> Игорь Шевченко © (10.03.06 22:11) [72]

Сообщения, посылаемые окну консоли через PostMessage, собственноручно организованным GetMessage-циклом не выбираются. Но у меня в [71] была мысль посылать не окнам (стандартному консольному или самостоятельно созданному), а потоку (через PostThreadMessage). Эти сообщения, на первый взгляд, нормально доходят.

> Сообщения, посылаемые окну консоли.

Разумеется, имеется в виду стандартное консольное окно. Если создать дополнительное своё, то сообщения, адресованные ему, вроде бы, нормально принимаются в цикле (тоже на первый взгляд).

> Если же использовать WaitForSingleObject, то нужен дополнительный
> поток. Хотя в принципе, ожидание сообщений консольного буфера
> у меня построено на WaitForSingleObjectEx, можно попробовать
> объединить ожидание event и буфера функцией WaitForMultipleObjects,
> как считаете? Оба события же должны ожидаться бесконечно

Конечно, WaitForMultipleObjects.
Если же используется WaitForSingleObjectEx, то можно извещать
ожидающий поток не с помощью event (SetEvent), а QueueUserAPC.

Илон Маск рекомендует:  Oracle приложение 1
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL