Frage wg. dynamischem Menü
-
Ich wollte mir für das normale Hauptmenü während der Laufzeit dynamisch Menüeinträge erzeugen lassen.
Und zwar sol diese Datei ausgelesen werden:.submenu 1 ..submenu 1_1 ..submenu 1_2 .submenu2 .submenu3 ..submenu 3_1.. sollen untermenüs von . sein
Die datei kann natürlich variieren, der Grundaufbau ist aber immer gleich und .. ist die höhste Verzweigung der Untermenüs.Ich habe mir dann folgenden Code zusammengeschustert:
BOOL CMainFrame::CreateMenus() { int iZeile = 0; unsigned int iID = first_ID + 1; int iSubMenuCount = -1; CStdioFile fDatei; CString sPath = m_config.GetConfigDir() + "Programm.cfg"; //Gibt zu öffnende Datei wieder CString sZeile, sZeile_old; CMenu MainMenu, Menu; CMenu subMenu[5]; Menu.CreatePopupMenu(); //einlesen der richtigen Dateistruktur und speichern der Untermenüs in subMenu[x] if (fDatei.Open( sPath, CFile::modeRead)) { while( fDatei.ReadString(sZeile) || (! sZeile.IsEmpty())) { sZeile.TrimLeft(); sZeile.TrimRight(); if (sZeile.Left(1) == ".") { if (sZeile_old.Left(2) != ".." && sZeile.Left(2) == "..") { //dann PopupMenü erstellen iSubMenuCount++; subMenu[iSubMenuCount].CreatePopupMenu(); } else if (sZeile_old.Left(2) == "..") { //dann PopupMenü-Eintrag anhängen subMenu[iSubMenuCount].AppendMenu(MF_BYPOSITION,iID,sZeile_old); } sZeile_old = sZeile; iID++; } iZeile++; } } fDatei.Close(); iSubMenuCount = -1; //speichern der gesamten Menüstruktur in Menu if (fDatei.Open( sPath, CFile::modeRead)) { while( fDatei.ReadString(sZeile) || (! sZeile.IsEmpty())) { sZeile.TrimLeft(); sZeile.TrimRight(); if (sZeile.Left(1) == ".") { if (sZeile_old.Left(2) != ".." && sZeile.Left(2) == "..") { //dann PopupMenü iSubMenuCount++; Menu.AppendMenu(MF_BYPOSITION | MF_POPUP, (UINT)subMenu[iSubMenuCount].m_hMenu, sZeile_old); } else if (sZeile_old.Left(2) == ".." && sZeile.Left(2) == "..") {} else Menu.AppendMenu(MF_BYPOSITION,iID,sZeile); sZeile_old = sZeile; iID++; } } } fDatei.Close(); MainMenu.LoadMenu(IDR_MAINFRAME);//das Hauptmenü MainMenu.InsertMenu(2, MF_BYPOSITION | MF_POPUP, (UINT)Menu.m_hMenu, "Dateneingabe"); SetMenu(&MainMenu); MainMenu.Detach();//Recource wieder freigeben Menu.Detach(); return true; }Das hierbei die letzte Zeile nicht verarbeitet wird, kann erstmal ignoriert werden.
Ich hatte mir gedacht, ich laufe die Datei erst einmal durch und packe alle Untermenüs in die jeweiligen PopupMenüs zusammen (Es muss immer ein neues PopupMenü erstellt werden, wenn auf ein . ein .. folgt). Dann ein 2. Durchlauf und alles in ein übergeordnetes CMenü und dieses dann ins Hauptmenü einfügen.
compilieren tut er ohne Fehler, aber wenn ich dann im Menü auf "Dateneingabe" klicke, stürzt er ab.
Unschön finde ich es auch noch, das ich so die Anzahl der subMenus auf max. 5 begrenzt habe. wie kann ich das ganze ohne Begrenzung der Anzahl machen?
Und vorallem, wieso funktioniert der Code nicht?mfg
tie
-
Hab es nach viel rumprobieren jetzt hingekriegt:
BOOL CMainFrame::CreateMenus() { bool bSubMenu = false; int iZeile = 0; unsigned int iID = first_ID + 1; CStdioFile fDatei; CString sPath = m_config.GetConfigDir() + "Programm.cfg"; //Gibt zu öffnende Datei wieder CString sZeile, sZeile_old; CMenu MainMenu, Menu; CMenu *subMenu = new CMenu; subMenu->CreatePopupMenu(); Menu.CreatePopupMenu(); //einlesen der richtigen Dateistruktur und speichern der Untermenüs in subMenu[x] if (fDatei.Open( sPath, CFile::modeRead)) { while( fDatei.ReadString(sZeile) || (! sZeile.IsEmpty())) { sZeile.TrimLeft(); sZeile.TrimRight(); if (sZeile.Left(1) == ".") { if (sZeile.Left(2) == "..") { bSubMenu = true; subMenu->AppendMenu(MF_STRING,iID++,sZeile); } else { if (bSubMenu) { Menu.AppendMenu(MF_BYPOSITION | MF_POPUP, (unsigned int)subMenu->GetSafeHmenu(), sZeile_old); subMenu = new CMenu; subMenu->CreatePopupMenu(); } else Menu.AppendMenu(MF_STRING,iID++,sZeile); sZeile_old = sZeile; bSubMenu = false; } } iZeile++; } } fDatei.Close(); if (bSubMenu) Menu.AppendMenu(MF_BYPOSITION | MF_POPUP, (unsigned int)subMenu->GetSafeHmenu(), sZeile_old); else Menu.AppendMenu(MF_STRING,iID++,sZeile_old); MainMenu.LoadMenu(IDR_MAINFRAME);//das Hauptmenü MainMenu.InsertMenu(2, MF_BYPOSITION | MF_POPUP, (UINT)Menu.GetSafeHmenu(), "Dateneingabe"); SetMenu(&MainMenu); MainMenu.Detach();//Recource wieder freigeben Menu.Detach(); return true; }Ich weiss aber nicht, ob das mit dem subMenu = new CMenu; subMenu->CreatePopupMenu(); so sauber ist. vielleicht gibts da ja ne bessere lösung
-
Ich hoffe mal in diesem Thread bleibt es nicht bei den Selbstgesprächen und ihr könnt mir hier helfen

Die Menüeinträge sind jetzt alle disabled.
Also wollte ich die mit EnableMenuItem() klickbar machen.hab mir das so gedacht:
subMenu->AppendMenu(MF_STRING,iID,sZeile); tempMenu = subMenu->GetSubMenu(subMenu->GetMenuItemCount()-1); tempMenu->EnableMenuItem(iID++, MF_ENABLED);statt
subMenu->AppendMenu(MF_STRING,iID++,sZeile);Aber tempMenu bekommt nur den Wert 0 und in der EnableMenuItem-Zeile kommt es dann zum Absturz
tempMenu is natürlich auch ein Zeiger der Klasse CMenu.
-
*up*
prob besteht immernoch
-
hab jetzt was gefunden, was wohl die lösung sein könnte
Hi all.
I already know the solution, though I'm getting quite a lot of mails how did I solve this problem.
Window's main menu has items, which are submenus, and submenus has items
which are usually final items, or (somtimes) further submenus. Usual menu looks like this:menu=
submenu1 submenu2 submenu3 ....
item11 item21 item31
item12 item22 ...
... ...
etc.But the menus are stored dynamically, means: menu has only pointers to
each submenu, and when You call GetSubmenu(GetMainMenu(MainWindow,...));
it returns You the pointer to that submenu. But it is stored in some other
way (I've forgotten how and don't understand why), so when You set this
item, it seams to be changed (no error code). But it loads every time
dynamically - from the previous definition (From the resource file or menu
created firs time) and draws as You created it for the first time.It is running on the main menu correctly, because it does not
reload from the resource. The main menu remains same all the time.So the solution is:
when submenu1 has defined constatnt MI_ITEM1, submenu2 MI_ITEM2, etc:
//In windows API:
switch (msg)
case WM_COMMAND :
switch ( LOWORD(wParam) ) {
case ( MI_ITEM1 ) :
//Dynamically create submenu
PopupMenu = CreateMenu(...);
AppendMenu(PopupMenu, "Label 11", ..., CMD_ITEM11);
...// show submenu:
TrackPopupMenuEx(PopupMenu, TPM_LEFTALIGN |
TPM_LEFTBUTTON, actualpos.x, actualpos.y, hWnd, NULL);return TRUE;
switch (CMD_ITEM11) : ActionItem11();
// Using MFC:
CWhatEver::OnSubmenu1Click ( CWnd *pWnd, CPoint actualpos)
{
...
//Dynamically create submenu
PopupMenu = CreateMenu(...);
AppendMenu(PopupMenu, "Label 11", ..., CMD_ITEM11);
...// show submenu:
TrackPopupMenuEx(PopupMenu, TPM_LEFTALIGN |
TPM_LEFTBUTTON, actualpos.x, actualpos.y, hWnd, NULL);...
}CWhatEver::OnItem11Click ( CWnd *pWnd, CPoint actualpos)
//means, when You click CMD_ITEM1
{
...
ActionItem11();
...
}nur leider versteh ich überhaupt nicht, was ich da wie einbauen soll. hoffe einer von euch versteht den code und kann mir das erklären
-
Schon in die FAQ geschaut ?

Devil
-
nich nur darein
bloß bin nicht fündig geworden
hab es jetzt auch hingekriegt, meinen code aber komplett umgebaut
kann es ja morgen mal posten, wenn ich auf arbeit bin.