Utilisateur anonyme
-
26 juin 2007 à 14:51
Utilisateur anonyme -
27 juin 2007 à 10:58
Bonjour!
Je réalise une application (MFC) qui comporte une boite de dialogue où je trace un graphique.
Cette boite de dialogue comporte quelques controles (boutons, Cedit...) à gauche, et à droite le graphique (qui est dessiné dans la fonction OnPaint). J'ai un thread qui envoie à intervalles réguliers un message à ma boite de dialogue, lorsque ce message est intercepté, je met à jour le graphique grâce à InvalidateRect(CRect,TRUE), CRect ne comportant que la partie droite de ma boite de dialogue (uniquement la partie graphique).
Lorsque je compile en mode débug, tout se passe bien, mais lorsque je compile en mode Release, un erreur
de mémoire se produit ("la mémoire ne peut pas être read").
Cette erreur se produit uniquement lorsque le pointeur de la souris passe sur un controle, ou lorsque je déplace ma fenetre. De plus, si je rafraichi ma fenetre avec la méthode Invalidate(), l'erreur se produit immédiatement, de même si le CRect de ma méthode InvalidateRect(CRect,TRUE) comporte la partie contenant les controles.
Je suppose donc que c'est le rafraichissement des controles qui pose problème, mais je ne comprend pas où est l'erreur, et encore moins comment la corriger...
cs_aardman
Messages postés1905Date d'inscriptionmercredi 22 janvier 2003StatutMembreDernière intervention17 septembre 20123 26 juin 2007 à 16:46
Salut,
Si tu dessines toi même le fond de ton graphique dans le OnPaint(), tu peux juste faire InvalidateRect(0,FALSE).
Si les boutons sont directement positionnés sur la fenetre ou tu
dessines, tu peux ptet essayer de mettre le style WS_CLIPCHILDREN a la
fenetre ou tu dessines.
Et enfin pour les erreurs, sans code on ne peux pas faire grand chose.
Finalement en combinant vos 2 réponses ça marche très bien donc encore merci... J'avais du faire une mauvaise manip dans mon OnPaint() à force de tout bidouiller...
Je met le code pour ceux que ça intéresse, il permet donc de repeindre une fenetre depuis un thread, en evitant l'effet de scintillement.
void COscilloscope::OnPaint()
{
CPaintDC fdc(this); // device context for painting
//mise en place du double-buffering
CDC dc;
dc.CreateCompatibleDC(pDC);
//on y ajoute un bitmap pour agrandir dc
CBitmap memBmp;
memBmp.CreateCompatibleBitmap(pDC, lRect.Width(), lRect.Height());
CBitmap* OldBmp = dc.SelectObject(&memBmp);
//On va peindre le fond
CBrush backBrush(RGB(250,250,250));
dc.FillRect(lRect,&backBrush);
//Ces trois fonctions permettent de dessiner sur la boite de dialogue
DrawLine(&dc);
DrawRepere(&dc);
DrawGraph(&dc);
//on bascule dc vers fdc
fdc.BitBlt(0,0,lRect.Width(),lRect.Height(),&dc,0,0,SRCCOPY);
dc.SelectObject(OldBmp);
dc.DeleteDC();
memBmp.DeleteObject();
ReleaseDC(pDC);
}
UINT ThreadFonction(LPVOID Param){
while(m_TransfertContinu){ //On effectue le thread tant que la variable m_tranfertContinu=TRUE
InvalidateRect((HWND)Param,0,FALSE); //le HWND de ma fenetre est passé à mon thread en paramètre
Sleep(40);
}
return 0;
}
Ne pas oublier de mettre votre boite de dialogue en style WS_CLIPCHILDREN!
En faisant InvalidRect(hwnd,0,TRUE) depuis mon thread l'erreur est en partie corrrigée.
Le problème est que j'ai mis en place un double buffering pour éviter le scintillement de mon grahique, mais lorsque je rafraichit toute la fenêtre, les boutons scintillent (contrairement au graphique). C'est pour cela que je rafraichissait seulement une partie de ma boite de dialogue.
En plus, l'erreur se produit toujours lorsque je déplace ou que je redimensionne ma fenetre, mais seulement quand le double buffering est mis en place, et pas quand je dessine directement sur la boite de dialogue.
Donc je vais essayer de voir tout ça! Merci beaucoup pour ta réponse!
Vous n’avez pas trouvé la réponse que vous recherchez ?
Le style WS_CLIPCHILDREN permet bien d'éviter le scintillement des boutons, merci!
Voici une partie de mon code. C'est avec ce code que se produit l'erreur décrite dans le premier post...
J'ai essayé de remplacer l'envoi du Message WM_UPDATE_UI dans mon thread par InvalidateRect(hwnd,0,TRUE) mais mon graphique scintille fortement (on dirai que le double buffering n'est plus effectué)...
//Fonction exécutée par mon thread :
UINT ThreadFonction(LPVOID Param){
while(GLOB->m_TransfertContinu){ //On effectue la boucle tant qu'une variable globale est à TRUE
//on y ajoute un bitmap pour agrandir dc
memBmp.CreateCompatibleBitmap(pDC, lRect.Width(), lRect.Height());
CBitmap* OldBmp = dc.SelectObject(&memBmp);
//Remplissage du fond
CBrush backBrush(RGB(250,250,250));
dc.FillRect(lRect,&backBrush);
//Ces trois fonctions permettent de dessiner mon graphique (le prog plante même si elles ne sont pas exécutées donc l'erreur ne vient pas de la)
DrawLine(&dc, 6);
DrawRepere(&dc);
DrawGraph(&dc);
//fdc.BitBlt(0,0,lRect.Width(),lRect.Height(),&dc,0,0,SRCCOPY); //on copie dc vers fdc (solution 1)
pDC->BitBlt(0,0,lRect.Width(),lRect.Height(),&dc,0,0,SRCCOPY); //on copie dc vers fdc (solution 2)
//Ces 2 solutions de copie ne changent pas mon problème!
dc.SelectObject(OldBmp);
dc.DeleteDC();
memBmp.DeleteObject();
Désolé je me suis trompé dans mon précédent post...
J'ai essayé de remplacer l'envoi du Message WM_UPDATE_UI dans mon
thread par InvalidateRect(hwnd,0,FALSE) . Je n'ai dans ce cas plus de problème de scintillement, par contre, mon erreur se produit lorsque que je déplace, redimensionne ou ferme la fenetre...
Oui effectivement mon pDC ne sert à rien, merci.
On peut donc supprimer les lignes "CDC *pDC;", "pDC=GetDC();" et "ReleaseDC(pDC);" et remplacer les "pDC" par des "&fdc".