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 Tech Support » Popup menu with a submenu Collapse All
Subject Author Date
Raffaele Cappelli Jul 9, 2006 - 2:14 AM

Hello, I have found the following bug:

if you 1) show a popup menu wich has a submenu, 2) open the submenu, 3) click on a submenu item without releasing the mouse button, then 4) move the mouse outside the menu and release the mouse button, the submenu correctly disappears, but the main popup menu remains visible and "frozen".
Please let me know if you can provide a fix.

Technical Support Jul 10, 2006 - 9:19 AM

Thank you for reporting this bug. We fixed it and you can download the update from our ftp site.

Raffaele Cappelli Jul 10, 2006 - 2:56 PM

May you please post here or send me only the portion of code modified to fix the bug? I am releasing and I do not want to use and test a whole new version of the library.

Technical Support Jul 11, 2006 - 8:43 AM

Please update the following method:

bool CExtPopupMenuWnd::_OnMouseClick(
    UINT nFlags,
    CPoint point,
    bool & bNoEat
    )
{
    ASSERT_VALID( this );
    if( GetSafeHwnd() == NULL )
        return false;
CExtPopupMenuSite & _site = GetSite();
    if(    _site.IsShutdownMode()
        || _site.IsEmpty()
        || _site.GetAnimated() != NULL
        )
        return true;
TranslateMouseClickEventData_t _td( this, nFlags, point, bNoEat );
    if( _td.Notify() )
    {
        bNoEat = _td.m_bNoEat;
        return true;
    }
CPoint ptScreenClick( point );
    ClientToScreen( &ptScreenClick );
HWND hWndFromPoint = ::WindowFromPoint( ptScreenClick );
    if(       hWndFromPoint != NULL
        &&    (::GetWindowLong(hWndFromPoint,GWL_STYLE)&WS_CHILD) != 0
        &&    ::GetParent(hWndFromPoint) == m_hWnd
        )
    {
        CWnd * pWnd = CWnd::FromHandlePermanent( hWndFromPoint );
        if( pWnd != NULL )
        {
            int nCount = ItemGetCount();
            for( int i = 0; i < nCount; i++ )
            {
                MENUITEMDATA & mi = ItemGetInfo( i );
                if( !mi.IsInplaceEdit() )
                    continue;
                if( ((LPVOID)mi.GetInplaceEditPtr()) != ((LPVOID)pWnd) )
                    continue;
                if( m_nCurIndex == i )
                    break;
                HWND hWndOwn = m_hWnd;
                _ItemFocusSet( i, FALSE, TRUE, FALSE );
                if( ! ::IsWindow( hWndOwn ) )
                    return true;
                break;
            }
        }
        bNoEat = true;
        return false;
    }
bool bLButtonUpCall =
        (nFlags==WM_LBUTTONUP || nFlags==WM_NCLBUTTONUP)
            ? true : false;
    if( bLButtonUpCall && (!_PtInWndArea(point)) )
    {
        CExtPopupMenuTipWnd & _tipWnd = GetTip();
        if( _tipWnd.GetSafeHwnd() != NULL )
        {
            CPoint ptScreen( point );
            ClientToScreen( &ptScreen );
            if( _tipWnd.GetSafeHwnd() == ::WindowFromPoint(ptScreen) )
                return true;
        }
        HWND hWndOwn = GetSafeHwnd();
        ASSERT( hWndOwn != NULL );
        ASSERT( ::IsWindow(hWndOwn) );
        if(     m_pWndParentMenu != NULL
            &&  m_pWndParentMenu->GetSafeHwnd() != NULL
            )
        {
            ASSERT_VALID( m_pWndParentMenu );
            ClientToScreen( &point );
            m_pWndParentMenu->ScreenToClient( &point );
            CExtPopupMenuWnd * pWndParentMenu = m_pWndParentMenu;
            if( pWndParentMenu->_OnMouseClick(
                    nFlags,
                    point,
                    bNoEat
                    )
                )
            {
                if( bNoEat )
                    return false;
                if( ::IsWindow(hWndOwn) )
                    _OnCancelMode();
                return true;
            }
            return false;
        }
        if(     nFlags == WM_RBUTTONUP
            ||  nFlags == WM_LBUTTONUP
            )
        {
            if(       ::IsWindow(hWndOwn)
                &&    CExtToolControlBar::g_bMenuTracking
                &&    hWndFromPoint != NULL
                )
            {
                CWnd * pWndCmp =
                    CWnd::FromHandlePermanent( hWndFromPoint );
                if( pWndCmp != NULL )
                {
                    CExtToolControlBar * pToolBar =
                        DYNAMIC_DOWNCAST( CExtToolControlBar, pWndCmp );
                    if( pToolBar != NULL )
                    {
                        ASSERT_VALID( pToolBar );
                        int nBtnIdx = pToolBar->GetMenuTrackingButton();
                        if( nBtnIdx >= 0 )
                        {
                            CExtBarButton * pTBB = pToolBar->GetButton( nBtnIdx );
                            if( pTBB != NULL )
                            {
                                ASSERT_VALID( pTBB );
                                CRect rcBtn = pTBB->Rect();
                                pToolBar->ClientToScreen( &rcBtn );
                                if( rcBtn.PtInRect(ptScreenClick) )
                                    return true;
                            }
                        }
                    }
                }
                _OnCancelMode();
            }
            return true;
        }
        _OnCancelMode();
        return false;
    }
bool bInplaceControlArea = false, bInplaceDropDownArea = false;
int nHitTest =
        _HitTest(
            point,
            &bInplaceControlArea,
            &bInplaceDropDownArea
            );
    if( _IsTearOff() && nHitTest == IDX_TEAROFF )
    {
        bool bLButtonUpCall =
            ( nFlags==WM_LBUTTONUP || nFlags==WM_NCLBUTTONUP )
                ? true : false;
        if( ! bLButtonUpCall )
            _DoTearOff();
        return true;
    }
    if( bLButtonUpCall )
    {
        HWND hWndOwn = m_hWnd;
        if( _StartScrolling( nHitTest ) )
            return true;
        if( ! ::IsWindow( hWndOwn ) )
            return true;
    }
    if( nHitTest < 0 )
    {
        if( bLButtonUpCall )
        {
            if(     (  nHitTest == IDX_SCROLL_TOP
                    || nHitTest == IDX_SCROLL_BOTTOM )
                )
            {
                return true;
            }
            if( nHitTest == IDX_EXPAND )
            {
                if(      ( ! m_bExpandWasPressed )
                    &&   m_bExpandAvailable
                    )
                    _DoExpand();
                return true;
            }
            if(     nFlags != WM_RBUTTONUP
                &&  nFlags != WM_LBUTTONUP
                )
            {
                _OnCancelMode();
                return true;
            }
        }
        if(      m_eCombineAlign != __CMBA_NONE
            &&   m_bTopLevel
            &&   ( ! bLButtonUpCall )
            )
        {
            CRect rcExcludeAreaTest( m_rcExcludeArea );
            ScreenToClient( &rcExcludeAreaTest );
            if( rcExcludeAreaTest.PtInRect( point ) )
            {
                _OnCancelMode();
                return true;
            }
        }
        if(     nFlags != WM_LBUTTONUP
            &&  nFlags != WM_LBUTTONDOWN
            &&  nFlags != WM_NCLBUTTONUP
            &&  nFlags != WM_NCLBUTTONDOWN
            &&  nFlags != WM_RBUTTONDOWN
            &&  nFlags != WM_NCRBUTTONDOWN
            &&  nFlags != WM_MBUTTONDOWN
            &&  nFlags != WM_NCMBUTTONDOWN
            )
        {
            bNoEat = false;
            return true;
        }
        return false;
    }
    ASSERT( nHitTest < m_items_all.GetSize() );
    if( !bLButtonUpCall )
        return true;
MENUITEMDATA & mi = ItemGetInfo(nHitTest);
    if( ( ! mi.IsEnabled() ) || mi.IsSeparator() )
    {
        _ItemFocusCancel( TRUE );
        _SetCapture();
        return true;
    }
    if(      mi.IsInplaceEdit()
        &&   mi.IsPopup()
        &&   (! mi.IsAllowInplaceEditActivation() )
        )
    {
        bInplaceControlArea = false;
        bInplaceDropDownArea = true;
    }
    if(      mi.IsInplaceEdit()
        &&   (! mi.IsPopup() )
        &&   (! bInplaceDropDownArea )
        &&   (! _FindHelpMode() )
        )
    {
        _SetCapture();
        HWND hWndOwn = m_hWnd;
        _ItemFocusSet( nHitTest, FALSE, TRUE, FALSE );
        if( ! ::IsWindow( hWndOwn ) )
            return true;
        CWnd * pWndInplace = mi.GetInplaceEditPtr();
        if( pWndInplace != NULL )
        {
            ASSERT_VALID( pWndInplace );
            ASSERT( pWndInplace->GetSafeHwnd() != NULL && (::IsWindow(pWndInplace->GetSafeHwnd())) );
            if( mi.IsAllowInplaceEditActivation() )
            {
                if( (pWndInplace->GetStyle() & WS_VISIBLE) == 0 )
                {
                    CRect rcInplaceEdit;
                    _GetItemRect( nHitTest, rcInplaceEdit );
                    rcInplaceEdit =
                        mi.AdjustInplaceEditRect(
                            rcInplaceEdit,
                            OnQueryLayoutRTL()
                            );
                    pWndInplace->SetWindowPos(
                        NULL,
                        rcInplaceEdit.left, rcInplaceEdit.top,
                        rcInplaceEdit.Width(), rcInplaceEdit.Height(),
                        SWP_NOZORDER|SWP_NOOWNERZORDER
                            |SWP_NOACTIVATE|SWP_SHOWWINDOW
                        );
                }
                pWndInplace->SetFocus();
            }
        }
        return true;
    }
    if( mi.IsPopup() )
    {
        bool bPopupOpened = false;
        if( mi.GetPopup()->GetSafeHwnd() != NULL )
            bPopupOpened = true;
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
        if( (!bPopupOpened) && mi.IsInplaceEdit() && _FindHelpMode() )
        {
            CExtCustomizeCmdTreeNode * pNode = mi.GetCmdNode();
            if( pNode != NULL )
                _EndSequence(
                    pNode->GetCmdID( false ),
                    mi.GetCmdReceiver()
                    );
        }
#endif
        if( ( ! bPopupOpened ) && mi.IsInplaceEdit() && bInplaceDropDownArea )
        {
            HWND hWndOwn = m_hWnd;
            _ItemFocusCancel( FALSE );
            if( ! ::IsWindow( hWndOwn ) )
                return true;
        }
        bool bContinueAsCommand = false;
        {
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
            bool bSeparatedDropDown = false;
            const CExtCustomizeCmdTreeNode * pNode = mi.GetCmdNode();
            if( pNode != NULL )
            {
                ASSERT_VALID( pNode );
                bSeparatedDropDown =
                    (pNode->GetFlags() & __ECTN_TBB_SEPARATED_DROPDOWN)
                        ? true : false;
            }
            if( bSeparatedDropDown )
            {
                CRect rcItem;
                _GetItemRect( nHitTest, rcItem );
                CRect rcPopupArrow( rcItem );
                rcPopupArrow.left =
                    rcPopupArrow.right - __EXT_MENU_POPUP_ARROW_AREA_DX;
                ClientToScreen( &rcPopupArrow );
                if( ! rcPopupArrow.PtInRect( ptScreenClick ) )
                    bContinueAsCommand = true;
            }
            else
#endif
                if( ! bPopupOpened )
                {
                    HWND hWndOwn = m_hWnd;
                    _ItemFocusSet(
                        nHitTest,
                        TRUE,
                        TRUE,
                        FALSE
                        );
                    if( ! ::IsWindow( hWndOwn ) )
                        return true;
                }
                else
                    return false;
        }
        if( ! bContinueAsCommand )
            return true;
    }
    if( mi.IsExtraMark() && ( ! _FindHelpMode() ) )
    {
        ASSERT( mi.GetExtraMarkCallback() != NULL );
        mi.GetExtraMarkCallback()( this, &mi );
        CClientDC dc( this );
        _DoPaint( dc );
    }
    else if(
              mi.IsExecutableCmdID()
        ||    (    mi.IsPopup()
#if (!defined __EXT_MFC_NO_CUSTOMIZE)
            &&    mi.GetCmdNode() != NULL
            &&    (mi.GetCmdNode()->GetFlags()&__ECTN_TBB_SEPARATED_DROPDOWN) != 0
            &&    (mi.GetCmdNode()->GetFlags()&(__ECTN_TBB_COLOR|__ECTN_TBB_UNDO_REDO|__ECTN_TBB_DATE)) != 0
#else
            &&    (    mi.GetPopup()->IsKindOf( RUNTIME_CLASS( CExtPopupColorMenuWnd ) )
#if (!defined __EXT_MFC_NO_UNDO_REDO_POPUP)
                ||    mi.GetPopup()->IsKindOf( RUNTIME_CLASS( CExtPopupUndoRedoMenuWnd ) )
#endif
#if (!defined __EXT_MFC_NO_DATE_PICKER_POPUP)
                ||    mi.GetPopup()->IsKindOf( RUNTIME_CLASS( CExtPopupDatePickerMenuWnd ) )
#endif
                )
#endif
            )
        )
    {
        if(  !  (        mi.GetCmdDeliverCb() != NULL
                &&    mi.GetCmdDeliverCb()( this, &mi )
                )
            )
            _EndSequenceEx( mi );
    }
    else
        _OnCancelMode();
    return true;
}

Raffaele Cappelli Jul 11, 2006 - 2:26 PM

The above code does not fix the bug.

Raffaele Cappelli Jul 11, 2006 - 2:36 PM

I think the problem is that m_pWndParentMenu->_SetCapture() needs to be called after canceling the submenu, or the parent menu will remain "frozen" until it is canceled too, for instance when you deactivate/activate the main window.

Technical Support Jul 12, 2006 - 10:25 AM

Please let us know how to reproduce the bug with any of Prof-UIS samples. Of course, we assume you have updated the method’s source code we provided in our previous message.