2009-05-13 10 views
7

Imaginez que j'ai un CDialog qui crée des contrôles dynamiquement lorsque l'utilisateur clique sur un bouton. Cela pourrait être comme ceci:Comment gérer les messages provenant de contrôles créés dynamiquement dans une application MFC?

// We don't know which is the first id for the new buttons until runtime (!) 
MyDialog::MyDialog(/*whatever parameters needed*/, first_id) 
    : next_id_(first_id) 
{ /*...*/ } 

BOOL MyDialog::OnSomeButtonClicked() 
{ 
    CButton* new_button = new CButton; 
    new_button->Create("Caption", WS_CHILD | WS_VISIBLE, this->new_button_rect_, 
        this, this->next_id_++); 
} 

Puis ma question serait: Comment pourrais-je gérer les messages de ce bouton? Est-il possible d'utiliser la fonction de carte de message MFC?

La solution devrait fonctionner dans vs6 et vs2005.

Merci!

Répondre

6

Ce sont les solutions que j'ai trouvé jusqu'à présent ordre de pertinence:

  1. Utilisez ON_COMMAND_RANGE si vous pouvez définir la plage des ID de contrôle que vous souhaitez gérer. Surcharge CWnd::PreTranslateMessage() et faites tout ce que vous voulez avec les messages reçus. REMARQUE: lorsque vous manipulez des boutons, tenez compte du fait que l'événement BN_CLICKED n'est PAS envoyé à PreTranslateMessage mais directement à la procédure de fenêtre.

  2. Surcharge CWnd::WindowProc() et faites ce que vous voulez avec les messages reçus. Notez que lorsque vous manipulez des boutons, c'est le SEUL moyen que j'ai trouvé pour gérer l'événement BN_CLICKED.

Liens intéressants:

J'espère que cette aide ... Merci à tous pour vos contributions.

0

Je crois que cet article explique assez bien et a le code source. Je n'ai pas essayé cela donc je ne peux pas garantir que cela fonctionne, mais dans le temps j'ai pensé que cela pourrait aider.

Article

+0

Ok, il est sans doute bon d'utiliser PreTranslateMessage pour ce genre de choses, mais je continue à se demander s'il y a un moyen d'utiliser l'installation de carte du message mfc: S –

5

Eventhough vous ne savez pas les valeurs exactes de l'identifiant, si vous connaissez la gamme possible d'ID la macro suivante peut être utilisée.

BEGIN_MESSAGE_MAP(MyDialog, CDialog) 
    ... 
    ... 
    ON_COMMAND_RANGE(1000, 5000, OnButtonDynamic) 
END_MESSAGE_MAP() 


void MyDialog::OnButtonDynamic(UINT nID) 
{ 

} 

Cela fonctionne pour ids dans la gamme 1000 - 5000.

+0

Uhm, merci pour la réponse, mais comment pourrais-je connaître la gamme à l'avance? –

0

Vous trouverez tous les détails (+ beaucoup plus) sur les boîtes de dialogue modales there.

+0

Je pense que c'est assez sans rapport: S –

0

insérer l'entrée d'ID du gestionnaire dans Resouce.h Ensuite, insérez l'entrée dans la carte du message du gestionnaire comme ON_BN_CLICKED (IDC_BTNCREATE, OnBnClickedrunCreated) ou vous pouvez directement utiliser l'ID entier comme ON_BN_CLICKED (1200, OnBnClickedrunCreated). Si vous utilisez la 2ème version, alors il n'y a pas besoin d'insérer une entrée dans resource.h . Donner la définition et la déclaration du gestionnaire dans les fichiers .h et .cpp. vous obtiendrez votre réponse.

2

J'ai quelques années de retard pour cette fête, mais la solution est d'assigner le même identifiant de contrôle à chaque bouton (pas besoin de 'réserver' les ID dans la ressource.h, et aucune restriction artificielle sur la quantité de contrôles qui peuvent être créés) pour enregistrer la poignée de fenêtre et d'utiliser GetCurrentMessage() dans le gestionnaire pour ce bouton:

// resource.h 
#define IDC_DYNAMIC_BUTTON 123 

// In message map 
ON_BN_CLICKED(IDC_DYNAMIC_BUTTON, OnDynamicButtonClicked) 

// Store the window handles when creating them in a member: 
std::map<HWND, SomeStruct> m_Buttons; 
... fill this map when creating the buttons, presumably in OnInitDialog() 

// Actual handler 
void MyDialog::OnDynamicButtonClicked() 
{ 
    const MSG* message = GetCurrentMessage(); 

    if (m_Buttons.find((HWND)message->lParam) != m_Buttons.end()) { 
     // Do something with m_Buttons[(HWND)message->lParam] 
    } 
} 
0

Utilisez cette technique: ON_CONTROL_RANGE (wNotifyCode, id1, id2, memberFxn). par exemple:

ON_CONTROL_RANGE(EN_UPDATE, IDC_EDIT_START, IDC_EDIT_END, OnEnUpdateEditParams)