Cum pot trimite un CString prin PostMessage ?

Intrebari legate de programarea cu biblioteci precum MFC, ATL, WTL si GDI+.
Post Reply
mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Cum pot trimite un CString prin PostMessage ?

Post by mesajflaviu » 26 Nov 2010, 10:16

Cum se poate trimite un CString prin ::PostMessage(...) ? Si apoi cum se poate "recupera" ? Eu l-am trimis ca lParam , dar nu am reusit sa-l recuperez pentru a-l folosi ...

Nu cred ca are rost sa pun codul pe care l-am incercat eu de vreme ce nu functioneaza ...



User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum pot trimite un CString prin PostMessage ?

Post by Marius Bancila » 26 Nov 2010, 10:25

Atentie, PostMessage pune mesajul in coada ferestrei si revine. Apelantul continua ruleze, nu e cu blocare ca la SendMessage. Din aceasta cauza, nu sti cand este tratat mesajul trimis. Probabil tu folosesti o variabila locala, care iese din scop si se distruge inainte ca destinatarul sa trateze mesajul tau. Ar fi mai multe optiuni. Prima ar fi sa folosesti SendMessage, dar asta depinde de ce faci tu exact. Alta optiune e sa folosesti o variabila CString care nu e distrusa in momentul in care se trateaza mesajul; poate fi de exemplu membra a unei clase, stiu eu. Si o a treia ar fi sa aloci variabila CString pe heap, sa pasezi pointerul la ea odata cu PostMessage, iar in handlerul mesajului dupa ce ai folosit-o sa o stergi. Atentie, aici ai o problema daca trimiti acelasi mesaj la mai multe ferestre si fiecare vrea sa stearga acelasi obiect de pe heap.
Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot trimite un CString prin PostMessage ?

Post by mesajflaviu » 26 Nov 2010, 10:43

Acel mesaj il trimit dintr-un thread , deci nu pot folosi SendMessage ... asta inseamna ca nu am nici o solutie sigura ? ( Ultima solutie propusa de tine are o rezerva )

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum pot trimite un CString prin PostMessage ?

Post by Silviu Ardelean » 26 Nov 2010, 11:37

Cum sa nu poti?
O faci ca si cu PostMessage() si in plus ai avantajul ca sti cand mesajul a fost trata in thread-ul destinatie... spre deosebire de situatia in care folosesti PostMessage(). In threadul curent se opreste executia pana iti vine raspunsul ca s-a tratat mesajul tau.

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum pot trimite un CString prin PostMessage ?

Post by Silviu Ardelean » 26 Nov 2010, 12:58

Iti recomand ideea sa folosesti SendMessage() si alocarea temporara pe heap.

Iata un exemplu:

Code: Select all

// in threadul tau de unde vrei sa trimiti mesajul
CString* sOutMsg = new CString();
*sOutLog = _T("your message");		

pThis->SendMessage(MYMSG_UpdateData,  0, (LPARAM) sOutMsg);	
Iar in threadul principal ai o metoda de tratare a mesajului tau:

Code: Select all

LRESULT CYourMainThreadClass::OnYourMessagehandler(WPARAM wParam, LPARAM lParam)
{
	CString* pobject = (CString*)lParam;

	if(pobject != NULL)
	{
		UpdateData(TRUE);

		m_sData += *pobject;
		m_sData += L" \r\n";
		delete pobject;

		UpdateData(FALSE);
	}
		
	return 0;
}
Daca vrei sa trimiti mesajul intre mai multe thread-uri secundare (nu thread-ul principal) atunci trebuie sa intrii la sincronizari.
Last edited by Silviu Ardelean on 26 Nov 2010, 17:58, edited 1 time in total.

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Cum pot trimite un CString prin PostMessage ?

Post by cristianamarie » 26 Nov 2010, 14:08

mesajflaviu wrote:Cum se poate trimite un CString prin ::PostMessage(...) ? Si apoi cum se poate "recupera" ? Eu l-am trimis ca lParam , dar nu am reusit sa-l recuperez pentru a-l folosi ...

Nu cred ca are rost sa pun codul pe care l-am incercat eu de vreme ce nu functioneaza ...
Nu ai cum sa trimiti nici un pointer direct prin PostMessage.

1. Poti sa il aloci cu un new CString si faci post (dar mai bine LPTSTR alocat decit CString), dar exista riscul sa nu fie procesat si ramine leak.
2. Poti sa il pui intr-o tabela globala de CString, il inserezi, iei indexul, si trimiti indexul in LPARAM in PostMessage. Trebuie sa rezolvi concurenta aici, dar fiind doar insert de unde faci post si read de unde vine mesajul, nu prea sint mari probleme.
3. IPC (dar WM_COPYDATA nu merge cu post, doar send) - ce mecanism vrei tu, dar e o variatiune a punctului 2.
Nuclear launch detected

User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum pot trimite un CString prin PostMessage ?

Post by Marius Bancila » 27 Nov 2010, 00:23

Nu ai cum sa trimiti nici un pointer direct prin PostMessage.
Ce vrei sa zici? Poti sa trimiti un pointer, dar trebuie sa fie clar ca obiectul pointat nu poate sa fie distrus inaintea tratarii mesajului. Daca conditia asta se indeplineste nu sunt probleme. Altfel da, sigur ca nu merge.

Silviu, in cazul folosirii lui SendMessage nu vad de ce ai mai aloca obiectul CString pe heap, si cu atat mai putin de ce handlerul distruge obiectul, ar putea s-o faca cel care trimite mesajul.
Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

User avatar
Silviu Ardelean
Senior
Senior
Posts: 1175
Joined: 12 Jul 2007, 09:22
Judet: Timiş
Location: Timisoara
Contact:

Re: Cum pot trimite un CString prin PostMessage ?

Post by Silviu Ardelean » 27 Nov 2010, 01:00

Marius Bancila wrote:Silviu, in cazul folosirii lui SendMessage nu vad de ce ai mai aloca obiectul CString pe heap, si cu atat mai putin de ce handlerul distruge obiectul, ar putea s-o faca cel care trimite mesajul.
Intr-adevar , aceasta abordare se preteaza obligatoriu pentru PostMessage(). Pentru SendMessage() nu mai e neaparat necesara alocarea pe heap.

User avatar
cristianamarie
Membru++
Membru++
Posts: 480
Joined: 12 Mar 2009, 18:47
Judet: Iaşi
Location: Iasi

Re: Cum pot trimite un CString prin PostMessage ?

Post by cristianamarie » 27 Nov 2010, 01:12

Marius Bancila wrote:
Nu ai cum sa trimiti nici un pointer direct prin PostMessage.
Ce vrei sa zici? Poti sa trimiti un pointer, dar trebuie sa fie clar ca obiectul pointat nu poate sa fie distrus inaintea tratarii mesajului.
Da, evident. Nu m-am exprimat fericit - normal ca se poate, dar trebuie rezolvate lifetime+owner+access, da.
Nuclear launch detected

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot trimite un CString prin PostMessage ?

Post by Ovidiu Cucu » 27 Nov 2010, 16:21

  1. Daca mesajul este postat la un singur thread aflat in acelasi proces, de obicei schema aloca si posteaza -> proceseaza si elibereaza, merge fara prea multe batai cap, sincronizari, si alte briz-brizuri; se poate spune: coada de mesaje asigura "sincronizrea".
    La cazul asta ar mai trebui totusi adaugat: string-ul / bufferul este transmis cu o frecventa rezonabila si este procesat intr-un timp rezonabl in asa fel incat sa nu "dea-n foc" :) coada de mesaje.
  2. Daca mesajul este postat la mai multe threaduri, atunci da, trebuie sa ma asigur ca nu se sterge pointerul pasat inainte ca mesajul sa fie procesat in toate thread-urile.
  3. Daca mesajul este pentru un thread din alt proces, atunci Post(Thread)Message sare din schema si trebuie folosita o alta metoda de IPC.

Pun pariu ca probema lui mesajflaviu se incadreaza in cazul 1. :)
Am atasat un exemplu in care se posteaza un pointer la CString din N thread-uri worker la fereastra principala a aplicatiei.
E totusi o mica sincronizare acolo, nu pentru a nu se incurca thread-urile intre ele, ci pentru a a asigura ca fiecare thread isi termina treaba si a evita astfel problema memory leaks de care amintea Cristian.
Attachments
TestMsg.zip
(8.89 KiB) Downloaded 182 times

mesajflaviu
Membru++
Membru++
Posts: 686
Joined: 10 Sep 2008, 21:40
Judet: Cluj

Re: Cum pot trimite un CString prin PostMessage ?

Post by mesajflaviu » 29 Nov 2010, 12:09

Va multumesc tuturor pentru solutii , ( Ovidiu , e didactic exemplul , multumesc ) .
Si eu am rezolvat intr-un mod similar problema :

In thread am :

Code: Select all

CString sTemp = "Unknown error";			
CString* sError = new CString(sTemp);
::PostMessage(m_hwndView,WM_USER_WORK_ERROR,(WPARAM)0,(LPARAM)(LPCSTR)sError);
iar in evenimentul care trateaza mesajul :

Code: Select all

LRESULT CRegistruCoView::OnWorkError(WPARAM wParam, LPARAM lParam)
{
	CString* sError = (CString*)lParam;
	CString& sTemp = *sError;
	GetDocument()->DoSomething(sTemp);
	delete sError;

	return 0;
}

User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3776
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

Re: Cum pot trimite un CString prin PostMessage ?

Post by Ovidiu Cucu » 29 Nov 2010, 12:52

O mica observatie: acel sTemp n-are nici un rost. Mai mult incurca decat ajuta. ;)

Este suficient:

Code: Select all

   CString* pError = new CString(_T("Unknown error"));
   ::PostMessage(...(LPARAM)pError);
respectiv

Code: Select all

   CString* pError = (CString*)lParam;
   GetDocument()->DoSomething(*pError);
   delete pError;

Post Reply