Aufbau / Benutzung der MENUITEMINFO-Struktur



  • Mir bereitet die Manipulation von Menü-Einträgen mithilfe SetMenuItemInfo() und der MENUITEMINFO-Struktur Kopfzerbrechen! Ich will z.B. bei fState zwischen MFS_ENABLED und MFS_DISABLED, oder zwischen MFS_CHECKED und MFS_UNCHECKED hin- und herschalten. Dazu setze ich zunächst fMask auf MIIM_STATE, um fState zu setzen / zu lesen.

    Jetzt sieht das wie folgt aus:
    Wenn MFS_ENABLED gesetzt ist, setze ich MFS_DISABLED und umgekehrt.
    Wenn MFS_CHECKED gesetzt ist, setze ich MFS_UNCHECKED und umgekehrt.

    Soweit die Theorie... Jetzt mal ein erstes Beispiel, wie ich mir das Vorstelle:

    MENUITEMINFO mif;
    mif.cbSize = sizeof(MENUITEMINFO);
    mif.fMask = MIIM_STATE;
    GetMenuItemInfo(hMenu, Identifier, FALSE, &mif);
    
    mif.fState = mif.fState & MFS_CHECKED ? MFS_UNCHECKED : MFS_CHECKED;
    SetMenuItemInfo(hMenu, Identifier, FALSE, &mif);
    

    Dabei gilt:

    MFS_CHECKED = MF_CHECKED   = 0x00000008L
    MFS_UNCHECKED     = MF_UNCHECKED = 0x00000000L
    

    Das heißt, wenn MFS_CHECKED gesetzt ist, sieht mein Bitmuster mindestens so aus:
    0000 1000

    Aber was, wenn noch andere Bits gesetzt waren? Die würde ich einfach löschen und somit ungewollt irgendwelche Einstellungen ändern! Jetzt kommt es mir natürlich in den Sinn, MFS_CHECKED so zu setzen:

    mif.fState |= MFS_CHECKED;
    

    Das würde dazu führen, dass MFS_CHECKED zusätzlich gesetzt wird, die original-Bits aber gesetzt bleiben. Problem: Was ist, wenn MFS_UNCHECKED gesetzt ist? Dann hab ich mir ja nen schönen Widerspruch gebaut, das Menu-Item ist checked und gleichzeitig unchecked!

    Aber es kommt ja noch härter, MFS_ENABLED / MFS_DISABLED sorgt für die totale Verwirrung: Was oben mit MFS_CHECKED / MFS_UNCHECKED noch so wunderbar geklappt hat, funktioniert mit MFS_ENABLED / MFS_DISABLED nicht!

    Das heißt in Code:

    MENUITEMINFO mif;
    mif.cbSize = sizeof(MENUITEMINFO);
    mif.fMask = MIIM_STATE;
    GetMenuItemInfo(hMenu, Identifier, FALSE, &mif);
    
    mif.fState = mif.fState & MFS_ENABLED ? MFS_DISABLED : MFS_ENABLED;
    SetMenuItemInfo(hMenu, Identifier, FALSE, &mif);
    

    ...natürlich versuche ich dabei nicht, den deaktiverten Menüeintrag mit einem Klick auf ihn selbst zu aktivieren!
    Die entsprechenden Werte sehen dabei übrigens so aus:

    MFS_ENABLED  = MF_ENABLED  = 0x00000000L = 0000 0000
    MFS_GRAYED   = MF_GRAYED   = 0x00000001L = 0000 0001
    MFS_DISABLED = MF_DISABLED = 0x00000002L = 0000 0010
    

    Und hier verfange ich mich schon wieder in Widerspruchlüchkeiten. Die MSDN sagt, MFS_DISABLED und MFS_GRAYED sei dasselbe, das Bitmuster ist es aber ganz offensichtlich nicht! Und wie sonst soll man die Werte manipulieren? Aber selbst wenn man im Code oben MFS_DISABLED mit MFS_GRAYED ersetzt, funktioniert es nicht! Ich verstehe wirklich nicht, warum! Und wieso haben MFS_ENABLED und MFS_DISABLED unterschiedliche Bits? Wieso kann ein Button zur gleichen Zeit aktiviert und deaktiviert sein?

    Bitte verschafft mir hier mal ein wenig mehr Durchblick!
    Danke im voraus!


  • Mod

    Ich habe keine Ahnung was für ein SDK Du verwendest, bei mir ist

    #define MFS_GRAYED          0x00000003L
    #define MFS_DISABLED        MFS_GRAYED
    

    Dasmit MFS_ENABLED ist wirklich verwirrend.
    Es ist offensichtlich, dass nur MFS_GRAYED/MFS_DISABLED hier den Status zeigen.

    D.h. willst Du einen Eintrag enabled anzeigen, heißt das:

    mif.fState &= ~(MFS_GRAYED);
    

    Gleiches gilt für MFS_CHECKED:

    Setzen:

    mif.fState |= MFS_CHECKED;
    

    Löschen

    mif.fState &= ~(MFS_CHECKED);
    

    Ich würde nur mit |= und &= ~ arbeiten un den entsprechenden signifikanten Flags.

    Ich gebe Dir recht, es ist verwirrend, aber denoch logisch... 😉



  • Ja, so wie du es sagst, erscheint es mir jetzt absolut logisch, danke :-).

    Aber wofür gibt es MFS_ENABLED? Zum Plattform SDK: Windows Server 2003 R2.


  • Mod

    Damit man bei einer Menuitem Ressource nicht 0 schreibten muss sondern eben MF_ENABLED. Das liest sich einfach besser, selbst wenn es nichts aktiv tut.

    Es gibt auch Code bei dem aktiv ein Flag mitgereicht werden soll. Wie willst Du jetzt im Code sagen: Setze dieses Item enabled!

    Im Endeffekt ist es ein lesbarer Platzhalter.

    PS: Diese Diskrepanzen gibt es übrigends auch noch bei anderen Bit Maksen.


Anmelden zum Antworten