2009-08-24 8 views
15

Dans mon application, je souhaite envoyer un message à une boîte de dialogue à partir d'un fil différent. Je veux passer une référence de classe dérivée std :: exception à la boîte de dialogue.Comment envoyer une chaîne via PostMessage?

Quelque chose comme ceci:

try { 
     //do stuff 
} 
catch (MyException& the_exception) { 
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, 0); //send the_exception or the_exception.error_string() here 
} 

Je souhaite recevoir le message dans ma boîte de dialogue et montrer l'erreur qui est the_exception.error_string()

LPARAM CMyDlg::SomeError(WPARAM, LPARAM) 
{ 
    show_error(????? 
    return 0; 
} 

passer le std::string the_exception.error_string() en utilisant PostMessage serait également ok, je deviner.

Répondre

12

Vous ne pouvez pas passer l'adresse de la chaîne dans PostMessage, car la chaîne est probablement locale dans la pile. Au moment où l'autre fil le ramasse, il aurait pu être détruit. Au lieu de cela, vous devez créer une nouvelle chaîne ou objet d'exception via new et transmettre son adresse à l'autre thread (via le paramètre WPARAM ou LPARAM dans PostMessage). L'autre thread possède alors l'objet et est responsable de sa destruction.

Voici quelques exemples de code qui montre comment cela pourrait se faire:

try 
{ 
    //do stuff 
} 
catch (MyException& the_exception) 
{ 
    PostMessage(MyhWnd, CWM_SOME_ERROR, 0, new string(the_exception.error_string)); 
} 


LPARAM CMyDlg::SomeError(WPARAM, LPARAM lParam) 
{ 
    // Put in shared_ptr so it is automatically destroyed. 
    shared_ptr<string> msg = reinterpret_cast<string*>(lParam); 

    // Do stuff with message 

    return 0; 
} 
+1

Salut, merci beaucoup pour votre réponse. vous avez oublié la distribution dans LPARAM PostMessage (MyhWnd, CWM_SOME_ERROR, 0, réinterprétation_cast (nouvelle chaîne (the_exception.error_string))); Et pourquoi ne pas utiliser auto_ptr à la place: std :: auto_ptr msg (reinterpret_cast (lParam)); Parce que cela montre le transfert de propriété. – rec

+0

ouch, mauvais formatage test de saut de ligne test de saut de ligne – rec

+1

N'est-ce pas une fuite de mémoire? Où détruisez-vous une nouvelle chaîne()? –

1

Tant que vous êtes dans un processus, il vous suffit de passer un pointeur vide * et de vous soucier de la durée de vie de l'objet.

Si c'est SendMessage, vous pouvez le passer dans LPARAM sous la forme d'un cast void *, et le client le rediffusera dans votre type de chaîne. Parce que SendMessage est synchronous, vous êtes en sécurité:

Si la fenêtre spécifiée a été créé par le thread appelant, la fenêtre procédure est appelée immédiatement comme un sous-programme . Si la fenêtre spécifiée a été créée par un thread différent, le système bascule sur ce thread et appelle la procédure de fenêtre appropriée . Les messages envoyés entre les threads sont traités uniquement lorsque le thread de réception exécute le code de récupération . Le fil d'envoi est bloqué jusqu'à ce que le fil de réception traite le message

Si vous voulez utiliser PostMessage alors vous aurez à faire au large d'une main explicite parce que l'appel est asynchrone: faire une copie de la chaîne sur le tas et en appelant le PostMessage vous avez passé la responsabilité de supprimer à la calee (le dialogue).

Si vous sortez du processus (MyhWnd appartient à un processus différent), alors c'est une toute autre histoire et vous devrez rassembler votre message en quelque chose comme un atome global.

+0

OK, il est temps de rentrer à la maison. J'ai répondu comme si l'OP posait des questions à propos de SendMessage et tout le problème était PostMessage ... –

+1

Bon à signaler que SendMessage est synchrone et vous n'avez pas à vous inquiéter du transfert de propriété.Cependant, SendMessage peut être re-entrant, c'est-à-dire, lors de l'appel à SendMessage votre thread peut être en train de pomper des messages, donc vous devez faire attention que votre passage à l'autre thread ne peut pas être muté dans l'un de vos wndprocs. – Michael

+0

IMO c'est la bonne réponse: utilisez SendMessage et copiez le message dans le thread de réception après l'avoir obtenu. Pas besoin de vous mettre en place la bombe avec des problèmes PostMessage/synchronisation compliqués pour une simple passe de chaîne (une chaîne que je présume sera plutôt courte). – Roel

0

Tant que vous savez que votre fenêtre (ou instance de CMyDlg) seront encore là après avoir affiché le message que vous pouvez simplement stocker la chaîne d'erreur dans une variable membre et lisez ceci dans votre gestionnaire de messages.

Questions connexes