Contexmenü einbinden

Hallo zusammen,

ich habe ein Applikation mit einem Trayicon welches bei Rechtsklick ein Kontextmenü öffnet. Da ich von MFC sogut wie nichts verstehe bin ich immer bemüht den Code so einfach zu halten das man ihn gut verstehen kann. Mein Kontextmenü baue ich folgendermassen auf:

Code:
MainMenu=CreatePopupMenu(); 
AppendMenu(MainMenu,0,0,_T("About"));
AppendMenu(MainMenu,0,0,_T("Remove"));
AppendMenu(MainMenu,0,1,"---------");
AppendMenu(MainMenu,0,0,_T("Exit"));
  
Das Menü erscheint einwandfrei und nun möchte ich, dass wenn ich About anwähle, dass etwas Passiert. Hierzu folgender Code. (Auch wenns nicht optimal ist möchte ich über Strings zugreifen)
 

if (message==WM_COMMAND) { 
if (LPCTSTR(wParam)=="&About") {
	 PostQuitMessage(0);
}
if (LPCTSTR(wParam)=="&Remove") {
//SetWindowText(Form1,"Load ...");
}
if (LPCTSTR(wParam)=="E&xit") {
//SetWindowText(Form1,"Save ...");
}
return 0; 
}
Wie könnte es anders sein, es tut sich nichts. Gibt ein Möglichkeit, dass noch einfacher zu lösen?

Grüße
 
Wie stellst du das Popupmenü dar?

Wenn du TrackPopupMenu benutzt, setze bei den Flags zusätzlich TPM_RETURNCMD ein, dann bekommst du die ID des selektierten Items direkt zurück und kannst dir das WM_COMMAND-Gehacke sparen.

Das führt uns zum zweiten Punkt, die IDs. Setze als dritten Parameter bei AppendMenu IDs ein bzw. Zahlenwerte. Anhand dieser erkennst du, welches Item gewählt ist. Diese IDs kannst du beliebig wählen (alles über 0 macht Sinn). Der Strich soll vermutlich ein Separator sein, dafür als zweiten Parameter MF_SEPARATOR einsetzen, bei den echten Menüitems MF_STRING. Auf den Text kannst du beim Separator verzichten.
 
Hallo,
ich habe vergessen das TrackPopupMenu anzugeben. Dabei ergibt sich nun folgendes Problem. Wenn ich bei den Flags und bei den UINT_PTR etwas anderes als 0 angebe wird das Munü ausgegraut.
Und was mich noch viel mehr interessiert an wen oder was wird diese Id zurückgegeben?

Code:
 CMenu MainMenu;
MainMenu.CreatePopupMenu(); 

MainMenu.AppendMenu(MF_STRING,4,_T("About"));

MainMenu.AppendMenu(MF_STRING,3,_T("Remove"));

MainMenu.AppendMenu(MF_SEPARATOR,2,"----------");

MainMenu.AppendMenu(MF_STRING,1,_T("Exit"));

TrackPopupMenu(MainMenu, TPM_RETURNCMD , (xpos), (ypos), 0, m_hWnd, NULL);


Grüße und schon mal Danke.

P.S. Wieviel Level gibts eigentlich bei deinem Java Rennspiel und kann man die Levels auch einzeln anwählen. (Ich versage meistens im fünften)
 
Ach so, wenn du CMenu benutzt, läuft das alles über die MFC-eigene GUI-Verwaltung, und die graut nicht-über-Assistent-verknüpfte Menüpunkte aus. Nerv!

Am besten die Win32 API-Varianten mit HMENU benutzen. Funktionieren praktisch gleich. TrackPopupMenu hat einen Rückgabewert, der BOOL definiert ist. BOOL ist aber eigentlich ein DWORD, und du kannst da eine einfache Zuweisung machen:

DWORD dwCommand = TrackPopupMenu( .... )


Fast übersehen: Sind 6 Level drin, sind nicht soo happig, man darf sich nur nicht von den unmöglichen Pokalen neppen lassen. Kann man nicht einzeln anwählen, ich meine allerdings, dass man mit einer Taste zum nächsten Level springen kann (wenn ich den Code dazu nicht ausgeklammert habe. Probier mal A oder S oder N).
 
Zuletzt bearbeitet:
Ich habe das ganze nun auf HMENU umgestellt, aber es hat sich quasi nichts verändert. Die Menüs sind immer noch ausgegraut. Die unten angegebene MessageBox zeigt immer einen leeren Wert.

Code:
void CMainFrame::OpenPopup(int xpos, int ypos){ 
static HMENU hPopupMenu;
hPopupMenu = CreatePopupMenu();
AppendMenu(hPopupMenu, MF_STRING, 1, "Restore");
AppendMenu(hPopupMenu, MF_STRING, 2, "Minimize");
AppendMenu(hPopupMenu, MF_STRING, 3, "Close Program");
DWORD dwCommand = TrackPopupMenu(hPopupMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN | TPM_RETURNCMD , (xpos), (ypos), 1, m_hWnd, NULL);
MessageBox((LPCTSTR)dwCommand,0,0);
}

Wenn ich nun die Werte so ändere das ich einen der Menüpunkten anwählen kann erhalte ich auch nicht die message WM_COMMAND

Code:
LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM 
 
...
 
if (message==WM_COMMAND) { 


if (lParam == 0)
{
switch(LOWORD (wParam))
{
 
case 1:
MessageBox("1",0,0);
break;
case 2:
 
MessageBox("2",0,0);
break;
case 3:
MessageBox("3",0,0);
break;
}
}
return 0;
}
return CFrameWnd::WindowProc(message, wParam, lParam);
}

Bin völlig Ratlos

Grüße
 
Die 1 in TrackPopupMenu muss laut Doku eine 0 sein (reserviert).
Das dwCommand ist nur eine Zahl, du bekommst nicht den gewählten Text zurück, sondern die ID, die du bei AppendMenu angegeben hast. In deinem Fall 1, 2 oder 3.

Nach TrackPopupMenu solltest du das HMENU auch wieder zappen, also DestroyMenu( hMenuPopup ); aufrufen.
 
Code:
void CMainFrame::OpenPopup(int xpos, int ypos){ dwCommand = TrackPopupMenu(hPopupMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN | TPM_RETURNCMD , (xpos), (ypos), 0, m_hWnd, NULL);
MessageBox((LPCTSTR)dwCommand,0,0); 
}

Mir würde die ID ja volkommen reichen. Aber die MessageBox bleibt komplett leer. Und selbst wenn ich da die ID gekommen würde, hätte ich immer noch das Problem in der WindowProc, weil ich dort nicht in das If-Statement reinkomme.

...
Code:
if (message==WM_COMMAND)
...

 
Ich meine sowas:

Code:
void CMainFrame::OpenPopup(int xpos, int ypos)
{ 
  DWORD dwCommand = TrackPopupMenu(hPopupMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN | TPM_RETURNCMD , (xpos), (ypos), 0, m_hWnd, NULL);
  switch ( dwCommand )
  {
    case 1:
       AfxMessageBox( "Punkt1" );
       break;
    case 2:
       AfxMessageBox( "Punkt2" );
       break;
    case 3:
       AfxMessageBox( "Punkt3" );
       break;
  }
}
 
Erstmal vielen dank, so würde es gehen wenn nicht das Problem mit den Ausgegrauten Menüs weiterhin bestehen würde. Nur mit der folgenden Kombination wird das Menü richtig angezeigt.
Code:
AppendMenu(hPopupMenu, 0, 0, "Restore");
Sobald ich eine der beiden Nullen ändere, wirds wieder grau, was mür mich bedeutet das ich in der Case Anweisung immer nur einen Fall habe. Mann müsste halt auf den String prüfen können, oder soetwas in der Art.

Grüße
 
Du kannst ein Kontextmenü unter MFC recht einfach erstellen und mit funktionalität belegen.

Du erstellst einfach eines mit dem Resourcen Editor (siehe Anhang)- als Klasse erstellst du keine Neue sondern wählst eine bereits Vorhandene (normalerweise die wo es aufgerufen wird) aus und fügst für jeden Eintag eine Funktion (OnCommand) hinzu um die Aktion zu behandeln.

Der Code um dieses dann anzuzeigen sieht wie folgt aus :
Code:
CMenu menu, *popup=NULL;

menu.LoadMenu(IDR_CONTEXT_IMAGEVIEW);
pPopup = menu.GetSubMenu(0);

//--- deaktiviert den 3. und 4. Eintrag zur Laufzeit ---
pPopup->EnableMenuItem(2, MF_BYPOSITION | MF_GRAYED);
pPopup->EnableMenuItem(3, MF_BYPOSITION | MF_GRAYED);

pPopup->TrackPopupMenu ( TPM_LEFTALIGN  | TPM_RIGHTBUTTON, point.x , point.y , this);

gegebenenfalls musst due noch die Koordinaten umrechnen lassen, wo das hin soll
etwa mit:
Code:
 this->ClientToScreen(&point);
oder so - kommt immer drauf an, wo du den Punkt her hast.
 

Anhänge

  • beispiel.png
    beispiel.png
    4,1 KB · Aufrufe: 76

Neue Beiträge

Zurück