Неа.
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 и удалить сообщение из очереди. Все!
Здравствуйте, 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 и удалить сообщение из очереди. Все!
Ну все так все... Каждый имеет право заблуждаться по своему .
Здравствуйте, 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 перерисовывает мои окна.
Здравствуйте, Alexey Shirshov, Вы писали:
AS>Здравствуйте, algod, Вы писали:
A>>GetMessage — выгребает с возвращением только PostMessage. Kirill и Павел правы.
AS>Тут я вообще не понял. У GetMessage чель одна — заполнить структуру MSG и удалить сообщение из очереди. Все!
Помоему написано не двусмыслено! Get(Peek)Message автоматически диспатчит
синхронные сообщения. Не заполняет она структуру MSG для синхронных сообщений!
Еще книжка хорошая есть — Рихтер "Windows для професионалов"
— там про это очень подробно рассказывается.
А если все равно не веришь — попробуй из GetMessage получить хотя бы одно
синхронное сообщение, успехов...
Это еще раз говорит о том, что если человек хочет за фонарным столбом разглядеть дерево, он найдет кучу способов это сделать.
KL>Помоему написано не двусмыслено! Get(Peek)Message автоматически диспатчит KL>синхронные сообщения. Не заполняет она структуру MSG для синхронных сообщений!
Может быть не заполняет. Но тогда как сообщение доставляется в оконную процедуру? Поставь breakpoint на DispatchMessage и он ни разу не сработает. Получается, что Get(Peek)Message просто знают адрес процедуры! Но откуда??
Как такой вот message pump узнаёт адрес оконной процедуры?
while (GetMessage(&msg, NULL, 0, 0));
KL>А если все равно не веришь — попробуй из GetMessage получить хотя бы одно KL>синхронное сообщение, успехов...
Вот если ты такой умный, объясни каким образом GetMessage доставляет оконной процедуре сообщения (синхронные).
Здравствуйте, 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 которой эти ф-ции являтся ).
Короче говоря, никаких GetWindowLong GetMessage не вызывает. Но, как я сам убедился, сообщения каким-то образом она все-таки в оконную процедуру передает.
Меня смутило то, что TaskManager не может закрыть окно, имеющее "пустой" цикл
while (GetMessage(&msg, NULL, 0, 0));
Наверняка он посылает WM_CLOSE асинхронно. Я не перестаю удивляться ребятам из мелкософта: ну что им мешало использовать SendMessageTimeout?
После непродолжительной отладки выяснил, что GetMessage вызывает оконную процедуру с помощью некой функции, адрес которой (Prof SP3) 0x77E174C8. Она находится непосредственно перед IsWindowEnabled. Эта функция вызывает еще одну, та еще одну и наконец мы попадаем в оконную процедуру.
Покапался я в книжках и нашел (у Pietrek'а), что адрес оконной процедуры лежит по смещению 0x28 в структуре WND. Насколько я понимаю, из HWND можно лекго получить указатель на эту структуру, так что обращатся к GetWindowLong не нужно.
В общем, тема требует дальнейшего изучения...
Однако на счет того, что GetMessage не вызывает оконную процедуру я погорячился. Признаю свою ошибку.
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;
}
Здравствуйте, Alexey Shirshov, Вы писали:
AS>После непродолжительной отладки выяснил, что GetMessage вызывает оконную процедуру с помощью некой функции, адрес которой (Prof SP3) 0x77E174C8
А если скачать pdb-шник для USER32? Там имя этой функции наверняка есть.
AS>Однако на счет того, что GetMessage не вызывает оконную процедуру я погорячился. Признаю свою ошибку.
Вот и молодец. Кстати, вот полный список тех, кто это делает:
Обратите внимание, что ::MsgWaitForMultipleObjects() в этом списке нет,
она не обрабатывает синхронные сообщения, но она вернет WAIT_OBJECT_0 + nCount
исли будет получено синхронные сообщение из другой нити. Так что если в ответ на
WAIT_OBJECT_0 + nCount тупо вызывать ::GetMessage(), то ::GetMessage()
обработает синхронный вызов. И будет ждать, пока кто-то еще не
отправит-таки сообщение через ::PostMessage(). Возможно, что вечно.
Именно так и происходит в годе, создаваемом мастером WTL для MultiThreadSDI.
Что я и пытался сказать в прошлом письме.
[]
БП>А если скачать pdb-шник для USER32? Там имя этой функции наверняка есть.
Нету.
БП>Вот и молодец. Кстати, вот полный список тех, кто это делает:
БП>DialogBox БП>DialogBoxIndirect БП>DialogBoxIndirectParam БП>DialogBoxParam БП>GetMessage БП>MessageBox БП>PeekMessage БП>SendMessage
Буду знать. Спасибо.
хъ
Так гдеж ты был, когда я просил посмотреть статью про WTL? Я эту фичу не смог объяснить. А Влад уже все сверстал.
БП>Именно так и происходит в годе, создаваемом мастером WTL для MultiThreadSDI. БП>Что я и пытался сказать в прошлом письме.