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 » ProfUIS 284 and VS2010 - ScrollBar Crash during initilization. Collapse All
Subject Author Date
Mark Lo Chiano Sep 10, 2010 - 4:40 PM

Sirs,


  I know that you have answered this before, but I am unable to locate the prior thread in the various forums.


  There appears to be a known incompatability between ProfUIS v284 and Visual Studio 2010.    One of the primary ways that this appears is that an application may crash during startup.  


  In particular, a CExtToolBoxWnd that receives normal OnSize messages initially passes that message along to CExtScrollWnd::OnSize for processing.   The CEstScrollWnd in turn calls the OnSwUpdateScrollBars() method.  This method then attempts to enable (or disable) the horizontal and vertical scroll bars using OnSwEnableScrollBarCtrl ( SB_VERT, sizeNeedSB.cy ? true : false );


  In my case, the issue is within the enable/disable of the vertical scroll bar, where it attempts to pass the call along to CWnd::ShowScrollBar ( SB_VERT, FALSE );   Inside CWnd::ShowScrollBar it always fails, reporting an invalid window handle.


 My memory of your prior answer was something along the lines of "To avoid this the application will have to use a delayed (or defered) window creation approach".


  If my memory is somewhat accurate...could you explain how this application crash can be avolded?


 

Janet W Sep 17, 2010 - 8:06 PM



Hi !

I’ve just visited this forum. Happy to get acquainted with you. Thanks.


 


 




__________________

http://moviesonlineworld.com

Mark Lo Chiano Sep 13, 2010 - 5:59 PM

Never mind....it looks like the html editor kills the formatting...so this is a very misleading example.

Mark Lo Chiano Sep 13, 2010 - 5:57 PM


 


Here is an example of one potential way to format your code..........


 


///////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////////////////////////////

//

// mtlc

//

bool CExtCmdProfile::UpdateFromMenu ( HMENU hMenu,

                                                               int   nResourceId,

                                                               bool bCustomize,

                                                               bool bReplaceOld,

                                      bool bRecursive,

                                                               bool bLoadTips )

{

//////////////////////////////////////

//     declare local variables

int            nMenuItemCount;

int            nMenuItemIdx;

CString        save_LastMenuName;

CExtCmdItem * pCmdItem = NULL;

CExtCmdItem * pTestCmdItem;

MENUITEMINFO   mii;

int            nLen;

bool           bResult;

BOOL           bExist;

int            iCustomizables;

int            iCustomizable;

bool           yesAdd;

 

    if ( hMenu == NULL )

    {

        return false;

    }

 

    if ( !( ::IsMenu ( hMenu ) ) )

    {

        return false;

    }

 

    //////////////////////////////////////////////////////////////////////////////

    //////////////////////////////////////////////////////////////////////////////

    //////////////////////////////////////////////////////////////////////////////

    //

    // loop through each of the menu items.........this will get the

    // primary top level items for this menu

    //

    nMenuItemCount = ::GetMenuItemCount ( hMenu );

    for ( nMenuItemIdx = 0; nMenuItemIdx < nMenuItemCount; nMenuItemIdx++ )

    {  

    //////////////////////////////

    // want this definition within the loop

    // so we get a fresh copy for every command

    // several lines of code are dependent upon detecting

    // a blank menutext

    CExtCmdItem    _cmd;

    CExtSafeString sMenuText;

   

        // get the menu item info

        ::memset ( &mii, 0, sizeof ( MENUITEMINFO ) );

        mii.cbSize = sizeof ( MENUITEMINFO );

        mii.fMask = MIIM_CHECKMARKS |

                              MIIM_DATA       |

                                   MIIM_ID         |

                                   MIIM_STATE      |

                                   MIIM_SUBMENU    |

                                   MIIM_TYPE;

        mii.cch        = __MAX_UI_ITEM_TEXT;

        mii.dwTypeData = sMenuText.GetBuffer ( __MAX_UI_ITEM_TEXT );

        ASSERT ( mii.dwTypeData != NULL );

        if ( mii.dwTypeData == NULL )

        {

            ASSERT ( FALSE );

 

            ////////////////////////////

            //       bad data type --> jump to next item

            continue;

        }

 

        ///////////////////////////////////////////////////////////////

        //    this call will load the menu text

        if ( !::GetMenuItemInfo ( hMenu, nMenuItemIdx, TRUE, &mii ) )

        {

            sMenuText.ReleaseBuffer ();

            ASSERT ( FALSE );

 

            ////////////////////////////

            //       could not get item information -->jump to next item

            continue;

        }

 

        sMenuText.ReleaseBuffer ();

        if ( ( mii.fType & MFT_SEPARATOR ) != 0 )

        {

            ////////////////////////////

            //       this is a separator --> jump to next item

            continue;

        }

 

        //////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////

        //////////////////////////////////////////////////////////////////

        // if sub-menu process it recursively

        if ( mii.hSubMenu != NULL )

        {

            if ( !bRecursive )

            {

                ////////////////////////////

                //   should not be here --> jump to next item

                continue;

            }

 

            /////////////////////////////////////////////////////////////////////

            /////////////////////////////////////////////////////////////////////

            /////////////////////////////////////////////////////////////////////

            //       after this call...want to reset the g_LastMenuName value

            bResult = UpdateFromMenu ( mii.hSubMenu, nResourceId, bCustomize, bReplaceOld, true, true );

 

            ////////////////////////////

            //       done with this submenu --> jump to next item

            continue;

        }   // if( mii.hSubMenu != NULL )

 

        // register command

        if ( ! CExtCmdManager::IsCommand ( mii.wID ) )

        {

            ////////////////////////////

            //       invalid command --> jump to next item

            continue;

        }

 

        ///////////////////////////////////////////////////////

        //    if this is menuItem 0, then this is the parent of all of the

        //    children

        _cmd.m_nCmdID = mii.wID;

 

        sMenuText.Replace ( _T ( "\n" ), _T ( "" ) );

        sMenuText.Replace ( _T ( "\r" ), _T ( "" ) );

        sMenuText.Replace ( _T ( "&" ), _T ( "" ) );    // mtlc

        sMenuText.TrimLeft ();

        sMenuText.TrimRight ();

 

        /////////////////////////////////////////

        //    begin mtlc additions

        _cmd.m_fromMenu    = 1;

        _cmd.m_fromToolBar = 0;

        _cmd.m_menuIds.Add ( ( UINT ) nResourceId );

 

        // end mtlc additions

        /////////////////////////////////////////

        if ( !sMenuText.IsEmpty () )

        {

            int nSep = sMenuText.ReverseFind ( _T ( ’\t’ ) );

            if ( nSep >= 0 )

            {

                nLen = sMenuText.GetLength ();

 

                ///////////////////////////////////////////////////////

                //   parse the accellerator

                _cmd.m_sAccelText = sMenuText.Right ( nLen - nSep );

                _cmd.m_sAccelText.TrimLeft ();

                _cmd.m_sAccelText.TrimRight ();

 

                ////////////////////////////////////////////////////////

                //   virtual key codes

                if ( _cmd.m_sAccelText.GetLength () > 0 )

                {

                    _cmd.m_HotKey.StringToVirtual ( _cmd.m_sAccelText );

                }   // end of translate to the internal virtual key code structure

               

                //////////////////////////////////////////////////

                //   parse the menu text

                _cmd.m_sMenuText = sMenuText.Left ( nSep );

                _cmd.m_sMenuText.TrimLeft ();

                _cmd.m_sMenuText.TrimRight ();

            }

            else

            {

                _cmd.m_sMenuText = sMenuText;

            }

        }   // if( ! sMenuText.IsEmpty() )

       

        //////////////////////////////////////

        //    load the tool tips

        if ( bLoadTips )

        {

            _cmd.TipsLoad ();

        }

 

        /////////////////////////////////////////////////

        //    do the actual storage

        bResult = CmdSetup ( _cmd, bReplaceOld );

 

        //////////////////////////////////////////////////////////////////////

        //    do we want to add this to the customizable command list?

        //    if so, then do not add it more than once for the same command id

        if ( bCustomize == true )

        {

            bExist = m_cmds.Lookup ( _cmd.m_nCmdID, pCmdItem );

            if ( bExist == TRUE )

            {

                yesAdd = true;

                iCustomizables = m_CustomizableCommands.GetCount ();

                for ( iCustomizable = 0; iCustomizable < iCustomizables; iCustomizable++ )

                {

                    pTestCmdItem = ( CExtCmdItem * ) m_CustomizableCommands.GetAt ( iCustomizable );

                    if ( pTestCmdItem->m_nCmdID == pCmdItem->m_nCmdID )

                    {

                        yesAdd = false;

                        break;

                    }

                }   // end of this customizable

 

                if ( yesAdd == true )

                {

                    m_CustomizableCommands.Add ( pCmdItem );

                }   // end of we had not seen this command before.

            }   // end of this is a valid command

        }   // end of remember this customizable command

    }   // for all menu level items

   

    /////////////////////////////////

    // all done

    return true;

}

// end of UpdateFromMenu method

 

//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////

//

//

//     mtlc...

//     this is the primary method that in in the ’Call From App’

//     chain

//

bool CExtCmdProfile::UpdateFromMenu ( UINT             nResourceID,

                                                               CExtCmdManager * parentMgr,

                                                               bool             bCustomizable,

                                                               bool             bReplaceOld,

                                      bool             bLoadTips )

{

///////////////////////////////////////

//     declare local variables

CMenu           *menu;

MENUINFO        *menuInfo;

bool            bResult;

menuCustomize   *newMenuCustomizer;

 

    __PROF_UIS_MANAGE_STATE;

    menu = new CMenu ();

    if ( !g_ResourceManager->LoadMenu ( *menu, nResourceID ) )

    {

        ASSERT ( FALSE );

        return false;

    }

 

    ///////////////////////////////////////////////////////

    // mtlc

    // want to get the information about this menu, and remember

    // this menu in the ’customizable’ list.

    if ( bCustomizable == true )

    {

        //////////////////////////////////////////////////

        //    create the structures

        newMenuCustomizer = new menuCustomize ();

        menuInfo = new MENUINFO ();

        ::memset ( menuInfo, 0, sizeof ( MENUINFO ) );

        menu->GetMenuInfo ( menuInfo );

 

        ////////////////////////////////////////////////////////////

        //    remember it

        newMenuCustomizer->bCustomizable = bCustomizable;

        newMenuCustomizer->pProfile      = this;

        newMenuCustomizer->theParentMenu = menu;

        newMenuCustomizer->menuInfo      = menuInfo;

        newMenuCustomizer->nResourceId   = nResourceID;

        newMenuCustomizer->MenuName      = "No Name Supplied";

 

        parentMgr->m_CustomizableMenus.Add ( newMenuCustomizer );

    }   // end of customizable menu

   

    ///////////////////////////////////////////////////////////////////////////////////////

    // pass it along to the method that will actually do the work

    bResult = UpdateFromMenu ( menu->GetSafeHmenu (), nResourceID, bCustomizable, bReplaceOld, true, bLoadTips );

 

    //////////////////////////////////////

    // if not customizable...release the menu class object

    if ( bCustomizable != true )

    {

        delete menu;

    }

 

    /////////////////////////

    // all done

    return bResult;

} // end of UpdateFromMenu method

Technical Support Sep 13, 2010 - 1:15 PM

Your improvement is the same as adding the following to the beginning of the method:

   if( GetSafeHwnd() == NULL )
                        return;

It would be extremely interesting to know what’s wrong with code formatting in details

Mark Lo Chiano Sep 13, 2010 - 9:26 AM

Here is a corrected version of the offending method.    Sorry the the copy/paste operation tends to strip out the tabs...


 


-----------------------  Begin Code Snippet -------------------------------------------


 ////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////

//

//

//

void CExtScrollWnd::OnSwEnableScrollBarCtrl ( int nBar, bool bEnable )

{

///////////////////////////////

// declare local variables





ASSERT_VALID ( this );

ASSERT ( nBar == SB_HORZ || nBar == SB_VERT || nBar == SB_BOTH );

if ( !IsWindowEnabled () )

{

bEnable = false;

}



DWORD dwWndStyle = CWnd::GetStyle ();

CPoint ptMove = OnSwGetScrollPos ();

CScrollBar* pScrollBarWndH = GetScrollBarCtrl ( SB_HORZ );

CScrollBar* pScrollBarWndV = GetScrollBarCtrl ( SB_VERT );

if ( nBar == SB_HORZ || nBar == SB_BOTH )

{

if ( ( !bEnable ) && ptMove.x != 0 )

{

ptMove.x = 0;

OnSwSetScrollPos ( ptMove );

} // if( (!bEnable) && ptMove.x != 0 )



if ( pScrollBarWndH != NULL )

{

if ( ( dwWndStyle & WS_HSCROLL ) != 0 )

{

CWnd::ShowScrollBar ( SB_HORZ, FALSE );

}



bool bAreadyEnabled = pScrollBarWndH->IsWindowEnabled () ? true : false;

if ( !( (bAreadyEnabled && bEnable) || ((!bAreadyEnabled) && (!bEnable)) ) )

{

pScrollBarWndH->EnableWindow ( bEnable ? TRUE : FALSE );

if ( OnSwCanAutoHideScrollBar ( true ) )

{

pScrollBarWndH->ShowWindow ( bEnable ? SW_SHOW : SW_HIDE );

}

else

if ( bEnable && ( pScrollBarWndH->GetStyle () & WS_VISIBLE ) == 0 )

{

pScrollBarWndH->ShowWindow ( SW_SHOW );

}

}

} // if( pScrollBarWndH != NULL )

else

{

if ( OnSwCanAutoHideScrollBar ( true ) )

{

CWnd::ShowScrollBar ( SB_HORZ, bEnable ? TRUE : FALSE );

}

else

{

CWnd::EnableScrollBar ( SB_HORZ, bEnable ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH );

}

} // else from if( pScrollBarWndH != NULL )

} // if( nBar == SB_HORZ || nBar == SB_BOTH )



if ( nBar == SB_VERT || nBar == SB_BOTH )

{

if ( ( !bEnable ) && ptMove.y != 0 )

{

ptMove.y = 0;

OnSwSetScrollPos ( ptMove );

} // if( (!bEnable) && ptMove.y != 0 )





///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////

// is this a valid window?

if ( pScrollBarWndV != NULL )

{

if ( ( dwWndStyle & WS_VSCROLL ) != 0 )

{

//////////////////////////////////////////////

// mtlc - Sept 2010 ...add check for isWindow

if ( ::IsWindow(m_hWnd) ) // <---- new code

{

// CWnd::ShowScrollBar ( SB_VERT, FALSE ); // <--- old code causes ASSERT for invalid handle

pScrollBarWndV->ShowScrollBar ( FALSE );

} // wait until the window handle is actually valid

} // does this window have a scrolling style?



bool bAreadyEnabled = pScrollBarWndV->IsWindowEnabled () ? true : false;

if ( !( (bAreadyEnabled && bEnable) || ((!bAreadyEnabled) && (!bEnable)) ) )

{

pScrollBarWndV->EnableWindow ( bEnable ? TRUE : FALSE );

if ( OnSwCanAutoHideScrollBar ( false ) )

{

pScrollBarWndV->ShowWindow ( bEnable ? SW_SHOW : SW_HIDE );

}

else

if ( bEnable && ( pScrollBarWndV->GetStyle () & WS_VISIBLE ) == 0 )

{

pScrollBarWndV->ShowWindow ( SW_SHOW );

}

}

} // if( pScrollBarWndV != NULL )

else

{

if ( OnSwCanAutoHideScrollBar ( false ) )

{

CWnd::ShowScrollBar ( SB_VERT, bEnable ? TRUE : FALSE );

}

else

{

CWnd::EnableScrollBar ( SB_VERT, bEnable ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH );

}

} // else from if( pScrollBarWndV != NULL )

} // if( nBar == SB_VERT || nBar == SB_BOTH )



CExtScrollBar* pExtScrollBarWndH = DYNAMIC_DOWNCAST ( CExtScrollBar, pScrollBarWndH );

CExtScrollBar* pExtScrollBarWndV = DYNAMIC_DOWNCAST ( CExtScrollBar, pScrollBarWndV );

if ( pExtScrollBarWndH != NULL && pExtScrollBarWndV != NULL )

{

pExtScrollBarWndH->SyncReservedSpace ( pExtScrollBarWndV );

pExtScrollBarWndV->SyncReservedSpace ( pExtScrollBarWndH );

} // if( pExtScrollBarWndH != NULL && pExtScrollBarWndV != NULL )

} // end of OnSwEnableScrollBarCtrl method


 


 


---------------------- End Code Snippet ------------------------------------------------


By the way, while I really like your company and you product, your coding formtting is extremely odd.   I believe that you would save you company and your customer’s a consideral amount of time and money if you would invest in one of the many code formatters.


 

Technical Support Sep 13, 2010 - 8:57 AM

Could show the call stack listing at the crash time?