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 = 0x00000000LDas heißt, wenn MFS_CHECKED gesetzt ist, sieht mein Bitmuster mindestens so aus:
0000 1000Aber 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 0010Und 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!
-
Ich habe keine Ahnung was für ein SDK Du verwendest, bei mir ist
#define MFS_GRAYED 0x00000003L #define MFS_DISABLED MFS_GRAYEDDasmit 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.
-
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.