Re[18]: SendMessage vs PostMessage
От: Alexey Shirshov Россия http://wise-orm.com
Дата: 13.03.03 08:53
Оценка:
Здравствуйте, algod, Вы писали:

[]

A>А ты проверь, как я .


Неа.

A>Я тоже сначала не поверил. Простейший эксперимент:

A>В одном процессе открой окно, напиши в свичере оконной процы
A>
A>case WM_USER + 0x100: MessageBepp (0); break;
A>

A>а потом зациклись в пустоте
A>
A>for ( ; ; ); 
A>


A>Во втором процессе найди это окно (по капшану, хотя бы) — и пульни в него WM_USER + 0x100...

A>Оно никогда не дойдет . И окно твое "висеть" будет. В прямом смысле слова.

Конечно, а что ты хотел?

A>А вот если ты напишешь хотя бы так:

A>
A>while (Get(Peek)Message (...)); 
A>


A>То твоя мессага приходить будет... И даже бекграунд окна будет перерисовываться (короче все, что присылали из других процессов по SendMessage)


Она не придет! Ты запусти окно и попробуй его закрыть — сообщение WM_CLOSE будет послано, но оно не дойдет до оконной процедуры. Почему перерисовывается фон? Потому что сообщения типа WM_ERASEBKGND, WM_NCPAINT и проч. не ставяться в очередь. Они через GetMessage никогда не проходят. Зачем? Подсистема GDI, прекрасно зная адрес оконной процедуры может напрямую ее вызывать. Зачем ей тратить время на помещение сообщения в очередь? Можно спокойно заменить
while (Get(Peek)Message (...));

на
Sleep(INFINITE);

Все эти сообщения прекрасно дойдут, так что дело не в GetMessage.

A>GetMessage — выгребает с возвращением только PostMessage. Kirill и Павел правы.


Тут я вообще не понял. У GetMessage чель одна — заполнить структуру MSG и удалить сообщение из очереди. Все!
Re[19]: SendMessage vs PostMessage
От: algod Украина  
Дата: 13.03.03 09:37
Оценка:
Здравствуйте, Alexey Shirshov, Вы писали:

A>>Во втором процессе найди это окно (по капшану, хотя бы) — и пульни в него WM_USER + 0x100...

A>>Оно никогда не дойдет . И окно твое "висеть" будет. В прямом смысле слова.
AS>Конечно, а что ты хотел?
Именно этого и хотел. И сообщение (WM_USER + 0x100) посланное из другого процесса никогда не дойдет. И другой процесс, который его послал тоже подвсиснет.
A>>А вот если ты напишешь хотя бы так:
A>>
A>>while (Get(Peek)Message (...)); 
A>>


AS>Она не придет! Ты запусти окно и попробуй его закрыть — сообщение WM_CLOSE будет послано, но оно не дойдет до оконной процедуры. Почему перерисовывается фон? Потому что сообщения типа WM_ERASEBKGND, WM_NCPAINT и проч. не ставяться в очередь. Они через GetMessage никогда не проходят.

Круто. MSDN читал? WM_ERASEBKGND — не прямое сообщение... Оно вызваеться по BeginPaint... Которое в свою очередь вызываеть через POSTMESSAGE!!! WM_CLOSE — кстати тоже где то через WM_NCLBUTTONDOWN...
А насчет того — что не работает... "Не верь глаза своим"

AS>Зачем? Подсистема GDI, прекрасно зная адрес оконной процедуры может напрямую ее вызывать. Зачем ей тратить время на помещение сообщения в очередь? Можно спокойно заменить

Полностью не верно!!! Иначе бы ты спокойно по сотне раз оказывался внутри одного и того же кода! У тебя никогда проги не висли? Вспомни как круто GDI перерисовывает бекграунды у подвисших прог...

AS>Тут я вообще не понял. У GetMessage чель одна — заполнить структуру MSG и удалить сообщение из очереди. Все!


Ну все так все... Каждый имеет право заблуждаться по своему .
There is no bug
Re[20]: SendMessage vs PostMessage
От: Alexey Shirshov Россия http://wise-orm.com
Дата: 13.03.03 09:52
Оценка:
Здравствуйте, algod, Вы писали:

A>Здравствуйте, Alexey Shirshov, Вы писали:


[]

A> Круто. MSDN читал? WM_ERASEBKGND — не прямое сообщение... Оно вызваеться по BeginPaint... Которое в свою очередь вызываеть через POSTMESSAGE!!! WM_CLOSE — кстати тоже где то через WM_NCLBUTTONDOWN...

A>А насчет того — что не работает... "Не верь глаза своим"

Ты несеш такую чушь, которую опровергать-то трудно!
1. BeginPaint дествительно "посылает" WM_ERASEBKGND, но только если установлен fErase.
2. PostMessage при этом не причем — оконная процедура вызывается напрямую.

Поставь breakpoint на PostMessage — она не будет вызвана системой ни разу! Поставь breakpoint на WM_ERASEBKGND и WM_PAINT и увидишь, что WM_ERASEBKGND срабатывает раньше!
Поставь вместо message pump'a Sleep() и увидешь, что GetMessage здесь вообще не причем!

хъ

A> Полностью не верно!!! Иначе бы ты спокойно по сотне раз оказывался внутри одного и того же кода! У тебя никогда проги не висли? Вспомни как круто GDI перерисовывает бекграунды у подвисших прог...


Это почему? Ты про что?

хъ

A>Ну все так все... Каждый имеет право заблуждаться по своему .


Заблуждайся на здоровье. Я имею обыкновение разбираться с проблемными областями, а не лепетать бесвязные реплики про то, что все не верно и как GDI перерисовывает мои окна.
Re[19]: SendMessage vs PostMessage
От: Kirill_Luzanov  
Дата: 13.03.03 13:22
Оценка:
Здравствуйте, Alexey Shirshov, Вы писали:

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


A>>GetMessage — выгребает с возвращением только PostMessage. Kirill и Павел правы.


AS>Тут я вообще не понял. У GetMessage чель одна — заполнить структуру MSG и удалить сообщение из очереди. Все!


Не ну народ — это не серьезно!
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/messagesandmessagequeuesreference/messagesandmessagequeuesfunctions/getmessage.asp.
Там написано:
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.

Помоему написано не двусмыслено! Get(Peek)Message автоматически диспатчит
синхронные сообщения. Не заполняет она структуру MSG для синхронных сообщений!
Еще книжка хорошая есть — Рихтер "Windows для професионалов"
— там про это очень подробно рассказывается.

А если все равно не веришь — попробуй из GetMessage получить хотя бы одно
синхронное сообщение, успехов...
Think different
Re[20]: SendMessage vs PostMessage
От: Alexey Shirshov Россия http://wise-orm.com
Дата: 13.03.03 14:34
Оценка:
Здравствуйте, Kirill_Luzanov, Вы писали:

[]

KL>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/messagesandmessagequeuesreference/messagesandmessagequeuesfunctions/getmessage.asp.

KL>Там написано:
KL>The GetMessage function retrieves a message from the calling thread's message queue.
KL>The function dispatches incoming sent messages until a
KL>posted message is available for retrieval.

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

KL>Помоему написано не двусмыслено! Get(Peek)Message автоматически диспатчит

KL>синхронные сообщения. Не заполняет она структуру MSG для синхронных сообщений!

Может быть не заполняет. Но тогда как сообщение доставляется в оконную процедуру? Поставь breakpoint на DispatchMessage и он ни разу не сработает. Получается, что Get(Peek)Message просто знают адрес процедуры! Но откуда??
Как такой вот message pump узнаёт адрес оконной процедуры?
while (GetMessage(&msg, NULL, 0, 0));


KL>А если все равно не веришь — попробуй из GetMessage получить хотя бы одно

KL>синхронное сообщение, успехов...

Вот если ты такой умный, объясни каким образом GetMessage доставляет оконной процедуре сообщения (синхронные).
Re[21]: SendMessage vs PostMessage
От: Kirill_Luzanov  
Дата: 13.03.03 15:17
Оценка:
Здравствуйте, Alexey Shirshov, Вы писали:

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


AS>[]


KL>>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/messagesandmessagequeuesreference/messagesandmessagequeuesfunctions/getmessage.asp.

KL>>Там написано:
KL>>The GetMessage function retrieves a message from the calling thread's message queue.
KL>>The function dispatches incoming sent messages until a
KL>>posted message is available for retrieval.

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


KL>>Помоему написано не двусмыслено! Get(Peek)Message автоматически диспатчит

KL>>синхронные сообщения. Не заполняет она структуру MSG для синхронных сообщений!

AS>Может быть не заполняет. Но тогда как сообщение доставляется в оконную процедуру? Поставь breakpoint на DispatchMessage и он ни разу не сработает. Получается, что Get(Peek)Message просто знают адрес процедуры! Но откуда??

Да, КОНЕЧНО ЗНАЮТ. см. далее
AS>Как такой вот message pump узнаёт адрес оконной процедуры?
AS>
AS>while (GetMessage(&msg, NULL, 0, 0));
AS>


KL>>А если все равно не веришь — попробуй из GetMessage получить хотя бы одно

KL>>синхронное сообщение, успехов...

AS>Вот если ты такой умный, объясни каким образом GetMessage доставляет оконной процедуре сообщения (синхронные).


Спасибо за комплимент.
Ты заблудился в трех соснах.
Встречный вопрос — а как ты думаешь как DispatchMessage передает сообщение оконной процедуре — ОТКУДА
эта ф-ция знает как ты говоришь адрес оконной процедуры? Не задумывался? Ведь все что она получает на входе —
это структура MSG. А получаешь ты эту структуру из ф-ции Get(Peek)Message. Или ты думаешь что если ты сделаешь
вызов GetMessage(&msg, NULL, 0, 0) — то получишь в результате (msg.hwnd == NULL)? Типа ты подскзываешь
винде как правильно заполнить структру MSG и если не задашь handle окна — то реакция винды будет ?
Когда ты вызываешь SendMessage — ты указываешь handle окна которому направляется сообщение.
Внутри эта ф-ция заполняте структру MSG. Операционная система ЗНАЕТ к какому окну относится какая оконная процедура
(для этого ты РЕГИСТРИРУЕШЬ класс окна, в информации о классе ты УКАЗЫВАЕШЬ АДРЕС ОКОННОЙ ПРОЦЕДУРЫ,
а потом при создании окна ЯВНО указываешь к какому классу оно(окно) принадлежит).
А по твоей логике получается что в виндах есть ф-ции так сказать приближенные к трону —
которые знают внутреннюю информацию — и есть типа ф-ции "простолюдины" —
которые далеки от придворных дел.

Ф-ций Get(Peek)Message ЗНАЮТ адреса нужных оконных процедур
(точнее это знает OC частью API которой эти ф-ции являтся ).
Think different
Re[21]: SendMessage vs PostMessage
От: algod Украина  
Дата: 13.03.03 15:32
Оценка: 3 (1)
Здравствуйте, Alexey Shirshov:

В дополние сказанному Kirill_Luzanov.
Если бы ты читал то, что было написанно раньше то заметил бы следуюющий код:

GetWindowLong(hwnd, GWL_WINDOWPROC);

Используя который можно получить текущюю оконную процу.

Кроме всего есть:
BOOL GetClassInfo( 
HINSTANCE hInstance, 
LPCTSTR lpClassName, 
LPWNDCLASS lpWndClass); 

int GetClassName(
  HWND hWnd,           
  LPTSTR lpClassName,  
  int nMaxCount        
);


с помощью которых можно получить предефайнутую (в классе) оконную процу.
There is no bug
Re[22]: SendMessage vs PostMessage
От: Alexey Shirshov Россия http://wise-orm.com
Дата: 14.03.03 06:45
Оценка:
Здравствуйте, Kirill_Luzanov, Вы писали:

[]

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

Меня смутило то, что TaskManager не может закрыть окно, имеющее "пустой" цикл

while (GetMessage(&msg, NULL, 0, 0));


Наверняка он посылает WM_CLOSE асинхронно. Я не перестаю удивляться ребятам из мелкософта: ну что им мешало использовать SendMessageTimeout?

После непродолжительной отладки выяснил, что GetMessage вызывает оконную процедуру с помощью некой функции, адрес которой (Prof SP3) 0x77E174C8. Она находится непосредственно перед IsWindowEnabled. Эта функция вызывает еще одну, та еще одну и наконец мы попадаем в оконную процедуру.

Покапался я в книжках и нашел (у Pietrek'а), что адрес оконной процедуры лежит по смещению 0x28 в структуре WND. Насколько я понимаю, из HWND можно лекго получить указатель на эту структуру, так что обращатся к GetWindowLong не нужно.

В общем, тема требует дальнейшего изучения...

Однако на счет того, что GetMessage не вызывает оконную процедуру я погорячился. Признаю свою ошибку.
Re[23]: SendMessage vs PostMessage
От: Alexey Shirshov Россия http://wise-orm.com
Дата: 14.03.03 06:51
Оценка:
Здравствуйте, Alexey Shirshov, Вы писали:

[]

Кстати, нашел в google.
DWORD* GetWndPointer(HWND hwnd) // hwnd is the handle of any window in the system
{
    DWORD user32_si; //user32 shared info; gSharedInfo
    DWORD pWND;
    DWORD local_correction;
    
    // 0x58180 is the offset of gSharedInfo in "user32.dll"
    user32_si=(DWORD)GetModuleHandle("user32.dll")+0x58180;

    pWND=*(DWORD*)(user32_si+4);
    pWND+=LOWORD(hwnd)*12;
    pWND=*(DWORD*)pWND; // now pWND points to the real WND structure above 2 GB
    // and this is a writable memory if we were running in system mode (ring 0)
    // but in user mode (ring 3) we could't even read it
    // this is something like 0xA03xxxxx this is where I want to
    // write 
    /*
    local_correction=*((DWORD *)0x7ffde6e8);
    // [7ffde6e8] - the value that must be subtracted from the pointer above 2 GB
    // in order to get user-mode accessible pointer to the window structure 
    pWND-=local_correction;
    // the new pointer points to read only memory but it is mapped to the same physical address as the
    // pointer above 2 GB, that is before the correction is made
    */
    return (DWORD*)pWND;
}


Не проверял, но выглядит правдоподобно.
Re[23]: SendMessage vs PostMessage
От: Блудов Павел Россия  
Дата: 14.03.03 09:05
Оценка: 14 (1)
Здравствуйте, Alexey Shirshov, Вы писали:

AS>После непродолжительной отладки выяснил, что GetMessage вызывает оконную процедуру с помощью некой функции, адрес которой (Prof SP3) 0x77E174C8


А если скачать pdb-шник для USER32? Там имя этой функции наверняка есть.

AS>Однако на счет того, что GetMessage не вызывает оконную процедуру я погорячился. Признаю свою ошибку.


Вот и молодец. Кстати, вот полный список тех, кто это делает:

DialogBox
DialogBoxIndirect
DialogBoxIndirectParam
DialogBoxParam
GetMessage
MessageBox
PeekMessage
SendMessage

Обратите внимание, что ::MsgWaitForMultipleObjects() в этом списке нет,
она не обрабатывает синхронные сообщения, но она вернет WAIT_OBJECT_0 + nCount
исли будет получено синхронные сообщение из другой нити. Так что если в ответ на
WAIT_OBJECT_0 + nCount тупо вызывать ::GetMessage(), то ::GetMessage()
обработает синхронный вызов. И будет ждать, пока кто-то еще не
отправит-таки сообщение через ::PostMessage(). Возможно, что вечно.

Именно так и происходит в годе, создаваемом мастером WTL для MultiThreadSDI.
Что я и пытался сказать в прошлом письме.

Павел.
Re[24]: SendMessage vs PostMessage
От: Alexey Shirshov Россия http://wise-orm.com
Дата: 14.03.03 09:11
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

[]

БП>А если скачать pdb-шник для USER32? Там имя этой функции наверняка есть.


Нету.

БП>Вот и молодец. Кстати, вот полный список тех, кто это делает:


БП>DialogBox

БП>DialogBoxIndirect
БП>DialogBoxIndirectParam
БП>DialogBoxParam
БП>GetMessage
БП>MessageBox
БП>PeekMessage
БП>SendMessage

Буду знать. Спасибо.

хъ

Так гдеж ты был, когда я просил посмотреть статью про WTL? Я эту фичу не смог объяснить. А Влад уже все сверстал.

БП>Именно так и происходит в годе, создаваемом мастером WTL для MultiThreadSDI.

БП>Что я и пытался сказать в прошлом письме.

Понял. Спасибо.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.