PostMessage mit Parameter std::vector<CString>?



  • Hallo zusammen... und ja ich bin es schon wieder :(...

    Aber ich habe unter dem Artikel hier folgende Aussage gefunden:

    Das tut in den Augen weh und gehört verboten. Veränderungen an GUI-Komponenten immer mit PostMessage realisieren. Ausführliche Begründungen gibst wie immer bei Google.

    "Gegoogeld" habe ich jetzt schon und ich verstehe ja auch das es so nicht sein sollte :)...

    Also ich sende jetzt Nachrichten per PostMessage an den Cwnd und den Cwnd selber übergebe ich nicht als Zeiger an den Thread (bzw. die Methode die im Thread läuft) sondern per HWND und dann per Cwnd::GetFromHwnd. Den Zeiger den ich dann habe kann ich getrost verwenden und die PostMessage Methode aufrufen.

    Nun würde ich gerne eine Nachricht mit Parametern senden und zwar am besten einen std::vector<CString> :). Da es sich aber um einen PostMessage aufruf handelt und ich nicht weiß wann (und ob) die Nachricht bearbeitet wird kann ich auch keinen Zeiger auf den Vector übergeben... denn sonst hab ich Memory Lecks oder aber Zugriffsfehler...

    Kennt jemand eine Lösung mit der man auch andere Dinge per PostMessage versenden kann :)? Ich wäre dafür sehr dankbar.



  • Tja, da bin ich auch schon wieder 😉

    PostMessage(..) hat drei Parameter. Das ist ein UINT, ein WPARAM (32 Bit Wert) und ein LPARAM (32 Bit Wert). Nun kannst du mit WPARAM und LPARAM zwei Werte and das Empfängerfenster übergeben. Das könnten ganz banale 32-Bit Werte sein (numerischer Natur) oder Adressen auf andere Daten (z.B auf einen std::vector<CString>). Bei Adressen musst Du casten. Nehmen wir den Einfachen Fall eines Strings:

    // das Dingens muss gültig sein, also entweder auf dem Heap (=> new), oder sonst wie
    static CSrting sGlobalString = "Ich bin ein Text";
    
    // "Der" Thread 
    DWORD WINAPI ThreadProc(LPVOID lpParameter )
    {
      ...
    
      // hWndReceiver bekommt eine WM_USER Message mit Parametern
      ::PostMessage( hWndReceiver, WM_USER, (WPARAM)&sGlobalString, 0 );
    
      ...
    }
    

    Und nun das Fenster (Dialog, View, oder was Dir sonst einfallen mag)

    BEGIN_MESSAGE_MAP(CDlgMenuApp, CWinApp)
      ...
      ON_MESSAGE( WM_USER, OnCatchWMUserMessages )
      ..
    END_MESSAGE_MAP()
    
    ...
    
    LRESULT CDlgMenuApp::OnCatchWMUserMessages(WPARAM wParam, LPARAM lParam)
    {
      // damit bekommst Du dann den "geposteten" string
      CString sMyString( (CString *)(wParam) );  
    
      ...
    }
    

    Das funktioniert mit allen beliebigen Datentypen. Dir muss nur bewusst sein, dass eine gepostete Message nicht unbedingt sofort verarbeitet wird. Die Werte, die über die Parameter übergeben werden, müssen natürlich im Message-Handler Deines Fensters gültig sein. Also können das keine Stack-Variablen aus Deinem Thread sein!

    Was immer Du erreichen willst, ich glaube, Du musst noch etwas über Threads und deren Synchronisation lesen 😉

    Gruss, Gio



  • Danke Gio für das ausführliche Beispiel...

    So hatte ich mir das auch schon gedacht... nur beim googeln bzw. in dem angesprochenen Artikel steht irgendwo das eine durch PostMessage gesendete Nachricht nicht mit sicherheit ausgeführt wird.

    Nehmen wir also nun mal an ich lege einen neuen CString mit new auf dem Heap an und zerstöre diesen wenn die Nachricht bearbeitet wurde. Was passiert aber mit dem CString wenn die Nachricht nicht bearbeitet wird? => Memory Leak :)...

    Ein anderer Fall ist es wenn das Programm beendet wird bevor alle Nachrichten abgearbeitet wurden... wer sorgt dann dafür das die Objekte im Speicher entfernt werden?!

    Was immer Du erreichen willst, ich glaube, Du musst noch etwas über Threads und deren Synchronisation lesen

    Das glaube und weiß ich auch :)... Nur ist es immer schwer irgendwo anzufangen ;).



  • du machst das super jochen_82:) genau deine fragen hier helfen mir auch immer weiter;)



  • Ich hab folgendes bei CodeProject gefunden:

    Sending and posting CString to windows via PostMessage, SendMessage



  • Ich hab das jetzt auch mal bei mir eingebunden... jedoch steht in dem CMessageString immer nur "Müll" drin...

    Ich rufe das folgende auf:

    CString sMessage = "HALLO";
    	CMessageString* pString = new CMessageString(sMessage);
    

    Natürlich wird dann der folgende Konstruktor verwendet:

    CMessageString::CMessageString(const CString& string) : CString(string) {
    	m_Manager.Add(this);
    }
    

    Aber wenn ich mir das nun ausgeben lasse

    TRACE("Ausgabe: %s %s\n", sMessage, (*pString));
    

    Steht in der Ausgabe:

    Ausgabe: HALLO [C

    Hat jemand schonmal mit dieser Klasse gearbeitet? Hat jemand einen schnellen Lösungshinweis?



  • 😉 Die Tücke einer abgeleiteten Klasse! Mach mal:

    TRACE("Ausgabe: %s %s\n", sMessage, (CString)(*pString));
    

    oder

    TRACE("Ausgabe: %s %s\n", sMessage, (const char *)(*pString));
    

    Die Klasse CString selbst hat den Operator ***const char **** implementiert. Das erwartet ***TRACE(..)***. CMessageString dagegen implementiert diesen Operator nicht. Deswegen musst Du casten.

    Gruss, Gio


Anmelden zum Antworten