Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS General Discussion » Bug in _FindMessageMapHandler? Collapse All
Subject Author Date
Nikita Davydov Feb 4, 2010 - 3:55 AM

Hello,


I create class (CMyClass) that is derived from other my class (CMyParentClass).



CMyParentClass is derived from CExtResizableDialog.


In CMyParentClass I implement OnPaint() and have ON_WM_PAINT in message map.


CMyClass does not handle WM_PAINT.


So... OnPaint in CMyParentClass doesn’t work. I tried to find a reason and found


that CExtResizableDialog handle WM_PAINT (in CExtWS::WindowProc and call _FindMessageMapHandler to check that WM_PAINT is handled by user. But _FindMessageMapHandler check message map only of most junior class (CMyClass) and doesn’t check message map of its parent. So it doesn’t know about the item ON_WM_PAINT in message map of CMyParentClass and so my OnPaint is not called.


I think it is not normal behaviour. I’ve correct FindMessageMapHandler but may be I can do something whithout correcting code of Prof-UIS?


Thank you


 


Nikitos I



 


 


Nikita Davydov Feb 4, 2010 - 6:49 AM

const AFX_MSGMAP_ENTRY * _FindMessageMapHandler(
UINT nMsg,
UINT nCode,
UINT nID
)
{
ASSERT_VALID( this );
/************** vv Prof-UIS vv *****************
const AFX_MSGMAP * pMessageMap = GetMessageMap();
if( pMessageMap != NULL )
{
UINT nEntry = 0;
const AFX_MSGMAP_ENTRY * lpEntry = NULL;
while( (lpEntry = (pMessageMap->lpEntries + nEntry))->nSig != AfxSig_end )
{
if(    lpEntry->nMessage == nMsg
&& lpEntry->nCode == nCode
&& nID >= lpEntry->nID
&& nID <= lpEntry->nLastID
)
return lpEntry;
nEntry++;
}
} // if( pMessageMap != NULL )
************** ˆˆ Prof-UIS ˆˆ *****************/

// ************** vv Nikitos I vv *****************
const AFX_MSGMAP *pThisMessageMap = GetThisMessageMap ();
const AFX_MSGMAP *pMessageMap = GetMessageMap ();
while ((pThisMessageMap != pMessageMap) && (pMessageMap != NULL))
{
UINT nEntry = 0;
const AFX_MSGMAP_ENTRY *lpEntry = NULL;
while ((lpEntry = (pMessageMap->lpEntries + nEntry))->nSig != AfxSig_end)
{
if ((lpEntry->nMessage == nMsg) && (lpEntry->nCode == nCode) &&
(nID >= lpEntry->nID) && (nID <= lpEntry->nLastID))
return lpEntry;
nEntry ++;
};
if (pMessageMap->pfnGetBaseMap == NULL)
return NULL;
pMessageMap = pMessageMap->pfnGetBaseMap ();
};
// ************** ˆˆ Nikitos I ˆˆ *****************

return NULL;
}

Nikita Davydov Feb 4, 2010 - 6:43 AM

 


 


 



const AFX_MSGMAP_ENTRY * _FindMessageMapHandler(this );

/************** vv Prof-UIS vv *****************

const AFX_MSGMAP * pMessageMap = GetMessageMap();

if( pMessageMap != NULL )

{

UINT nEntry = 0;

const AFX_MSGMAP_ENTRY * lpEntry = NULL;

while( (lpEntry = (pMessageMap->lpEntries + nEntry))->nSig != AfxSig_end )

{

if( lpEntry->nMessage == nMsg

&& lpEntry->nCode == nCode

&& nID >= lpEntry->nID

&& nID <= lpEntry->nLastID

)

return lpEntry;

nEntry++;

}

} // if( pMessageMap != NULL )

************** ˆˆ ProfUIS ˆˆ *****************/

 

// ************** vv Nikitos I vv *****************

 

 

 

{

UINT nEntry =

 

 

{

 

(nID >= lpEntry->nID) && (nID <= lpEntry->nLastID))

 

nEntry ++;

};

 

 

pMessageMap = pMessageMap->pfnGetBaseMap ();

};

const AFX_MSGMAP *pThisMessageMap = GetThisMessageMap (); const AFX_MSGMAP *pMessageMap = GetMessageMap (); while ((pThisMessageMap != pMessageMap) && (pMessageMap != NULL))0; const AFX_MSGMAP_ENTRY *lpEntry = NULL; while ((lpEntry = (pMessageMap->lpEntries + nEntry))->nSig != AfxSig_end) if ((lpEntry->nMessage == nMsg) && (lpEntry->nCode == nCode) && return lpEntry; if (pMessageMap->pfnGetBaseMap == NULL) return NULL;

// ************** ˆˆ Nikitos I ˆˆ *****************

 

 

return NULL;

}

UINT nMsg,

UINT nCode,

UINT nID

)

{

ASSERT_VALID(


Technical Support Feb 4, 2010 - 1:48 PM

Thank you for the interesting information. Your improved version of the _FindMessageMapHandler() method works only with Visual Studio 2005 (8.0) and later Visual Studio versions. The GetThisMessageMap() API is not present in Visual C++ 6.0 and it’s present in Visual Studio .NET (7.0) and Visual Studio .NET 2003 (7.1) only in the DLL version of MFC (when the _AFX_DLL preprocessor symbol is defined while compiling MFC-based project). This means your good improvement cannot be applied as is because we support compatibility with Visual Studio versions older than Visual Studio 2005 (8.0). We spend several hours on improving your good version of the _FindMessageMapHandler() method. Here is the updated version of the .../Prof-UIS/Include/ExtTempl.h file:

http://www.prof-uis.com/download/forums/tmp/ExtTempl_h_for_Nikita_Davydov.zip

What’s new in this header file? The CExtWS::WindowProc() method handles the WM_PAINT message a bit differently and searches/invokes message map handlers before doing default painting. Of course, our version of the _FindMessageMapHandler() method is also there:

   const AFX_MSGMAP_ENTRY * _FindMessageMapHandler( UINT nMsg, UINT nCode, UINT nID )
            {
                        ASSERT_VALID( this );
                        UINT nEntry = 0;
                        const AFX_MSGMAP_ENTRY * lpEntry = NULL;
                        const AFX_MSGMAP * pMessageMap = GetMessageMap(); 
#if ( _MFC_VER >= 0x800 )
                        const AFX_MSGMAP * pThisMessageMap = GetThisMessageMap();
                        for( ; pThisMessageMap != pMessageMap && pMessageMap != NULL; pMessageMap = pMessageMap->pfnGetBaseMap() )
                        {
                                    for( nEntry = 0, lpEntry = NULL; ( lpEntry = ( pMessageMap->lpEntries + nEntry ) ) -> nSig != AfxSig_end; nEntry ++ )
                                    {
                                                if(                     lpEntry->nMessage == nMsg
                                                            &&        lpEntry->nCode == nCode
                                                            &&        lpEntry->nID <= nID && nID <= lpEntry->nLastID
                                                            )
                                                            return lpEntry;
                                    }
                                    if( pMessageMap->pfnGetBaseMap == NULL ) 
                                                return NULL;
                        }
#else // ( _MFC_VER >= 0x800 )
            #if ( defined _AFXDLL )
                        for( ; pMessageMap != NULL; pMessageMap = (*pMessageMap->pfnGetBaseMap)() )
            #else
                        for( ; pMessageMap != NULL; pMessageMap = pMessageMap->pBaseMap )
            #endif
                        {
                                    for( nEntry = 0, lpEntry = NULL; ( lpEntry = ( pMessageMap->lpEntries + nEntry ) ) -> nSig != AfxSig_end; nEntry ++ )
                                    {
                                                if(                     lpEntry->nMessage == nMsg 
                                                            &&        lpEntry->nCode == nCode 
                                                            &&        lpEntry->nID <= nID && nID <= lpEntry->nLastID
                                                            )
                                                            return lpEntry;
                                    }
                        }
#endif // else from ( _MFC_VER >= 0x800 )
                        return NULL;
            }

It’s tested and works with Visual C++ 6.0, Visual Studio 2005 (8.0), Visual Studio 2008 (9.0) and Visual Studio 2010 beta 2 (10.0). It’s buggy with Visual Studio .NET (7.0) and Visual Studio .NET 2003 (7.1) because the message map implementation in these VS versions is different and does not allow to detect the pThisMessageMap pointer in all the cases because the GetThisMessageMap() API is present in the DLL MFC version only. As result, the CDialog::OnPaint() handler method is always invoked. This is not a problem for Visual C++ 6.0 because there is no CDialog::OnPaint() method there.
In conclusion, we keep this question open and continue searching for a better solution. We would like to ask you to handle the WM_PAINT messages in the WindowProc() virtual method in all your CExtWS-based windows including CExtResizableDailog-derived classes.

Nikita Davydov Feb 4, 2010 - 2:29 PM

Thank you for your explanation. I’ll handle WM_PAINT in WindowProc - it’s better solution at this time because I don’t like to change Prof-UIS code. It is difficult to keep changes on different comps and when update Prof-UIS version.


Nikitos I