Probleme mit CMenu

jokey2

Erfahrenes Mitglied
Hallo Gemeinde!

Ich habe ein Hauptmenü, in dem ich ein Untermenü dynamisch anpassen will, je nach einer bestimmten Auswahl. Das klappt ja auch soweit, es werden dynamisch Menüpunkte hinzugefügt oder gelöscht. Nun möchte ich aber auch, daß je nach Status der Auswahl ein oder mehrere dieser dynamisch erzeugten Menüpunkte aktiviert oder deaktiviert (grau) ist. Das versuche ich mit folgendem Code:
Code:
if(m_pDoc->m_pActiveFile->IsProcessable())
   	pSubMenu->AppendMenu(MF_STRING | MF_ENABLED, ID_COMPILE_OBJECT, cstrMenuText);
    else
 	 pSubMenu->AppendMenu(MF_STRING | MF_DISABLED | MF_GRAYED, ID_COMPILE_OBJECT, cstrMenuText);
Das Problem ist, auch wenn der else-Zweig durchlaufen wird, ist der Menüpunkt aktiv. Was mache ich da falsch?
 
Hmm, kann sein, dass dir da MFC mit seinem CmdUI-Handler dazwischenfunkt. Du könntest dir für deine dynamischen Menüpunkte einen OnCmdUI-Handler anlegen lassen und dort das Ein-/Ausgrauen übernehmen.

Oder auf CMenu verzichten und das ganze direkt in Win32-API machen (CreatePopupMenu usw.). Dadurch umgehst du das MFC-Framework.
 
Danke für den Tip, hat aber auch nicht funktioniert. Das Ganze verhält sich etwas merkwürdig. Ich hab's jetzt erstmal so gelöst, das die Items, die grau dargestellt worden wären, erst gar nicht angelegt werden. Das geht nämlich. Nur mit dem Enablen/Disablen gibt's Probleme.
 
Ich habe immer noch ein Problem mit diesem besc........ Menü!
Ich habe meinen MainFrame mit 2 Splittern in 3 Bereiche aufgeteilt. Ich nenne sie CLeftView(CTreeView), CRightView (CFormView; davon gibt es mehrere abgeleitete Views, die ausgetauscht werden, je nach Auswahl im LeftView) und CBottomView(CFormView mit einem Richedit-Control). Wenn der Fokus nun nicht im LeftView ist, dann sind die Untermenüpunkte von 2 Hauptmenüpunkten grau und deaktiviert.
Die Behandlungsroutinen (OnCommand...) dieser Untermenüpunkte liegen im CLeftView. Es muß wohl daran liegen, daß die Menüpunkte grau gemacht werden (vermute ich, bitte korrigieren, wenn ich da falsch liege), aber wo und warum? Und vor Allem: wie kann ich das abstellen (möglichst ohne die ganzen Routinen in CMainFrame verlagern zu müssen!)?
 
Blöde Frage, die IDs die du für die dynamisch addierten Menüpunkte nimmst, gibt es die für andere Punkte oder sind das "freie" IDs (bzw. selbst angelegte).

MFC hat nämlich die dumme Eigenschaft beim Öffnen eines Menüs alle Menü-Einträge, die keinen Handler haben, ebenfalls einzugrauen (was für statische Menüs ja auch Sinn macht, nicht aber bei dynamischen Menüs).
Deshalb mache ich dynamische Menüs immer über CreatePopupMenu/TrackPopupMenu selbst. Dann kann mir MFC nicht reinpfuschen.
 
Ich habe mir statische Dummy-Menüpunkte angelegt, die diese ID's haben und dann auch über den Kalssenassistenten die Handler angelegt. Die waran ja da. Aber das Framework hat die Menüpunkte deaktiviert, wenn das View, in dem die Handler implementiert waren, nicht den Fokus hatte.
Ich habe jetzt doch alle Handler des Hauptmenüs in den MainFrame verlegt, jetzt klappt alles. Wenn mir allerdings einer sagen könnte, wo diese automatische Deaktivierung stattfindet und wie man sie abschalten kann, wäre ich sehr dankbar. Es ist manchmal doch etwas kompliziert, da ich dann Funktionen, die ich eigentlich protected haben wollte, jetzt public machen mußte.
 
Da ich nicht ganz auf dynamische Menüpunkte verzichten wollte, nur weil ich MFC verwende, und auch nicht mein komplettes Menü umstellen wollte habe ich noch etwas rumgesucht und habe Folgendes rausgefunden:
Wenn man MFC verwendet und dynamisch Menüpunkte erstellt, werden die beim Programmstart ausgegraut, da kein Handler dafür existiert (wie Endurion schon gesagt hat). Man kann aber per Hand einen Handler ON_COMMAND_RANGE erstellen, dem man die untere und die obere ID für die dynamischen Menüpunkte übergibt, sowie eine Funktion, die dann aufgerufen wird. Diese Funktion hat einen Parameter, der die ID enthält. Sie wird immer aufgerufen, wenn ein Menüpunkt mit einer ID im angegebenen Bereich angeklickt wird. So existiert dann ein Handler für die ID's und sie werden nicht automatisch ausgegraut.

Hier noch etwas Beispielcode:

MainFrame.cpp:
Code:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
    //{{AFX_MSG_MAP(CMainFrame)
...
    //}}AFX_MSG_MAP
ON_COMMAND_RANGE(ID_MENU_DYNAMIC_START, 0xFFFF, OnCommandRange)
END_MESSAGE_MAP()

...

void CMainFrame::OnCommandRange(UINT iID) 
{
    ...
}
MainFrame.h:
Code:
// Generierte Message-Map-Funktionen
protected:
    //{{AFX_MSG(CMainFrame)
    ...
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
    afx_msg void OnCommandRange(UINT iID);
Beachten: Die Funktionsdeklaration nach DECLARE_MESSAGE_MAP() einfügen!
 
Hab' noch was rausgefunden:
CFrameWnd hat die Membervariable 'm_bAutoMenuEnable'. Wenn diese Variable TRUE ist, dann werden die Menüpunkte je nach Vorhandensein eines Commandhandlers ausgegraut oder nicht. Ist sie FALSE, geschieht das nicht, d.h. sie behalten ihren Anfangsstatus bei.
Wenn man also vermeiden will, daß die Menüs ausgegraut sind, nur weil kein Commandhandler da ist, setzt man diese Variable im Konstruktor auf FALSE.
Hab's allerdings noch nicht selber getestet, aber so steht's im MSDN.
 
Zurück