Text-Strings aus Thread in den Dialog bringen...



  • Bitte schlagt mich nicht, ich habe hier wirklich erstmal gesucht, aber ich finde nichts dazu:
    Ich möchte über eine User-definierte Message Text-Meldungen von einem Thread an meinen Dialog senden und sie dort weiterverarbeiten.
    Aber wie genau kann ich in meiner Nachricht Text unterbringen?

    ::PostMessage(hWnd, WM_USER_THREAD_INFO, (WPARAM)[HIER ZEIGER ODER REFENZ AUF TEXT?], 0);
    

    Thx schonmal für Eure Hinweise 🙂
    Gruß T.



  • Wenn's nur an ein edit/static oder so gehen soll:

    LPCTSTR str = _T("Hallo Welt!");
    PostMessage(hwnd_of_Control, WM_SETTEXT, 0, (LPARAM) str);
    
    1. Text geht ins LPARAM
    2. Zeiger auf text nach LPARAM gecastet
    3. Die Win32 API stellt bei WM_SETTEXT sicher, daß der String kopiert wird
      (ist wichtig!! der String könnte ja temporär sein: z.B.
      [cpp]
      if (foo)
      {
      CString s = ....;
      PostMessage(hwnd,WM_MY_MESSAGE, 0, (LPARAM) (LPCTSTR) s);
      // < hier wird s freigegeben
      // kann aber sein der message-handler wurde noch gar nicht aufgerufen -
      // lParam enthält ungültigen Zeiger
      }

    Wenn du den String in der Dialog-Klasse noch nachbearbeiten willst, wird es etwas komplizierter:

    a) entweder SendMessage, das wartet bis die message abgearbeitet wurde (bremst aber evtl.)
    b) allozierst den string im thread und gibst iihn im message-Handler frei (musst aber sicherstellen, daß der Handler auch wirklich aufgerufen wird, und nicht z.B. der Dialog zwischendrin freigegeben wird)
    c) String in einem geshareten Puffer / CString-Variable (mit Critical Section schützen!)
    d) ein Mechanismus wie die MFC Temp Maps (allozierte objekte werden in einem Container gespeichert und im OnIdle-Handler freigegeben)



  • OK, das waren schonmal gute Tipps!
    Jetzt habe ich sinngemäß folgenden Code geschrieben:

    UINT CMyDlg::thrFunction(LPVOID pParam)
    {	
    	CMyDlg* pDlg = (CMyDlg*)pParam;
    	HWND hWnd = pDlg->m_hWnd;
    	HWND hCtrl = ::GetDlgItem(hWnd,IDC_INFO_DISPLAY);
    	ASSERT(IsWindow(hWnd)); 
    	ASSERT(IsWindow(hCtrl));
    	CString strInfo = _T("BlaBla...");
    	//Funzt nicht:
    	//::PostMessage(hCtrl,WM_SETTEXT ,0,(LPARAM)(LPCTSTR)strInfo);
    	//Funzt:
    	pDlg->GetDlgItem(IDC_INFO_DISPLAY)->SetWindowText(strInfo);
    	return (UINT)0;
    }
    

    Fragen:
    1.Wieso kommt bei Postmessage nichts in meinem Static an?
    2.Wäre die Variante mit SetWindowText wirklich threadsafe? SetWindowText basiert ja auf WM_SETTEXT, im Prinzip sollte es ja OK sein, oder?

    Thx schonmal + Gruß 🙂



  • so, nun habe ich's mit einem API-Aufruf gemacht:

    ::SetDlgItemText(hWnd, IDC_INFO_DISPLAY, strInfo);
    

    Bis dann! 😉



  • Mag sein das ich mich mit dem "PostMessage behandelt WM_SETTEXT speziell" irre - ich kann jedenfalls nix dazu in der MSDN finden. 😉

    Die WindowProc wird immer in dem Thread ausgefuehrt, der das Fenster erzeugt hat. SendMessage wartet immer, bis die WIndowProc abgearbeitet ist, damit ist das SetWindowText (bzw. ein SendMessage(WM_SETTEXT) threadsicher.

    PostMessage wäre effektiver, da der Threadswitch nicht sofort erzwungen wird. Wenn du den Thread nur hast, damit das Userinterface "aktiv" bleibt, macht das ueberhaupt nix. Wenn du allerdings prozessorintensives Background-Prozessing hast, das wirklich so schnell wie möglich gehen soll, und die Textupdates recht haeufig kommen, würde ich zu einem mit einer Critical Section geschützten geshareten CString greifen.

    😉 WM_SETTEXT usw. an einen anderen PROZESS werden korrekt behandelt.


Anmelden zum Antworten