Программирование на языке MFC

Мой второй блог в серии программирования

Макрос BEGIN_MESSAGE_MAP


Во-первых, этот макрос завершает таблицу сообщений записью с нулевой сигнатурой. Во-вторых, он ставит ту самую завершаю­щую фигурную скобку, которой мы недосчитались при анализе тек­ста макроса BEGIN_MESSAGE_MAP. На этом наше знакомство с таблицей сообщений можно завершить.

Перед началом рассмотрения таблицы сообщений мы остано­вились на методе DispatchThreadMessageEx() класса CWinThread. Итак, вернемся к коду этого метода и продолжим работу.

Итак, что происходит в этом методе? Сначала метод выбирает ука­затель на таблицу сообщений при помощи метода GetMessageMap(), а затем входит в цикл для поиска необходимого обработчика сооб­щений. При этом обработка сообщений с кодом менее OxCOOO не­сколько отличается от обработки сообщений с кодом от OxCOOO и выше.

Если обрабатывается сообщение с кодом менее OxCOOO, это означает, что сообщение является сообщением Windows. Для по­иска необходимого обработчика вызывается функция AfxFind-MessageEntry(). Исходный код этой функции находится в файле wincore.cpp:

Пример

AfxFindMessageEntry(const AFX_MSGMAP_ENTRY* IpEntry,

UINT nMsg, UINT nCode, UINT nID)

{

#if defined(_M_IX86) && !defined(_AFX_PORTABLE) // 32-bit Intel 386/486 version.

ASSERT(offsetof(AFX_MSGMAP_ENTRY, nMessage) == 0) ;

ASSERT(offsetof(AFX_MSGMAP_ENTRY, nCode) == 4);

ASSERT(offsetof(AFX_MSGMAPJ2NTRY, nIDl == 8);

ASSERT(offsetof(AFX_MSGMAP_ENTRY, nLastID) == 12);

ASSERT(offsetof(AFX_MSGMAP_ENTRY, nSig) == 16);

asm

MOV EBX,IpEntry

MOV EAX, nMsg

MOV EDX,nCode

MOV ECX,nID

loop:

CMP DWORD PTR [EBX+16],0

JZ _ failed

CMP EAX,DWORD PTR [EBX]

JE found_message

nSig (0 => end)

nMessage

next:

ADD EBX,SIZE AFX_MSGMAP_ENTRY
JMP
short loop

found_message:

CMP EDX,DWORD PTR [EBX+4]

JNE next

nCode

// message and code good so far // check the ID

CMP ECX,DWORD PTR [EBX+8]

JB _ next

CMP ECX,DWORD PTR [EBX+12]
JA
next

nID

nLastID

// found a match

MOV IpEntry,EBX

JMP short end

return EBX

failed:

XOR EAX,EAX

MOV IpEntry,EAX

return NULL

end:

return IpEntry; #else // _AFX_PORTABLE

// С version of search routine while (lpEntry->nSig != AfxSig_end) {

if (lpEntry->nMessage — nMsg && lpEntry->nCode == nCode && nID >= lpEntry->nID && nID <= lpEntry->nLastID)

{

return IpEntry;

}

lpEntry++;

}

return NULL; // not found #endif // _AFX_PORTABLE }

Похожие статьи: