PeekMessage liefert IMMER den Wert 1 zurück



  • Hallo,

    ich verwende 2 threads. Einen mit Steuerung der Fensterelemente (soll später aber auch ohne Fenster laufen) und einen ohne Fenster. Beide threads sollen untereinander strings austauschen können. Laut dem was ich gefunden habe, sollte wohl die Funktion „PeekMessage“ die richtige Wahl sein.

    Ich habe mal den Ausschnitt aus meinem Code eingefügt. Leider ist es bei mir so, dass „PeekMessage“ immer den Wert „1“ zurück gibt, ohne dass ich je zuvor die Funktion „PostThreadMessage“ aufgerufen habe. Der Wert „1“ sollte ja bedeuten, dass eine Nachricht im Puffer ist und sollte aber wenigstens durch die Option/Angabe von „PM_REMOVE“ wieder verschwinden. Tatsache ist aber, dass ich nun in einer Endlosschleife hängen bleibe und immer die „1“ erhalte. Ich verstehe einfach nicht was ich falsch mache.

    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
    {
        /* ___ run dialog box _______________________________________________ */
        // Create the thread to begin execution on its own.
        CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
            startFFDialogBox,       // thread function name
            hInst,                  // argument to thread function 
            0,                      // use default creation flags 
            &dwThreadIdArray[0]);   // returns the thread identifier 
    
        createMessageQueue();
    
        /* ___ run winsock server ___________________________________________ */
        // Create the thread to begin execution on its own.
        CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
            initWinsockServer,      // thread function name
            hInst,                  // argument to thread function 
            0,                      // use default creation flags 
            &dwThreadIdArray[1]);   // returns the thread identifier 
    
        // Wait until all threads have terminated.
        WaitForMultipleObjects(threadCnt, hThreadArray, TRUE, INFINITE);
    
        return 0;
    }
    
    /* receive-thread: create queue for messages */
    void createMessageQueue(void)
    {
        // create an event for the thread's queue completition
        hEvent = CreateEvent(NULL, false, \
            true, (LPTSTR)_T("TESTEvent")); // event name
    
        // wait for queue completition
        DWORD dwState = WaitForSingleObject(hEvent, 100); // wait 100 ms
    }
    
    //  dieses callback gehört zum aufgerufenen thread "startFFDialogBox"
    INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
    {
       // ...
    
        BOOL bRet;
        MSG msg;
    
        // get messages by message from threads local queue
        while ((bRet = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) != WM_QUIT)
        {
            if (bRet == -1)
            {
                return 1;  // error!
            }
            else  
            { // a valid message is received
    
                // <---  hier hänge ich mit dem ständigen Wert "bRet==1" fest
            } 
        }
    
        return TRUE; // Message handled 
    }
    

  • Mod

    Was heißt Du hängst fest?

    Wenn Da zum Beispeil ein WM_PAINT erzeugt wird und Du ihn einfach entfernst ohne das er bearbeitet wird, dann wird einfach ein neuer erzeugt.
    Ohne dass Du nachrichten auch bearbeiten last funktioniert das nicht.

    Du solltest vor allem auchnicht darauf kommen in der Nachrichten Behandlung selbst gleich wieder eine Nachrichten Behandlung zu starten.
    Wenn dort ein DoModal läuft, dann bau doch einfachnur eine Nachrichtenbehandlung in die DlgProc ein.

    Was hast Du den vor?



  • Martin Richter schrieb:

    Was hast Du den vor?

    Ich habe einen force-feedback-joystick, den ich bereits ansteuern kann. Ein TCP-server ist bereits auch so gut wie fertig. Nun möchte ich damit meinen "dann ferngesteuerten" Roboter durch's Wohnzimmer steuern.
    In Sachen Win und C++ bin ich einigermaßen neu. Meine Stärken liegen in jahrelanger Erfahrung mit C und Programmierung auf Hardware/Mikrocontrollern.

    Martin Richter schrieb:

    Was heißt Du hängst fest?

    Ich meinte damit, dass ich nicht mehr aus der while-Schleife rauskomme, da der Wert immer "1" ist.

    Martin Richter schrieb:

    Wenn Da zum Beispeil ein WM_PAINT erzeugt wird und Du ihn einfach entfernst ohne das er bearbeitet wird, dann wird einfach ein neuer erzeugt.
    Ohne dass Du nachrichten auch bearbeiten last funktioniert das nicht.
    Du solltest vor allem auchnicht darauf kommen in der Nachrichten Behandlung selbst gleich wieder eine Nachrichten Behandlung zu starten.

    Wegen der WM_PAINT-Sache muss ich mich mal einlesen, wie ich das zu tun habe...

    Martin Richter schrieb:

    Wenn dort ein DoModal läuft, dann bau doch einfachnur eine Nachrichtenbehandlung in die DlgProc ein.

    DoModal geht nicht. Ich muss das Fenster auf jedem Fall minimieren können (besser noch, auch "verschwinden lassen" können). Zur gleichen Zeit muss ein anderes Fenster/Programm bedienbar sein.



  • Irgendwie bin ich wegen der Sache, dass ich auch Fenster-eigene Sachen (wie z.B. WM_PAINT) mit abarbeiten muss, ein wenig stutzig geworden. Eigentlich wollte ich die Nachrichten auch ohne zusätzliche Fensterbehandlungen austauschen können. Bin ich hier wohl mit meinem "PeekMessage" und "PostThreadMessage" auf dem falschen Weg? (Wenn ich in der Sprache Qt geschrieben habe, waren Nachrichten zwischen threads auch nie an Fenstern gekoppelt)


  • Mod

    Du kannst nicht einfach Nachrichten aus der Schleife entfernen ohne sie zu bearbeiten.
    Also im Minimum. PeekMessage mit remove und danach TranslateMessage und DispatchMessage. Aber in keinem Fall in der DlgProc! Das ist Unfug.
    Wo sitzt den bitte DeineNachrichtenschleife in dem Thread startFFDialogBox?

    Wieso soll DoModal nicht gehen? Das geht auch mit minimieren und so weiter...
    Du kannst auch einen Dialog versteckenund die Schleife weiterlaufen lassen.
    Du benötigst in jedem Fall eine echte Nachrichtenschleife!



  • @Hans_Wurst
    Ich glaube nicht dass PeekMessage jemals WM_QUIT zurückliefern wird. Du musst schon im msg nachgucken was du bekommen hast.

    Und der Test auf -1 ist IMO sowieso ganz falsch. -1 ist bei GetMessage ein spezieller Returnwert, nicht aber bei PeekMessage . Bei PeekMessage immer nur auf == 0 oder != 0 testen.

    Bau dein Programm erstmal entsprechend um, und dann teste nochmal.



  • Also ich habe jetzt mal versucht eure Tipps umzusetzen. Ich merke aber, dass ich einfach zu unerfahren bin, in der Windowsprogrammierung.

    Ich sollte für den Anfang besser einfach nur meinen dialog-thread haben (die ja bereits Nachrichtenschleifen verwenden) und einen zweiten thread, von dem aus einfach nur ein string in der dialogbox vom dialog-thread ausgegeben wird.

    Ich habe versucht solch ein Beispiel im Netz zu finden, konnte aber immer nur einzelne Codeschnipzel finden. Kennt jemand eine Seite auf der ich mich darüber ein wenig einlesen kann? Am leichtesten würde es mir fallen, wenn man ein fertiges (Minni-)Projekt hat, in dem man mit dem debuger schauen kann, was passiert.



  • Es tut mir leid, wenn ich schon wieder um Unterstützung bitte, aber es will einfach nicht laufen.

    Für den Test erster Schritte bin ich nun erst mal wieder zurück auf das fertige Beispielprogramm von Windows zurück gegangen, welches man auch hier sehen kann:
    http://www.getcodesamples.com/src/AF47D42D/8B839A3B

    Dort wird ein Fenster erzeugt und besitzt somit auch schon eine Nachrichtenschleife. Nachdem ich nun schon ewig das Internet durchforste, scheine ich in diesem Beispiel tatsächlich nur einem neuen case-Fall einfügen zu müssen um bei (z.B.) dem Tastendruch auf "a" agieren zu können:

    INT_PTR CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
    {
        switch( msg )
        {
            case WM_KEYDOWN:
                if (wParam == 0x41)
                {
                    MessageBox( hDlg, _T("a wurde gedrückt"), _T("Taste"), MB_OK );
                }
                else
                {
                    MessageBox( hDlg, _T("Fail"), _T("Taste"), MB_OK );
                }
                break;
        // ....
    

    Der neu eingefügte case-Fall wird allerdings nie bedient.



  • Dialoge bekommen keine WM_KEYDOWN Nachrichten geschickt (weil sie nie den Input-Focus haben), so einfach ist das.

    https://www.google.com/search?hl=en&q=dialog+wm_keydown



  • So, ich konnte nun mein kleines Progrämmchen fertig stellen. Recht herzlichen Dank an alle, die mich hier unterstützt haben.


Anmelden zum Antworten