![]() |
Context menu tracking when Skinning |
Post Reply
|
| Author | |
rdhd
Senior Member
Joined: 13 August 2007 Location: United States Status: Offline Points: 985 |
Post Options
Thanks(0)
Quote Reply
Topic: Context menu tracking when SkinningPosted: 3 hours 49 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.
|
|
![]() |
|
rdhd
Senior Member
Joined: 13 August 2007 Location: United States Status: Offline Points: 985 |
Post Options
Thanks(0)
Quote Reply
Posted: 3 hours 34 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.
|
|
![]() |
|
Post Reply
|
|
|
Tweet
|
| Forum Jump | Forum Permissions ![]() You cannot post new topics in this forum You cannot reply to topics in this forum You cannot delete your posts in this forum You cannot edit your posts in this forum You cannot create polls in this forum You cannot vote in polls in this forum |