Codejock Forums Homepage
Forum Home Forum Home > Codejock Products > Visual C++ MFC > Skin Framework
  New Posts New Posts RSS Feed - Context menu tracking when Skinning
  FAQ FAQ  Forum Search   Events   Register Register  Login Login

Context menu tracking when Skinning

 Post Reply Post Reply
Author
Message
rdhd View Drop Down
Senior Member
Senior Member
Avatar

Joined: 13 August 2007
Location: United States
Status: Offline
Points: 985
Post Options Post Options   Thanks (0) Thanks(0)   Quote rdhd Quote  Post ReplyReply Direct Link To This Post Topic: Context menu tracking when Skinning
    Posted: 4 hours 38 minutes ago at 1:18pm
I found that when I have a skin applied and I do a right click on a control on some of our popups the context menu I track causes the popup to dismiss. To fix that I found I could pass in TPM_RECURSE when tracking the popup menu. That keeps CJ from closing the popup. Unfortunately it also lets CJ track the mouse wrt the popup as well as the context menu (popup itself). Well sort of. The context menu items don't highlight as I move over them though the items on the popup below it do. When I click a context menu item I do get the command ID back.

Not a fan of my work-around which is described and implemented as:

            // 12/22/25: RDH PR 11388058. This code was changed to call the frame window so the menu displays a Dark
            // theme. That api routes through Codejock's CXTPCommandBars::TrackPopupMenu, which calls
            // XTPMouseManager::SendTrackLost on entry. SendTrackLost walks CXTPMouseManager::m_arrTracked calling
            // OnTrackLost, which ends tracking mode on the MRUPopupBar and closes the vertical MRU out from under us.
            //
            // 8/31/26 RDH: That was originally worked around by passing TPM_RECURSE, because Codejock skips
            // SendTrackLost when that flag is set. But TPM_RECURSE does not mean "leave my popup alone" - it also
            // calls LockTrackRecurse(TRUE), which bumps m_nLockRecurse on EVERY bar already being tracked, and
            // m_nLockRecurse is the flag that gates all hot tracking (CXTPPopupBar::OnMouseMove,
            // CXTPCommandBar::OnMouseMove and OnMouseLeave, the hover timers, CXTPMouseManager::DeliverMessage).
            // The result was a context menu whose items never highlighted, and stale highlights left lit on the MRU
            // items underneath because nothing was allowed to clear them.
            //
            // Removing just our own bar from the tracked array is not enough, and it is worth knowing why. An
            // MRUPopupBar is a CXTPRibbonSystemPopupBarPage, that is, a page of the system menu popup that spawned
            // it, and that parent bar is tracked too. SendTrackLost calls OnTrackLost on the parent, the parent
            // closes its child popups, and ours goes down with it however carefully we detached it. That is exactly
            // what TPM_RECURSE was papering over by locking the whole array rather than one entry.
            //
            // So do what TPM_RECURSE did, minus the freeze: lift the entire tracked array out for the duration of
            // the call and put it back afterwards. SendTrackLost then has nothing to walk and is a no op, every
            // bar keeps its tracking mode, and because nobody gets m_nLockRecurse set the context menu hot tracks
            // normally. The bars are restored in their original order, since SetTrack appends.
            //
            //
            // Do not try to solve this by vetoing dismissal in MRUPopupBar::SetTrackingMode instead. SendTrackLost
            // is "while (m_arrTracked.GetSize() > 0) m_arrTracked[0]->OnTrackLost();" - a veto that stops a bar
            // being removed from the array hangs the thread.
            CXTPCommandBar*   pOwningBar     = DYNAMIC_DOWNCAST(MRUPopupBar, GetParent());
            CXTPMouseManager* pMouseManager  = XTPMouseManager();

            std::vector<CXTPCommandBar*> vecSuspendedBars;

            if(pOwningBar && pMouseManager)
            {
                CXTPMouseManager::CTrackArray& arrTracked = pMouseManager->GetTrackArray();

                for(int i = 0; i < (int)arrTracked.GetSize(); i++)
                {
                    vecSuspendedBars.push_back(arrTracked[i]);
                }

                for(size_t i = 0; i < vecSuspendedBars.size(); i++)
                {
                    pMouseManager->RemoveTrack(vecSuspendedBars[i]);
                }
            }

            BOOL item = pFrameWnd->TrackPopupMenu(subMenu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_LEFTBUTTON, point.x, point.y, this, nullptr, JNone, hInstance);

            for(size_t i = 0; i < vecSuspendedBars.size(); i++)
            {
                // The window can be gone if a command tore the bar down while the menu was up.
                if(::IsWindow(vecSuspendedBars[i]->GetSafeHwnd()))
                {
                    pMouseManager->SetTrack(vecSuspendedBars[i], FALSE);
                }
            }

As I noted before the code related to suspending and resuming tracking I made to keep the popup displayed when a skin was applied was to add TPM_RECUSE to the flags passed in. I did not determine why a skin being applied caused the dismissal and no skin applied kept the popup from being dismissed when tracking the context menu on an item in that popup. The above code now keeps the popup from being dismissed while allowing correct tracking on the item I am showing the context menu for.
Back to Top
rdhd View Drop Down
Senior Member
Senior Member
Avatar

Joined: 13 August 2007
Location: United States
Status: Offline
Points: 985
Post Options Post Options   Thanks (0) Thanks(0)   Quote rdhd Quote  Post ReplyReply Direct Link To This Post Posted: 4 hours 23 minutes ago at 1:33pm
Mea cupla. It wasn't skinning that caused the dismissal. It was the fact that I had to use CJ TrackPopupMenu to get the skin applied to the context menu. We have the code here being used in cases where we don't have a popup displaying the item for which we are showing the context menu.

So I guess the work-around I have though seemingly a bit dangerous (subject to CJ changes over time ...) is probably the best I can do.
Back to Top
 Post Reply Post Reply
  Share Topic   

Forum Jump Forum Permissions View Drop Down

Forum Software by Web Wiz Forums® version 12.04
Copyright ©2001-2021 Web Wiz Ltd.

This page was generated in 0.500 seconds.