[Menüleiste] Callbacks werden nicht immer ausgeführt


  • Mod

    Dann schau mal in die resource.h rein ob evtl. zwei unterschiedliche Symbole die selbe ID haben!
    Bzgl. MDI Nein: Fenster



  • Hallo Martin,

    Symbole mit gleicher ID sind in der Resource.h nicht vorhanden.

    Dass die geöffneten MDI-Fenster unter den File-Menüpunkt gehängt werden ist aber doch auch nicht korrekt. Ist das vielleicht ein Anhaltspunkt der die Fehlersuche vereinfachen könnte?


  • Mod

    Du kannst einfach mal den Debugger benutzten und OnCmdMsg in Deinem CMainFrame durch debuggen, wenn die ID angeklickt wird.
    CMDIFRame::OnCmdMsg ist verantwortlich für das Routing des Commands.

    Ansonsten schau in CMDIFrameWnd::GetWindowMenuPopup.
    Das Menü, das ein Command Id nID >= AFX_IDM_WINDOW_FIRST && nID <= AFX_IDM_WINDOW_LAST hat ist das Fenster Menü.

    Ich würde mal sagen Deine gesamten IDs sind etwas durcheinander.

    Anmerkung:
    #define AFX_IDM_WINDOW_FIRST 0xE130
    #define AFX_IDM_WINDOW_LAST 0xE13F

    Dir ist auch klar, dass es resevierte ID Bereiche gibt? (siehe TN).



  • Hallo Martin,

    ich habe OnCmdMsg() in der MainFrame-Klasse überladen, allerdings fällt es mir schwer das Anklicken der ID abzufangen, da der Breakpoint bereits erreicht wird, wenn ich den Menüpunkt File anklicke, und ich somit garnicht mehr dazu komme, den Menü-Unterpunkt Workspace anzuklicken.


  • Mod

    Du kannst doch den Breakpoint so setzen, dass er nur bei der ID zuschlägt. Zudem hättest Du das nicht überladen brauchen.

    Du kanst auch im MFC Source Code einen BP setzen.



  • Hallo Martin,

    der Code der überladenen OnCmdMsg()-Methode sieht so aus:

    BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void *pExtra, AFX_CMDHANDLERINFO *pHandlerInfo)
    {
    	if (nID == ID_VUE_WORKSPACE)
    		__super::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
    
    	return TRUE;
    }
    

    Wobei ID_VUE_WORKSPACE die vom Resourcen-Editor vergebene ID des Untermenüpunktes Workspace ist. Setze ich den Breakpoint in den if-Block, dann wird der Breakpoint allerdings schon erreicht, sobald ich in der Menüleiste auf File klicke.


  • Mod

    Das ist korrekt. Denn in diesem Fall wird der OnUpdate Handler gesucht.
    Schau mal die die Doku an zu OnCmdMsg
    Wenn DU nur das Command Debuggen möchtest ist nCode CN_COMMAND!



  • Hallo Martin,

    wenn ich das if-Statement folgendermaßen ändere:

    if (nID == ID_VUE_WORKSPACE && nCode == CN_COMMAND)
    {
        ...
    }
    

    wird der Breakpoint nach wie vor schon beim Klick auf File erreicht.


  • Mod

    Komisch. Ist ja auch wurscht. Debugge in die Funktion und schau noch wo der Handler das UI enabled.
    Den er findet ja einen Handler.



  • Hallo Martin,

    vielen Dank für die geduldige Hilfe. Das Debuggen der OnCmdMsg-Nachrichtenkette hat den Fehler offenbart.


  • Mod

    Und hatte ich Recht?
    War doch ein Handler drin?



  • Hallo Martin,

    ja, Dein Tipp war richtig. Allerdings war es nicht ganz so einfach herauszufinden, weil Teile der GUI und deren Callbacks generisch über XML-Dateien erzeugt werden.



  • Hallo Community,

    ich bin's nochmal. Leider besteht nach wie vor das Problem, dass die Liste der geöffneten MDI-Fenster unter den ersten Menüpunkt gehängt wird.
    Laut Internet-Recherche soll eine mögliche Lösung darin liegen, die Funktion GetWindowMenuPopup() der Klasse CMDIFrameWnd zu überschreiben. Jetzt habe ich beim Debuggen festgestellt, dass weder die überschriebene, noch die Funktion der Basisklasse aufgerufen werden, wenn im Menü navigiert wird.

    Für Ideen und Hinweise bin ich, wie immer, dankbar.

    [edit]

    Offenbar wird die Funktion nicht automatisch aufgerufen, das geschieht jetzt allerdings durch einen expliziten Aufruf:

    CMenu* menubar = GetMenu();
    CMenu* wmenu = CMenu::FromHandle(GetWindowMenuPopup(menubar->GetSafeHmenu()));
    

    Nach diesem Aufruf ist wmenu == NULL, trotzdem werden die aktiven MDI-Fenster eingehängt.

    [/edit]

    Freundliche Grüße,

    Jas


  • Mod

    Du sollst das icht überschreiben.
    Hier nochmal was ich geschrieben habe:

    Ansonsten schau in CMDIFrameWnd::GetWindowMenuPopup.
    Das Menü, das ein Command Id nID >= AFX_IDM_WINDOW_FIRST && nID <= AFX_IDM_WINDOW_LAST hat ist das Fenster Menü.

    Ich würde mal sagen Deine gesamten IDs sind etwas durcheinander.

    Anmerkung:
    #define AFX_IDM_WINDOW_FIRST 0xE130
    #define AFX_IDM_WINDOW_LAST 0xE13F

    Dir ist auch klar, dass es resevierte ID Bereiche gibt? (siehe TN).

    Du benötigst einen DummyEintrag in dem fenster Menü.



  • Hallo Martin,

    ich habe den expliziten Aufruf der Funktion wieder heraus genommen.

    Wenn ich einen Breakpoint in die CMDIFrameWnd::GetWindowMenuPopup(HMENU hMenuBar) Funktion setze, wird dieser Breakpoint nie erreicht.


  • Mod

    Hast Du OnCreateClient überschrieben und rufst evtl. nicht die Funktion der Elternklasse auf?

    Debugge mal in die Funktion und schau Dir die CreateClient Implementierung an.



  • Hallo Martin,

    CMDIFrameWnd::OnCreateClient(...) wird nicht überschrieben.
    Das Debuggen in die CMDIFrameWnd::OnCreateClient(...) Methode, bzw. in die CMDIFrameWnd::CreateClient(...) Methode habe ich gemacht.

    Ich fürchte ich verstehe allerdings nicht ganz worauf Du hinaus willst.


  • Mod

    CMDIFrameWnd::CreateClient wird mit dem Parameter aufgerufen, der als Menü dienen soll.

    GetWindowMenuPopup wird aufgerufen von CMDIChildWnd::OnUpdateFrameMenu.
    Hast Du das überschrieben?

    Schau Dir doch den Source-Code von winmdi.cpp an. Das ist doch keine Hexerei was dort passiert.


Anmelden zum Antworten