Здравствуйте, algod, Вы писали:
A>Здравствуйте, Рек, Вы писали:
Рек>>Правильно ли я понял,
Рек>>что SM-сообщения обрабатываются внутри GetMessage (прямым колом)
Рек>>и никогда не попадают в DispatchMessagе?
Рек>>В том числе и тогда когда сообщение пришло из другого потока.
Рек>>Так?
A>Извини — наверное где то неправильно выразился
A>GetMessage — забирает следующее сообщение из очереди. И ничего более... Оно не вызывает оконную процедуру.
A>вот DispatchMessagе — уже вызывает оконную процедуру, исходя из параметров полученых из GetMessage, по пути обработав таймер.
A>SendMessage напрямую вызывает оконную процу (с синхронизацией, естественно).
НЕВЕРНО!!! Если поток не вызывает GetMessage или PeekMessage сообщение НИКОГДА не будет обработанно!
SendMessage НЕ ВЫЗЫВАЕТ напрямую оконную процедуру — если бы это было так — то оконная процедура вызывалсь бы
в
ТЕКУЩЕМ потоке — а не потоке
ВЛАДЕЮЩЕМ очередью сообщений!!!
В WINDOWS ВСЕ СООБЩЕНИЯ ДЛЯ ПОТОКА ОБРАБАТЫАЮТСЯ ТОЛЬКО В САМОМ ПОТОКЕ!
Так что прав — Pek.
Синхронные сообщения имеют наибольший приоритет и обрабатываются в первую очередь!
Они обрабатываются автоматически
(перенаправляются в оконную процедру) внутри вызова потоком Get(Peek)Message.
Используя Get(Peek)Message можно выбрать из очереди только асинхронное собщение.
A>Т.е., грубо говоря, содержимое DispatchMessagе можно представить как:
A>A>LRESULT
A>DispatchMessage
A> ( CONST MSG *lpmsg )
A>{
A>// ***********************
A>// Обработка каллбека таймера, если обрабатываем сообщение WM_TIMER, если такой имееться
A>// ***********************
A>// Возможно что то еще: проверки на валидность оконного хендла, етс.
A>// ***********************
A> return SendMessage
A> ( lpmsg->hwnd,
A> , lpmsg->message
A> , lpmsg->wParam
A> , lpmsg->lParam );
A>}
A>
A>Грубая реализация SendMessage:
A>A>LRESULT SendMessage
A> ( HWND hWnd
A> , UINT Msg
A> , WPARAM wParam
A> , LPARAM lParam)
A>{
A>// ***********************
A>// Что то тут есть: проверка на валидность оконного хендла, синхранизация многопоточности етс.
A>// ***********************
A> return CallWindowProc
A> ( (WNDPROC) GetWindowLong (lpmsg->hwnd, GWL_WNDPROC)
A> , lpmsg->message
A> , lpmsg->wParam
A> , lpmsg->lParam );
A>}
A>
A>Я не знаю досконально внутренний механизм этих функций, но судя по всему, оно где то рядом...
A>Теоретически можно поробовать реализовать стандартный оконный луп через CallWindowProc или
A>SendMessage — и посмотреть что получиться...
A>з.ы. кстати — сейчас попробую, и напишу 
Все не так
ПСЕВДОКОД Windows

:
LRESULT SendMessage(HWND hWnd, UINT Msg , WPARAM wParam , LPARAM lParam)
{
DWORD dwThreadID = System::GetWindowNativeThreadID(hWnd);
System::MessageQueue* pQueue = System::GetThreadMessageQueue(dwThreadID);
MSG msg(Msg, wParam, lParam)
return pQueue->AddSync(&msg);
}
LRESULT System::MessageQueue::AddSync(MSG* pMsg)
{
SyncMSGWrapper SyncMsg(pMsg);
m_mtx.Lock();
m_list.push_back(&SyncMsg)
m_mtx.Unlock();
m_NewMsgEvent.Set();
if(WaitForXXXX(SyncMsg.m_ProcessedEvent.GetHandle(), INFINITE) == WAIT_OBJECT_0)
return SyncMsg.GetResult();
else
обработка ошибок
}
BOOL GetMessage(MSG* pMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
{
System::MessageQueue* pQueue = System::GetThreadMessageQueue(::GetCurrentThreadID());
return pQueue->GetMessage(pMsg, hWnd, wMsgFilterMin,wMsgFilterMax);
}
BOOL System::MessageQueue::GetMessage(MSG* pMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
{
if(::GetCurrentThreadID() != m_dwNativeThreadID)
return -1;
while(TRUE)
{
m_mtx.Lock();
if(m_list.empty())
{
if(WaitForXXX(m_NewMsgEvent.GetHandle(), INFINiTE) == WAIT_OBJECT_0)
break;
}
else
{
for(iter i = m_list.begin(); i != m_list.end(); ++i)
{
SystemMSG* pMSG = *i;
if(pMSG->IsSync())
{
FindAndCallWindowProc(pMSG);
pMsg->m_ProcessedEvent.Set();
m_list.erase(i);
}
}
// далее поиск на соотв фильтру асинхронного сообщения и возврат
// первого подходящего
}
}
}