Message flow traceable message LRESULT CALLBACKAFXWNDPROC (HWND HWND, UINT NMSG, WPARAM WPARAM, LPARAM LPARAM) {// ...
// All Other Messages Route Through Message Map CWND * PWND = CWND :: fromHandlePermanent (hwnd); // ... Return AFXCallWndProc (PWND, HWND, NMSG, WPARAM, LPARAM);}
LRESULT AFXAPI AfxCallWndProc (CWnd * pWnd, HWND hWnd, UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0) {// ... // Catch exceptions thrown outside the scope of a callback // in debug builds and warn the user. LRESULT Lresult; // ... // delegate to Object's WindowProc LRESULT = PWND-> WindowProc (NMSG, WPARAM, LPARAM); // ... return LRESULT;} Finally, the message is transmitted to WindowProc, this is a virtual function in a CWND class In the MFC, there are many classes of the heavy-duty function, but because the general windows are derived from CWnd (such as CFrameWnd),, CWND :: WndProClResult CWnd :: WindowProc (Uint Message, WPARAM WPARAM, LPARAM LPARAM) {// OnWndMsg does most of the work, except for DefWindowProc call LRESULT lResult = 0; if (OnWndMsg (message, wParam, lParam, & lResult)!) lResult = DefWindowProc (message, wParam, lParam); return lResult;} firstly OnWndMSG processing message, if OnWndMSG has failed to process messages, call DefWindowProc. Let's see OnWndmsg first, this is a virtual function of a CWND class. This function is very simple. If the message is WM_COMMAND or WM_NOTIFY, the message is handed over to ONCOMMAND and ONNOTIFY processing, otherwise look for the message cache built in the MFC. Message, if there is no corresponding handler, return false (this will be handed over to CWnd :: DefWindowProc), if you hit, further judgment is the message that the user's own registration is still the standard Windows message, if it is the former, jump To the label LDispatchRegistered process, call the corresponding message processing function, otherwise jump to the LDispatch processing, call the correct message processing function. If the message is not in the cache, you will find along the inheritance route of a class, and find the message mapping table of each class by AFXFindMessagentry. If the match is found, the message is also processed according to whether or not the user registered message, If you have never found a match, return false, handed down to CWnd :: DefWindowProc. Bool CWnd :: OnWndmsg (Uint Message, WPARAM WPARAM, LRESULT * PRESULT) {LRESULT LRESULT = 0; Union MessageMapFunctions MMF; MMF.PFN = 0;
// Special Case for Commands if (message == wm_command) {if (oncommand (wparam, lparam)) {LRESULT = 1; goto LreturnTrue;} Return False;} // Special Case for Notifies if (message == WM_NOTIFY) {NMHDR * pNMHDR = (NMHDR *) lParam; if (! pNMHDR-> hwndFrom = NULL && OnNotify (wParam, lParam, & lResult)) goto LReturnTrue; return FALSE;} // ... ... const AFX_MSGMAP * pMessageMap; pMessageMap = GetMessageMap (); // Get message map UINT iHash class; iHash = (LOWORD ((DWORD_PTR) pMessageMap) ^ message) & (iHashMax-1); AfxLockGlobals (CRIT_WINMSGCACHE); AFX_MSG_CACHE * pMsgCache; pMsgCache = & _afxMsgCache [iHash]; const AFX_MSGMAP_ENTRY * lpEntry; // determines whether the message is in the cache if (message == pMsgCache-> nMsg && pMessageMap == pMsgCache-> pMessageMap) {// cache hit lpEntry = pMsgCache-> lpEntry; AfxUnlockGlobals (Crit_winmsgcache); if (lpenTry == null) // In the cache, but there is no corresponding entry, return false returnaf false;
// cache hit, And it needs to be Handled if (Message <0xc000) / / Otherwise, in accordance with the user-defined message, jump to the corresponding position goto ldispatch; // Standard Windows Message Else Goto LdispatchRegistered; //// User Custom Message} Else // If the message is not in the cache, you have to check the house to check {// not in cache, Look for it pmsgcache-> nmsg = message; pmsgcache-> pimentagemap = pMessageMap; // below this for Cycle from the derived class to the base class for each class message mapping table for (/ * pMessagemap already initàed * /; pMessageMap! = NULL; PMESSAGEMAP = PMESSAP-> PBASEMAP) {if (Message <0xc000) // If the message is a standard Windows message {// constant window message if ((lpEntry = AfxFindMessageEntry (pMessageMap-> lpEntries, message, 0, 0)) = NULL!) {pMsgCache-> lpEntry = lpEntry; AfxUnlockGlobals (CRIT_WINMSGCACHE); goto LDispatch; / / If you find the corresponding item, turn the process}}} else // If it is a user-defined message {// registered windows message lpenTry = pimentRiesMap-> LpenTries; while ((LpenTry = afxFindMessageTry " ! = Null) {uint * PNID = (UINTRY-> nsig); assert (* pnid> = 0xc000 || * PnID == 0); // must be successfully registered if (* pnID == message) {pMsgCache-> lpEntry = lpEntry; AfxUnlockGlobals (CRIT_WINMSGCACHE); goto LDispatchRegistered; // if found to turn treated} lpEntry ; // keep looking past this one}}} // In the cache, all classes are not ignored, then return false, handed down to cwnd :: defWndproc // PMSGCache-> LPENTRY = NULL; AFXUNLOCKGLOBALS (crit_winmsgcache); return false;} // is right below Windows standard messages and user custom messages LDispatch: assert (Message <0xC000); MMF.PFN = LPENTRY-> PFN;
Switch (LpenTry-> nsig) {Default: Assert (false); Break
Case AFXSIG_B_D_V: LRESULT = (this -> * mmf.pfn_b_d) (CDC :: FromHandle (ReinterPret_Cast
Case AFXSIG_B_U_V: LRESULT = (THIS -> * MMF.PFN_B_U) (static_cast
case AfxSig_b_h_v: lResult = (this -> * mmf.pfn_b_h) (reinterpret_cast