Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[MFC] UpdateAllViews et les Items

26 réponses
Avatar
TigrouMeow
Bonsoir,

J'ai deux questions sur les MFC, décidément je suis plein de
problèmes ces derniers temps.

Bon je tiens à parler un tout petit peu de l'architecture de mon
programme avant. Rien d'extraordinaire, une doc, des views
associés, et à côté de ça je lance un thread. Ce thread a des
impacts sur mon doc, il renseigne régulièrement des variables
qui s'y trouvent.

Maintenant j'ai deux questions.

1) Quand je fais un pDoc->UpdateAllViews(NULL) depuis
une de mes views, pas de problème. Par contre, si je l'appelle
depuis mon thread séparé, j'ai un "Debug Assertion Failed".

Voici le stacktrace si ça peut aider :
- mfc71d.dll!CWnd::AssertValid() Ligne 888 + 0x43 C++
- mfc71d.dll!CCtrlView::AssertValid() Ligne 563 C++
- WinTrace.exe!CListe::AssertValid() Ligne 25 C++
- mfc71d.dll!AfxAssertValidObject ...
- mfc71d.dll!CDocument::UpdateAllViews ...

Pour info, le pointeur vers pDoc et le même que ça soit dans
mon thread que dans mes views, j'ai vérifié sa valeur et il n'y
a aucun problème.

2) Dans une TreeView et une ListView, est-il possible de
spécifier une couleur spéciale pour un certain item ? Si oui,
bien sur, comment ? :)

Je vous remercie beaucoup, surtout surtout sur la 1ère
question car ça me bloque vraiment dans ma progression,
sinon la deuxième question je trouverai ça génial si il y
avait un moyen pas compliqué (sans recoder ou modifier
un widget...).

--
Meow ;o)

10 réponses

1 2 3
Avatar
TigrouMeow
"Patrick Philippot" a écrit dans le
message de news: d38uei$uf8$
TigrouMeow wrote:
J'y comprends rieeeeeeeeeeeeen, merci une fois de plus de m'aider...



La méthode que je vous ai proposée doit fonctionner. Mais cela suppose que
vous compreniez ce que vous faites, sinon il faudra que vous dicte le
code. On en revient au débat de départ: si vous ne maîtrisez pas les bases
des MFC, on risque de tourner en rond.

C'est un projet urgent ou bien vous avez le temps de prendre le temps?



C'est un projet assez urgent, j'ai une semaine, et j'ai beaucoup beaucoup
de choses à faire à côté. Enfin le reste me posera pas trop trop de
problèmes car j'ai déjà fait deux autres programmes avec les MFC
mais c'est la première fois que je fais un thread séparé comme ça :(
Avatar
TigrouMeow
"Patrick Philippot" a écrit dans le
message de news: d38ueh$uf8$
TigrouMeow wrote:
J'ai essayé d'implémenté comme vous me l'avez dit, donc dans mon doc
je trouve un :
BEGIN_MESSAGE_MAP(CWinTraceDoc, CDocument)
ON_COMMAND(LIBRARY_ADD, AddLibrary)
END_MESSAGE_MAP()

Et la déclaration de la fonction :
void CWinTraceDoc::AddLibrairy()
{
TRACE("AddLibraryn");
}

Et dans l'include du Doc je déclare le prototype comme ça :
afx_msg void AddLibrairy();

Il me sort une erreur :
AddLibrary : identificateur non déclaré.



... à moins que AddLibrairy ne soit pas une faute de frappe, je ne vois
pas...

Suis désolé d'être aussi nul,



Il me semble surtout que vous voulez aller plus vite que la musique. Quand
j'étais petit, on apprenait l'alphabet en commençant par le A et on lisait
les livres et les documentations en commençant par le chapitre 1. On
apprenait les bases puis on construisait dessus. Il paraît que les choses
ne fonctionnent plus comme ça de nos jours, qu'il faut être productif,
gagner du temps, aller vite et construire les gratte-ciel en commençant
par le toit mais c'est dommage, je trouve ça bien pratique, comme méthode
de travail :-) .

mais j'ai de plus en plus l'impression
que la MFC est très très mal faite de partout,



Comme je le disais, il faut d'abord se former à son fonctionnement. Les
MFC ne sont pas l'idéal comparées à d'autres frameworks (comme OWL) mais
elles sont plus solides qu'on ne le dit souvent. En termes de
programmation objet, le design est assez limite mais il ne faut pas
oublier que les MFC ont été conçues pour VC ++ 16-bit et que les
programmes écrits proprement il y a 13 ans pour VC++ 1.0 peuvent être
repris dan sla version actuelle pratiquement tels quels. C'est un avantage
que beaucoup d'entreprises ont apprécié mais cela a été fait au proix de
qulques concessions.



Normalement, je prends mon temps :) J'ai déjà étudié un peu les MFC
et ça marchait très bien pour ce dont j'avais besoin. Et malheureusement
j'ai plus le temps de me pencher sur tout ces problèmes, par contre
je le prendrais pour bien étudier les WinForms (je ne pense pas
revenir au MFC un jour... d'ici que j'arrive dans la vie active je sais pas
si il sera courant de voir des offres d'emploi demandant un ingénieur
spécialisé MFC lol).

Je viens de relancer mon Visual Studio (j'étais parti faire les courses)
et oh surprise, ça compile :/

Par contre je reçois pas le message au niveau de mon doc. Ce qui
m'étonne, c'est qu'on poste un message sur la MainFrame, et
qu'on le récupère au niveau de la doc ! A priori je fais tout comme
vous me l'avez expliqué.

Je récapitule :
1. Je récupère la MainFrame avec AfxGetMainWnd().
2. Dans la classe de mon thread, je met à jour le CWnd*
avec la valeur que j'ai récupéré précédemment.
3. Mon doc contient
BEGIN_MESSAGE_MAP(CWinTraceDoc, CDocument)
ON_COMMAND(LIBRARY_ADD, AddLibrairy)
END_MESSAGE_MAP()
Il contient aussi la fonction AddLibrairy.
4. Dans mon thread, je poste comme ceci sur le CWnd* :
->PostMessage(WM_COMMAND,
MAKEWPARAM((LIBRARY_ADD, 0), 0));

Voilà... ça marche vraiment pas, j'ai mis un TRACE dans la
fonction AddLibrairy mais jamais ça ne s'affiche.

Question subsidiaire :
Le truc c'est que j'aimerais passer en arguments des valeurs
ou des objets. Si je m'embète avec tout ça, c'est que je veux
pas mettre dans mon thread principal (mon application fenetre)
un bouton Rafraichir, ou alors gérer un WM_TIMER toutes
les secondes, ça serait vraiment anti-pro.

Merci encore ;)
Avatar
Patrick Philippot
Bonjour,

TigrouMeow wrote:
4. Dans mon thread, je poste comme ceci sur le CWnd* :
->PostMessage(WM_COMMAND,
MAKEWPARAM((LIBRARY_ADD, 0), 0));



1. J'ai commis une erreur dans le code proposé: essayez en utilisant
l'API ::PostMessage(...) - pas la méthode de CWnd - et en passant le
handle de la fenêtre en premier argument. Passer par le pointeur pose le
même problème que l'appel de UpdateAllViews depuis le thread, je pense.
Voir la page que vous avais déjà proposée:
http://www.mvps.org/vcfaq/mfc/12.htm .

2. Si ça ne fonctionne toujours pas, utilisez
CWnd::SendMessageToDescendants et traitez le message au niveau de la
View.

3. Si ça ne fonctionne toujours pas, envoyez le message directement à la
View. Les messages de commande "cascadent". S'ils ne sont pas traités au
niveau de la vue, par le biais des message maps, ils vont cascader
jusqu'au document. S'ils ne sont pas traités au niveau du document, ils
remontent jusqu'à la mainframe. Il y a une discussion sur cette méthode
là: http://codeproject.com/file/filechange.asp .

4. Vous pouvez aussi récupérer le message au niveau de la mainframe et
faire directement ceci:

CDocument* pDocument = GetActiveDocument();
pDocument->UpdateAllViews(NULL­);


Il y a aussi une solution assez élégante proposée par J-P Franconieri
là:
http://groups-beta.google.com/group/comp.os.ms-windows.programmer.tools.mfc/browse_frm/thread/28e39a8ad93b522b/1aa7e5ab3417a946?q=mfc+UpdateALlviews+%22worker+thread%22&rnum=5#1aa7e5ab3417a946

Il y a nécessairement une de ces solutions (ou une combinaison de ces
solutions) qui fonctionne.

Question subsidiaire :
Le truc c'est que j'aimerais passer en arguments des valeurs
ou des objets.



Créez une structure dont vous passez l'adresse dans le LPARAM du
message.

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Avatar
TigrouMeow
"Patrick Philippot" a écrit dans le
message de news: d3av1c$1m8c$
Bonjour,

TigrouMeow wrote:
4. Dans mon thread, je poste comme ceci sur le CWnd* :
->PostMessage(WM_COMMAND,
MAKEWPARAM((LIBRARY_ADD, 0), 0));



1. J'ai commis une erreur dans le code proposé: essayez en utilisant l'API
::PostMessage(...) - pas la méthode de CWnd - et en passant le handle de
la fenêtre en premier argument. Passer par le pointeur pose le même
problème que l'appel de UpdateAllViews depuis le thread, je pense. Voir la
page que vous avais déjà proposée: http://www.mvps.org/vcfaq/mfc/12.htm .

2. Si ça ne fonctionne toujours pas, utilisez
CWnd::SendMessageToDescendants et traitez le message au niveau de la View.

3. Si ça ne fonctionne toujours pas, envoyez le message directement à la
View. Les messages de commande "cascadent". S'ils ne sont pas traités au
niveau de la vue, par le biais des message maps, ils vont cascader
jusqu'au document. S'ils ne sont pas traités au niveau du document, ils
remontent jusqu'à la mainframe. Il y a une discussion sur cette méthode
là: http://codeproject.com/file/filechange.asp .

4. Vous pouvez aussi récupérer le message au niveau de la mainframe et
faire directement ceci:

CDocument* pDocument = GetActiveDocument();
pDocument->UpdateAllViews(NULL­);


Il y a aussi une solution assez élégante proposée par J-P Franconieri là:
http://groups-beta.google.com/group/comp.os.ms-windows.programmer.tools.mfc/browse_frm/thread/28e39a8ad93b522b/1aa7e5ab3417a946?q=mfc+UpdateALlviews+%22worker+thread%22&rnum=5#1aa7e5ab3417a946

Il y a nécessairement une de ces solutions (ou une combinaison de ces
solutions) qui fonctionne.

Question subsidiaire :
Le truc c'est que j'aimerais passer en arguments des valeurs
ou des objets.



Créez une structure dont vous passez l'adresse dans le LPARAM du message.



Super merci pour la réponse ;) Je surveillais attentivement j'avais peur
de pas avoir de réponse vu que c'est dimanche ;) Bon ma réponse là
est inutile, en fait j'ai à peine lu, je vais lire plus attentivement et
essayer de résoudre le problème, et je vous tiens au courant du succès.
Merci beaucoup encore :P
Avatar
Patrick Philippot
Cherchez également le sample MTRECALC dans votre doc, c'est exactement
ce que vous voulez faire. Désolé, je viens juste de découvrir son
existence.

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Avatar
TigrouMeow
"Patrick Philippot" a écrit dans le
message de news: d3av1c$1m8c$
Bonjour,

TigrouMeow wrote:
4. Dans mon thread, je poste comme ceci sur le CWnd* :
->PostMessage(WM_COMMAND,
MAKEWPARAM((LIBRARY_ADD, 0), 0));



1. J'ai commis une erreur dans le code proposé: essayez en utilisant l'API
::PostMessage(...) - pas la méthode de CWnd - et en passant le handle de
la fenêtre en premier argument. Passer par le pointeur pose le même
problème que l'appel de UpdateAllViews depuis le thread, je pense. Voir la
page que vous avais déjà proposée: http://www.mvps.org/vcfaq/mfc/12.htm .

2. Si ça ne fonctionne toujours pas, utilisez
CWnd::SendMessageToDescendants et traitez le message au niveau de la View.

3. Si ça ne fonctionne toujours pas, envoyez le message directement à la
View. Les messages de commande "cascadent". S'ils ne sont pas traités au
niveau de la vue, par le biais des message maps, ils vont cascader
jusqu'au document. S'ils ne sont pas traités au niveau du document, ils
remontent jusqu'à la mainframe. Il y a une discussion sur cette méthode
là: http://codeproject.com/file/filechange.asp .

4. Vous pouvez aussi récupérer le message au niveau de la mainframe et
faire directement ceci:

CDocument* pDocument = GetActiveDocument();
pDocument->UpdateAllViews(NULL­);


Il y a aussi une solution assez élégante proposée par J-P Franconieri là:
http://groups-beta.google.com/group/comp.os.ms-windows.programmer.tools.mfc/browse_frm/thread/28e39a8ad93b522b/1aa7e5ab3417a946?q=mfc+UpdateALlviews+%22worker+thread%22&rnum=5#1aa7e5ab3417a946

Il y a nécessairement une de ces solutions (ou une combinaison de ces
solutions) qui fonctionne.

Question subsidiaire :
Le truc c'est que j'aimerais passer en arguments des valeurs
ou des objets.



Créez une structure dont vous passez l'adresse dans le LPARAM du message.



J'ai beau tout essayé... j'ai toujours rien, et jamais je ne reçois aucun
message nulle part...

Y'a forcément un truc qui ne vas pas, surtout que vous me dites que
je peux passer mes objects en paramètres, mais QUEL paramètre?
Je n'ai aucun paramètre sur mes fonctions qui sont censés
réceptionner mes messages... c'est des afx_msg void ReceiveMSG().
Si par malheur je met deux paramètres WPARAM et LPARAM, là
le compilo n'aime pas du tout.

Je commence à me demander si tous mes problèmes ne viennent pas
d'une macro qui s'est ajouté ou supprimé quelquepart et que tout
le reste dysfonctionne......
Avatar
TigrouMeow
"Patrick Philippot" a écrit dans le
message de news: d3b0s9$1mtb$
Cherchez également le sample MTRECALC dans votre doc, c'est exactement ce
que vous voulez faire. Désolé, je viens juste de découvrir son existence.



Merci c'est en cours de download :)
Avatar
TigrouMeow
"Patrick Philippot" a écrit dans le
message de news: d3b0s9$1mtb$
Cherchez également le sample MTRECALC dans votre doc, c'est exactement ce
que vous voulez faire. Désolé, je viens juste de découvrir son existence.



Au fait, si vous voulez je peux vous envoyer le programme, vous verrez
peut-être directement le problème... Car bon je pense vraiment avoir
compris les techniques que vous m'avez proposer sauf qu'elle ne
marche jamais ! :( J'ai lu tous les liens, la MSDN, tout partout, et
jamais ça marche, et pourtant... je crois que j'ai tout essayé...
Avatar
Patrick Philippot
TigrouMeow wrote:
Au fait, si vous voulez je peux vous envoyer le programme, vous verrez
peut-être directement le problème...



Je pense que le sample MTRECALC est suffisamment clair. Cette appli
lance un "worker thread" qui envoit un message privé WM_USER_RECALC_DONE
quand il veut que la vue soit rafraîchie, le message est réceptionné par
la vue qui avise le document de l'événement et ce dernier déclenche
l'UpdateAllViews.

On ne peut pas rêver mieux; c'est exactement ce que vous voulez faire.
Il ne vous reste qu'à vérifier la conformité de votre code.

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
Avatar
Patrick Philippot
TigrouMeow wrote:
Y'a forcément un truc qui ne vas pas, surtout que vous me dites que
je peux passer mes objects en paramètres, mais QUEL paramètre?
Je n'ai aucun paramètre sur mes fonctions qui sont censés
réceptionner mes messages... c'est des afx_msg void ReceiveMSG().
Si par malheur je met deux paramètres WPARAM et LPARAM, là
le compilo n'aime pas du tout.



Regardez dans MTRECALC. Le message privé est réceptionné dans la vue en
surchargeant OnMessage (macro ON_MESSAGE) et ce handler accepte bien un
WPARAM et un LPARAM).

--
Patrick Philippot - Microsoft MVP
MainSoft Consulting Services
www.mainsoft.fr
1 2 3