2010-07-28 3 views
2

J'ai un CMFCRibbonUndoButton sur le ruban d'une application MFC. J'ai un gestionnaire pour quand son ID est cliqué (ON_COMMAND(ID_EDIT_UNDO, ...)). Toutefois, lorsque le bouton est également dans la barre d'outils d'accès rapide (QAT), il existe apparemment deux CMFCRubbonUndoButtons qui conservent chacun leur propre état. Dans le gestionnaire de commandes, je ne sais pas comment dire lequel a été cliqué, et si vous appelez GetActionNumber() sur le mauvais, vous obtenez le mauvais nombre d'actions d'annulation retournées.MFC Ribbon - Obtention de l'élément de base à partir de la commande

Y a-t-il un moyen dans mon gestionnaire ON_COMMAND pour obtenir le CMFCRibbonBaseElement* qui a déclenché l'événement? Edit: la réponse est importante pour moi, la question est un peu obscure mais je mets une prime!

Edit: voici comment il est ajouté à la QAT:

CList<UINT, UINT> lstQATCmds; 
lstQATCmds.AddTail(ID_EDIT_UNDO); 
m_RibbonBar.SetQuickAccessCommands(lstQATCmds); 
+0

Pourriez-vous donner un exemple d'ajout du bouton Annuler au QAT? Je n'ai pas travaillé avec MFC depuis un moment, mais il semble très étrange qu'il ne garderait pas l'état cohérent entre les boutons. –

+0

Ajout du code que j'utilise, les boutons sont ajoutés au QAT par ID. Il est basé sur l'exemple de code. – AshleysBrain

+0

Voulez-vous que les deux boutons d'annulation affichent la même liste d'éléments d'annulation?Dans mon application de test, je peux appeler AddUndoAction pour ajouter des éléments au bouton Annuler dans le ruban, mais ces éléments n'apparaissent pas dans le bouton Annuler de la barre d'outils d'accès rapide. J'ai jeté un oeil à travers le code source MFC, et il semble que la solution à votre problème ne sera pas simple. – ChrisN

Répondre

1

Est-il possible dans mon ON_COMMAND gestionnaire pour obtenir le CMFCRibbonBaseElement* qui a déclenché l'événement?

Pas directement, non. Le message WM_COMMAND est envoyé à partir de CMFCRibbonBaseElement::NotifyCommand et ce message n'inclut pas le pointeur dans ses paramètres.

Pour savoir quel bouton Annuler a été cliqué à partir du gestionnaire ON_COMMAND, j'ai écrit cette classe, qui hérite de CMFCRibbonUndoButton. Ce que fait ce code est de stocker un pointeur sur le dernier bouton Annuler à chaque fois que l'un des boutons est cliqué, ou que le menu contextuel est activé.

// CMyMFCRibbonUndoButton.h 

class CMyMFCRibbonUndoButton : public CMFCRibbonUndoButton 
{ 
    DECLARE_DYNCREATE(CMyMFCRibbonUndoButton) 

public: 
    CMyMFCRibbonUndoButton(); 
    CMyMFCRibbonUndoButton(UINT nID, LPCTSTR lpszText, 
     int nSmallImageIndex = -1, int nLargeImageIndex = -1); 

    virtual void OnClick(CPoint point); 
    virtual void OnShowPopupMenu(); 

    static CMyMFCRibbonUndoButton* GetLastActivated(); 

private: 
    static CMyMFCRibbonUndoButton* s_pLastActivated; 
}; 

// CMyMFCRibbonUndoButton.cpp 

IMPLEMENT_DYNCREATE(CMyMFCRibbonUndoButton, CMFCRibbonUndoButton) 

CMyMFCRibbonUndoButton* CMyMFCRibbonUndoButton::s_pLastActivated = NULL; 

CMyMFCRibbonUndoButton::CMyMFCRibbonUndoButton() 
{ 
} 

CMyMFCRibbonUndoButton::CMyMFCRibbonUndoButton(UINT nID, LPCTSTR lpszText, 
    int nSmallImageIndex, int nLargeImageIndex) : 
    CMFCRibbonUndoButton(nID, lpszText, nSmallImageIndex, nLargeImageIndex) 
{ 
} 

void CMyMFCRibbonUndoButton::OnClick(CPoint point) 
{ 
    s_pLastActivated = this; 
    CMFCRibbonUndoButton::OnClick(point); 
} 

void CMyMFCRibbonUndoButton::OnShowPopupMenu() 
{ 
    s_pLastActivated = this; 
    CMFCRibbonUndoButton::OnShowPopupMenu(); 
} 

CMyMFCRibbonUndoButton* CMyMFCRibbonUndoButton::GetLastActivated() 
{ 
    return s_pLastActivated; 
} 

Utilisez cette classe à la place de CMFCRibbonUndoButton lorsque votre barre initialisant de ruban. Dans la fonction de gestionnaire, appelez GetLastActivated() pour récupérer ce pointeur, par exemple:

void CMyTestDoc::OnEditUndo() 
{ 
    CMyMFCRibbonUndoButton* pUndoButton = 
     CMyMFCRibbonUndoButton::GetLastActivated(); 

    ASSERT_VALID(pUndoButton); 

    if (pUndoButton != NULL) 
    { 
     int ActionNumber = pUndoButton->GetActionNumber(); 
     // etc. 
    } 
} 

C'est un peu un hack, certes, mais il était la seule façon que je pouvais trouver pour résoudre le problème.

Quoi qu'il en soit, j'espère que cela aide,

Chris

+0

Merci, mais lorsque MFC clone le bouton Annuler dans les coulisses, il crée un CMFCRibbonUndoButton ordinaire - pas la classe dérivée, donc il ne met jamais à jour 's_pLastActivated' du bouton QAT! – AshleysBrain

+0

Intéressant, ce code fonctionne bien dans mon application de test, et lorsque MFC clone le bouton, il crée un objet 'CMyMFCRibbonUndoButton'. MFC appelle 'GetRuntimeClass() -> CreateObject()' sur le bouton, il doit donc créer un objet de la bonne classe. – ChrisN

+0

Ah - J'ai dû manquer quelque chose - je vais essayer à nouveau. – AshleysBrain

0

Jetez un oeil à la MSOffice2007Demo dans le Visual C++ 2008 Feature Pack examples

Ils utilisent une technique différente où ils emprisonnent un message enregistré (AFX_WM_ON_BEFORE_SHOW_RIBBON_ITEM_MENU) dans ce gestionnaire ils reconstruisent dynamiquement la liste d'annulation (similaire à l'ancienne gestion du SDK WM_INITMENUPOPUP).

Le CMFCRibbonUndoButton qui a provoqué le message est transmis dans la partition logique du message.

En utilisant cette technique, vous conservez votre liste d'annulation indépendamment des commandes du ruban et utilisez le contrôle comme vue dans votre liste.

Questions connexes