GetMessage oder PeekMessage ?



  • moin meisters ...

    Ein Dialog mit Fortschrittsanzeige und Abbrechen-Button.
    Ich möchte keinen Thread verwenden.
    In einer Schleife wird was gemacht, und in dieser möchte ich immer mal prüfen
    ob der Button gedrückt wurde.

    Es darf kein Thread sein, weil ich den Code auch für PalmOS (keine Threads
    möglich ) verwenden möchte, etwas geändert natürlich, aber im Ablauf und
    Design soll beides identisch sein.

    Was wird in einem solchen Fall genommen, GetMessage oder PeekMessage ?

    Besten Dank im Voraus
    mfg
    RB



  • GetMessage kehrt immer nur dann erst zurück, wenn tatsächlich eine Message eingetroffen ist (z.B. Buttonclick). Liegen keine Messages vor, so "schläft" das Programm.
    PeekMessage dagegen, kehrt sofort zurück, auch wenn keine Message vorliegt. In diesem Fall kann das Programm andere Aktivitäten machen.

    Ein Beispiel (Windows, MFC):

    MSG message;
    if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) {
        ::TranslateMessage(&message);
        ::DispatchMessage(&message);
    }
    

    Auf API übertragen, sollte das ähnlich aussehen.

    EDIT: Sorry, das sind APIs 🙄



  • Danke für die schnelle Antwort 🙂

    mfg
    RB



  • irgendwie habe ich da aber doch ein Problem

    // soll Abbrechen realisieren
    bool IsCanceled(UINT idBtnCancel)
    {
        bool canceled = false;
        MSG msg;
        if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) 
        { 
            TranslateMessage(&msg); 
            if( msg.message == WM_COMMAND && LOWORD(msg.wParam) == idBtnCancel )
                canceled = true;
            else
                DispatchMessage(&msg);
        }
        return canceled;
    }
    
    // DIALOG(!)-Proc
    ...
    case WM_COMMAND:
        if( LOWORD(wParam) == IDC_BTN_START )
        {
            for(long l=0; l<100000 && !IsCanceled(IDC_BTN_STOP); l++)
                SendMessage(hProgress, PBM_SETPOS, l, 0);
    
            return TRUE;
        }
    

    Also die for-Schleife soll abgebrochen werden können. Ich kann aber auf der
    "Abbrechen"-Schaltfläche rumklicken wie ich will 😃 es passiert nichts. 😡

    Hat jemand sowas schon mal gemacht und kann mir noch nen Tip geben ?
    Liegts daran, daß ein Dialog verwendet wurde ? (Ich muß aber einen Dialog verwenden !)

    mfg
    RB



  • WM_COMMAND kommt gar nicht in der Message Loop an.



  • ok stimmt.

    Aber WM_LBUTTONDOWN, nur das nützt mir nix, weil ich nicht weiß von welchem
    Button( wenn überhaupt ) und über die Koordinaten ... keine Lösung.

    Ich versuche nun schon ne ganze weile, nur mit dem Debugger is auch nicht das Wahre.

    WM_COMMAND wird wohl erst duch DispatchMessage generiert ?

    Also werden denn nur die Nachrichten des Buttons an den Dialog dort empfangen.

    😡 😮 😕 🤡

    Also für PalmOS würde es so aussehen,

    static bool DialogCanceled( ControlPtr ctlP, unsigned short ctlId )
    {
    	EventType event;			// Ereigniszeiger
    	bool  canceled = false;		// Rückgabe
    
    	// Liegen Ereignisse an ?
    	if( EvtSysEventAvail( false ) || EvtEventAvail ( ) )
    	{
    	// hole Ereignis
    		EvtGetEvent( &event, 0 );
    	// Ereiginstyp und Id prüfen
    		if( event.eType == ctlSelectEvent && event.data.ctlSelect.controlID == ctlId )
    	// Abbrechen wurde gedrückt
    			canceled = true;
    
    		if( !SysHandleEvent( &event ) )
    	//	alle anderen Ereignisse verarbeiten lassen 
    			CtlHandleEvent( ctlP, &event );
    	}
    	return canceled;
    }
    

    nur halt für Windows ...

    wenn nicht lasse ich mir was anderes einfallen, würde mir aber nicht recht sein

    mfg
    RB



  • johu 🤡

    bool IsCanceled(UINT idBtnCancel, HWND hDlg)
    {
    	bool canceled = false;
    	MSG msg;
    	if( PeekMessage(&msg, hDlg, 0, 0, PM_REMOVE) ) 
    	{ 
    		TranslateMessage(&msg);
    		if( msg.hwnd == GetDlgItem(hDlg, idBtnCancel) )
    		{
    			if( msg.message == WM_LBUTTONUP )
    			{
    				canceled = true;
    			}
    			DispatchMessage(&msg);
    		}
    	}
    	return canceled;
    }
    

    so wirds was 😃 nur ebend sollten die anderen Controls deaktiviert werden, weil sie eh nicht reagieren ...

    mfg
    RB



  • EnableWindow - aber warum verarbeitest du nicht alle Nachrichten und setzt bei dieser Message in deiner normalen Fenster-Prozedur einfach eine globale Variable 😕



  • moin meister ...

    der entgültige Code sieht jetzt so erst mal aus.

    bool IsCanceled(UINT idBtnCancel, HWND hDlg)
    {
    	bool canceled = false;
    	static bool bDown = false;
    
    	RECT rc;
    	MSG msg;
    
    	if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) 
    	{ 
    		TranslateMessage(&msg);
    		if( msg.hwnd == GetDlgItem(hDlg, idBtnCancel) )
    			// wurde Taste der Mous über der Schaltfläche gedrückt ?
    			if( msg.message == WM_LBUTTONDOWN )
    			// ja: Merker setzen
    				bDown = true;
    
    			// wird die Taste der Mous über der Schaltfläche gelöst und wurde sie vorher gedrückt ?
    			if( msg.message == WM_LBUTTONUP && bDown)
    			{
    			// ja:
    
    			// Koordinaten konvertieren
    				ScreenToClient(msg.hwnd, &msg.pt);
    			// Bereich des Clients holen
    				GetClientRect(msg.hwnd, &rc);
    			// Mouse wurde über Client losgelassen
    				if( PtInRect(&rc, msg.pt) )
    			// Aktion soll abgebrochen werden
    					canceled = true;
    			// Merker zurücksetzen, weil static
    				bDown = false;
    			}
    		DispatchMessage(&msg);
    	}
    	return canceled;
    }
    

    weiter oben hatte ich mal den Code gezeigt für PalmOS.
    Ich möchte gern Programme für PalmOS und WinCE schreiben, wobei bei der Programmierung selbst eigentlich keine großen Unterschiede mehr anfallen sollen.

    Wenn ich diese Funktionalität nur für Win bräuchte würde ich mir diese Umständliche Lösung nicht aufhalsen.

    Nur PalmOS verarbeitet Nachrichten nicht ganz so wie Windows. Es gibt auch keine Threads, hier gäbe es für Win eine einfache Lösung.

    Unter PalmOS kann man daher eine "Endlosschleife" nicht abbrechen, oder man verwendet eine Funktion in der Schleife wie weiter oben in einem Beitrag
    aufgezeigt ist.

    Jetz der Compatible Code für Win und Palm

    for(int i=0; i<MAX && !IsDialogCanceled(...); i++)
    machewas()

    wobei machewas in ANSI-C oder so gepinselt ist und eh "platformunabhänig" ist.

    🤡 🤡 🤡 🤡 🤡

    So werde ich die Geister von J2ME die ich rief wieder los !!!

    Wenn wer schon mal mit J2ME (JAVA für Handys) gearbeitet hat, wird feststellen,
    das Java mit sehr viel Glück platformunabhängig sein kann aber niemals Geräteunabhängig sein wird 🤡

    Zumindest häufen sich die Stellenangebote:
    "Suche J2ME-Programmierer der Siemens-Spiele auf Nokia portiert"

    Seit wann wird platformunabhängige Software auf andere (Fremdfirmen)Platformen portiert ? Da stimmt doch was nicht !!!

    Auch Tool wie AppForge ( VB für Palm/WinCE ) bewegen sich auf dem schmalen Grad
    des kleinsten gemeinsamen Nenners und sind keine Alternative.

    Die obige Problematik mit der Schleife ist nicht zu lösen, da Appforge viel zu träge ist. Die Schleife soll aber abgebrochen werden wen Cancel gedrückt wird und nicht 3 Minuten Später ...

    mfg
    RB


Anmelden zum Antworten