Popup-Menüs erstellen



  • Das hab ich schon ausprobiert, damit komm ich nicht so ganz klar (Programm stürzt ab).
    Die Idee von GeorgeHomes funktioniert doch ganz gut.



  • So finde ich es am bequemsten:

    void CTestDlg::OnOK() 
    {
    	CMenu menu;
    	menu.CreatePopupMenu();
    
    	menu.AppendMenu(MF_STRING,1,"Eintrag 1");
    	menu.AppendMenu(MF_STRING,2,"Eintrag 2");
    	menu.AppendMenu(MF_STRING,3,"Eintrag 3");
    	menu.AppendMenu(MF_STRING,4,"Eintrag 4");
    
    	CPoint pt;
    	GetCursorPos(&pt);
    	int ret = menu.TrackPopupMenu(TPM_NONOTIFY | TPM_RETURNCMD,pt.x,pt.y,this);
    	switch(ret)
    	{
    	case 1:
    		// ...
    		// break;
    	case 2:
    		// ...
    		// break;
    	case 3:
    		// ...
    		// break;
    	case 4:
    		{
    			CString text;
    			text.Format("Auswahl ID: %d",ret);
    			MessageBox(text);
    		}
    	}
    }
    


  • Ich definiere die Menüpunkte lieber zur Laufzeit, weil man dann einfach allgmein gleich flexibeler ist. In vielen fällen ist ein variables Contextmenü recht praktisch.

    Die TrackPopupMenu Funktion TPM_RETURNCMD auf wartemodus zu schalten und dann direkt auf den Rückgabewert zu reagieren, ist auch sicher keine schlechte Variante. Ich persönlich finde aber das verarbeiten via Messages allgemeiner, da man dann auch problemloser einen Punkt aus dem Contextmenü auch ins normale Menü einfügen kann.

    Alternativ kannst du die Messages auch in einer selbst überschriebenen WindowProc verarbeiten, in der du auf die WM_COMMAND Message reagierst. Dann steht im LOWORD des wParams die ID des ausgelösten Menüpunktes. So eine überschriebene WindowProc könnte dann so aussehen:

    LRESULT CTestContext2Dlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
    {
    	// TODO: Speziellen Code hier einfügen und/oder Basisklasse aufrufen
    	switch (message)
    	{
    	case WM_COMMAND:
    		switch (LOWORD(wParam))
    		{
    		case IDM_MENU1:
    			// Hier benutzerdefinierte Funktion.
    			MessageBox("Menüpunkte 1 angeklickt!");
    			return true;
    		}
    		break;
    	}
    
    	return CDialog::WindowProc(message, wParam, lParam);
    }
    


  • Wo wir gerade so schön dabei sind: Wenn ich einen Menüpunkt zur Laufzeit hinzufüge wird er doch bei SDI und MDI Anwendungen (und bei Meiner Dialogfeld Anwendung wo ich nicht CMenu verwende) deaktiviert dargestellt. EnableMenuItem hilft da nicht. Wie bekomme ich das hin das man das Item anklicken kann?



  • Hm, das von dir beschriebene Problem ist mir noch nie aufgefallen. Also ich habe jetzt einfach mal (in einer Dialogfeld Anwendung) meinen IDM_MENU1 punkt in das Dialogfeldmenü (mit Resourceneditor) hinzugefügt. Der ist nicht deaktiviert.

    Dann habe ichs mal damit versucht, in das Dialogfeldmenü ein Item zur Laufzeit hinzuzufügen und auch das ist nicht deaktiviert:

    CMenu* pMenu = GetMenu();
    pMenu = pMenu->GetSubMenu(0);
    pMenu->InsertMenu(-1, MF_BYCOMMAND, 103, "Menüpunkt 2");
    


  • Die Idee von Nemesyzz funktioniert gut, wie kann ich es aber machen, das das popup menü nur innerhalb eines Listenelementes erscheint?



  • OnContextMenu() übeschreiben, CWnd vergleichen

    if (pWnd == GetDlgItem(IDC_LIST1))
    	GetMenu()->GetSubMenu(0)->TrackPopupMenu(/*...*/);
    


  • Jo, super. Klappt
    Danke

    PS. Find ich gut, das es hier im Forum noch hilfsbereite leute gibt und nicht nur solche, die gleich auf irgendwelche anderen seite verweisen.



  • hast du VC++?
    denn da kenn ich einen Trick :-.)
    einen einfachen ohne viel tippen



  • Ja, hab ich.



  • und was ich eben kann ist für dialogfelder
    kannst damit was anfangen?
    dann werde ich das doc für dich heraussuchen
    wenn es für dialoge sein soll



  • Ich benutze Eure Anleitung für das Tray-Icon und es klappt ja soweit alles sehr gut.
    Wie bekomme ich es aber hin, dass sich das Popup-Menu wieder schließt, wenn ich irgendwo anders hinklicke und nicht ins Menu?



  • Habs selbst gefunden... 🙂
    Und für alle die es auch interessiert:

    Auszug aus der MSDN
    Remarks
    To display a context menu for a notification icon, the current window must be the foreground window before the application calls TrackPopupMenu or TrackPopupMenuEx. Otherwise, the menu will not disappear when the user clicks outside of the menu or the window that created the menu (if it is visible). However, when the current window is the foreground window, the second time this menu is displayed, it displays and then immediately disappears. To correct this, you must force a task switch to the application that called TrackPopupMenu at some time in the near future. This is done by posting a benign message to the window or thread, as shown in the following code sample:

    Also das heißt, Window erst als Foreground setzen und dann gleich WM_NULL posten:

    SetForegroundWindow();
    TrackPopupMenu(.......);
    PostMessage(WM_NULL, 0, 0);
    


  • Die folgende Variante von Nemesyzz gefällt mir sehr gut. Ich brauche allerdings noch eine Titelzeile in der ich einen String ausgeben kann. Irgendwie finde ich nicht die richtigen Parameter dafür.

    Welche Möglichkeiten gibt es?

    Nemesyzz schrieb:

    So finde ich es am bequemsten:

    void CTestDlg::OnOK() 
    {
    	CMenu menu;
    	menu.CreatePopupMenu();
    
    	menu.AppendMenu(MF_STRING,1,"Eintrag 1");
    	menu.AppendMenu(MF_STRING,2,"Eintrag 2");
    	menu.AppendMenu(MF_STRING,3,"Eintrag 3");
    	menu.AppendMenu(MF_STRING,4,"Eintrag 4");
    
    	CPoint pt;
    	GetCursorPos(&pt);
    	int ret = menu.TrackPopupMenu(TPM_NONOTIFY | TPM_RETURNCMD,pt.x,pt.y,this);
    	switch(ret)
    	{
    	case 1:
    		// ...
    		// break;
    	case 2:
    		// ...
    		// break;
    	case 3:
    		// ...
    		// break;
    	case 4:
    		{
    			CString text;
    			text.Format("Auswahl ID: %d",ret);
    			MessageBox(text);
    		}
    	}
    }
    


  • Gibt es bei PopUp Menüs tatsächlich keine Überschriften? Und wie kann man dynamisch die Schriftarte u.s.w. der einzelnen Menüeinträge bestimmen?

    Genügt es den Font zu setzen?



  • http://www.codeproject.com/menu/gradientmenus.asp
    Diese Klasse verwende ich bei meinen Popup-Menu um einen Titel anzuzeigen.


Anmelden zum Antworten