Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
987 connectés 

  FORUM HardWare.fr
  Programmation
  API Win32

  CreateCompatibleDC me renvoie NULL dans WM_PAINT

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

CreateCompatibleDC me renvoie NULL dans WM_PAINT

n°2011812
jbs106
Posté le 26-07-2010 à 14:31:56  profilanswer
 

Bonjour,
 
Mon programme dessine dans un bitmap stocké, toutes les opérations de dessins sont stocké, de se coté là, pas de soucis. Quand je souhaite inserer un bitmap, là commence le petit problème. Je dois l'inserer, pour cela, j'appel une boite de dialogue de recherche de fichier qui me renvoie le nom du fichier. De là, j'ouvre un HANDLE sur le nom de fichier. J'ai ouvert mon fichier. Je click pour un premier point et le deuxieme point n'est pas fixé tant que je ne lache pas le bouton de la souris, j'agrandi l'image, pas de probleme, je retreci l'image probleme, l'image laisse des traces. Je decide de forcer le refraichissement de l'appli par InvalidateRect et UpdateWindow dans le traitement du message WM_MOUSEMOVE, le traitement du message de WM_PAINT s'effectue, mais le HDC fournie a partir de CreateCompatibleDC est un pointeur NULL. Quand je ne le force pas j'obtient bien un compatible DC.
 
Une idée?

mood
Publicité
Posté le 26-07-2010 à 14:31:56  profilanswer
 

n°2011821
olivthill
Posté le 26-07-2010 à 14:41:20  profilanswer
 

Ah, ah, ah [:haha]
Dans WM_PAINT, il faut récupérer le HDC via BeginPaint, par exemple

PAINTSTRUCT ps;
HDC hdc;
...
      hdc = BeginPaint(hwnd, &ps);
...
      EndPaint(hwnd, &ps);

Message cité 1 fois
Message édité par olivthill le 26-07-2010 à 14:42:56
n°2011874
jbs106
Posté le 26-07-2010 à 16:33:25  profilanswer
 

olivthill a écrit :

Ah, ah, ah [:haha]
Dans WM_PAINT, il faut récupérer le HDC via BeginPaint, par exemple

PAINTSTRUCT ps;
HDC hdc;
...
      hdc = BeginPaint(hwnd, &ps);
...
      EndPaint(hwnd, &ps);



 
Voici mon code :

Code :
  1. LRESULT TDrawer::MsgPaint  (WPARAM wParam, LPARAM lParam)
  2. {
  3. PAINTSTRUCT PS;
  4. RECT rect = {0, 0,Bitmap::GetWidth(),Bitmap::GetHeight()};
  5. HDC hdc  = BeginPaint(m_hWnd,&PS);
  6. //HDC hdcNULL = GetDC(NULL);
  7. HDC hdcMem = CreateCompatibleDC(hdc);
  8. HBITMAP hBitmapOld = (HBITMAP) SelectObject(hdcMem, m_hBitmap);
  9. RECT rcClip;GetClipBox(hdcMem,&rcClip);
  10. FillRect(hdcMem, &rect,static_cast<HBRUSH>(GetStockObject (WHITE_BRUSH)));
  11. int nPos = this->m_ListElement.size();
  12. int iPos = 0;
  13. while(iPos<nPos)              // Loop while aPos is not null
  14. {
  15.  if(RectVisible(hdcMem,&this->m_ListElement[iPos]->GetBoundRect())) // If the element is visible...
  16.   this->m_ListElement[iPos]->Draw(hdcMem,m_pSelected);   // ...draw it
  17.  iPos++;
  18. }
  19. //if(m_pTempElement)
  20. // m_pTempElement->Draw(hdcMem);
  21. StretchBlt(hdc, m_Origine.x, m_Origine.y, m_View.cx * m_Scale, m_View.cy * m_Scale, hdcMem,abs(m_OrigineView.x-m_Origine.x)/m_Scale,abs(m_OrigineView.y - m_Origine.y)/m_Scale , m_View.cx, m_View.cy, SRCCOPY);
  22. SelectObject(hdcMem, hBitmapOld);          // Release
  23. DeleteDC(hdcMem);
  24. //ReleaseDC(NULL,hdcNULL);
  25. EndPaint(m_hWnd, &PS);            // Utiliser hBitmap ensuite...
  26. return TRUE;
  27. }
Code :
  1. LRESULT TDrawer::MsgMouseMove (WPARAM wParam, LPARAM lParam)
  2. {
  3. HDC hdc,hdcMem;
  4. HBITMAP hBitmapOld;
  5. m_SecondPoint.x = (short) LOWORD(lParam);
  6. m_SecondPoint.y = (short) HIWORD(lParam);
  7. if(m_MoveMode)// If we are in move mode, move the selected element and return
  8. {
  9.  hdc    = GetDC(m_hWnd)   ; SetROP2(hdc  ,R2_NOT);
  10.  hdcMem = CreateCompatibleDC(hdc); SetROP2(hdcMem ,R2_NOTXORPEN);
  11.  hBitmapOld = (HBITMAP)SelectObject(hdcMem, m_hBitmap);
  12.  MoveElement(hdcMem, m_SecondPoint);   // Move the element
  13.  this->m_bModified = TRUE;
  14.  goto LibèreDC;
  15. }
  16. ClientToPixel(m_SecondPoint);
  17. if((GetCapture() == m_hWnd)&&(wParam & MK_LBUTTON))// Si le bouton gauche est enfoncé
  18. {
  19.  hdc    = GetDC(m_hWnd)   ; SetROP2(hdc  ,R2_NOT);
  20.  hdcMem = CreateCompatibleDC(hdc); SetROP2(hdcMem ,R2_NOTXORPEN);
  21.  hBitmapOld = (HBITMAP)SelectObject(hdcMem, m_hBitmap);
  22.  if(m_pTempElement) // Si un élément temporaire est déjà défini
  23.  {
  24.   if(CURVE == this->GetElementType())   // Si c'est une courbe
  25.   {  SetROP2(hdcMem,R2_COPYPEN);
  26.    (static_cast<ECurve*>(m_pTempElement))->DrawSegment(hdcMem,m_SecondPoint); // We are drawing a curve
  27.    (static_cast<ECurve*>(m_pTempElement))->AddSegment(m_SecondPoint);   // so add a segment to the existing curve
  28.    goto LibèreDC;
  29.   }
  30.   m_pTempElement->Draw(hdcMem); // Redraw the old element so it disappears from the view
  31.   delete m_pTempElement;   // Delete the old element
  32.   m_pTempElement = 0;    // Reset the pointer to 0
  33.  }
  34.  m_pTempElement = CreateElement(); // Créer un element mais temporaire tant que l'utilisateur ne lache pas le button pour figer l'élément
  35.  m_pTempElement->Draw(hdcMem);  // Draw the element
  36.  goto LibèreDC;
  37. }
  38. else    // Si nous ne dessinons pas alors mise en surbrillance sous le pointeur d'un élément existant
  39. {
  40.  VElement* pCurrentSelection = SelectElement(m_SecondPoint);// Existe-t-il un élément sous le pointeur?
  41.  if(pCurrentSelection!=m_pSelected)   // Si l'élément sous le pointeur est différent que l'ancien élément?(soit l'ancien ou un nouveau)
  42.  {
  43.   hdc    = GetDC(m_hWnd)   ; SetROP2(hdc  ,R2_NOT);
  44.   hdcMem = CreateCompatibleDC(hdc); SetROP2(hdcMem ,R2_NOTXORPEN);
  45.   hBitmapOld = (HBITMAP)SelectObject(hdcMem, m_hBitmap);
  46.   if(m_pSelected)       // Si existance de l'ancien élément, est (toujours) de la couleur "surbrillance"
  47.   { m_pSelected->Draw(hdcMem,m_pSelected); // En le dessinant de la couleur surbrillance, Nous effaçons ses pixels (NOTXORPEN)
  48.    m_pSelected->Draw(hdcMem);    // L'élément est dessiné de sa plume, son épaisseur et sa couleur d'origine
  49.   }
  50.   m_pSelected = pCurrentSelection;        // Save elem under cursor
  51.   if(m_pSelected)                         // Is there one?
  52.   {
  53.    m_pSelected->Draw(hdcMem);
  54.    m_pSelected->Draw(hdcMem,m_pSelected);// Yes, so get it redrawn
  55.   }
  56.   goto LibèreDC;
  57.  }
  58. }
  59. return DefMDIChildProc(m_hWnd,WM_MOUSEMOVE,wParam,lParam);
  60. LibèreDC:
  61. StretchBlt(hdc, m_Origine.x, m_Origine.y, m_View.cx * m_Scale, m_View.cy * m_Scale, hdcMem,abs(m_OrigineView.x-m_Origine.x)/m_Scale,abs(m_OrigineView.y - m_Origine.y)/m_Scale , m_View.cx, m_View.cy, SRCCOPY);
  62. SelectObject(hdcMem, hBitmapOld);   // Release
  63. BOOL bOK = DeleteDC(hdcMem);
  64. bOK = ReleaseDC(m_hWnd, hdc);
  65. ::InvalidateRect(m_hWnd, NULL, TRUE);
  66. ::UpdateWindow(m_hWnd);
  67. return TRUE;
  68. }

n°2011878
jbs106
Posté le 26-07-2010 à 16:41:42  profilanswer
 

Y a des commentaires qui me semblent erronés...


Message édité par jbs106 le 26-07-2010 à 16:42:14
n°2011893
olivthill
Posté le 26-07-2010 à 17:23:52  profilanswer
 

Le commentaire erroné était un peu d'humour, excusez-moi.
 
Merci pour le code. C'est plus clair.
 
Mais, il manque des infos intéressantes. Par exemple :
 
- D'où vient TDrawer (parce que MsgPaint n'est peut-être pas appelé lors du traitement de WM_PAINT, ou pas uniquement, ou autre) ?
- D'où vient Bitmap (parce que les dimensions sont peut-être égales à zéro) ?
- Est-ce que m_hWnd contient bien ce qui est attendu (parce que l'un des problèmes fréquents est que l'on essaye de peindre le fond, alors que le programme tourne pour la peinture d'un bouton) ?
- Est-ce que le hdc est nul juste après la ligne 7 ou bien ailleurs (parce que vous nous donnez beaucoup de lignes de codes qui suivent ce problème initial, et qui donc ne concerneraient pas ce problème) ?
 
C'est étrange car CreateCompatibleDC marche bien habituellement. Les cas où un nul est renvoyé est quand il n'y a pas assez de place en mémoire, où quand le DC d'origine est étrange comme celui d'une imprimante ou d'un scanner particulier.
 
Habituellement, c'est le bitmap associé au DC qui ne contient qu'un seul pixel noir, et cela étonne le programmeur, mais cela vient de ce que la mémoire pour les pixels du bitmap n'a pas été allouée. Je ne sais pas si c'est le cas ici.
 
Le problème des traces qui subsistent est peut-être similaire à celui décrit à http://www.codeguru.com/forum/showthread.php?t=495844 .

n°2011914
jbs106
Posté le 26-07-2010 à 18:32:55  profilanswer
 

msgpaint est bien appelé lors du message WM_PAINT,
 
Bitmap est une class stockant un bitmap.
 
m_hWnd contient bien le handle de la fenetre; au moment de la création, si m_hWnd est null, le programme s'arrete ou annule la création de l'objet.
 
il est null juste apres la ligne 7.
 
Comme le DC est null, j'obtient une zone de clipping de 1*1pixel.
 
Comme la zone de dessin ne se redessine pas, que mon compatible DC est null, mon bitmap laisse des traces.
 
Je ne travaille qu'avec des objets:
 
J'ai un objet Windower dont toutes les fenetres héritent, sauf  TDrawer qui derive (d'abord) Scroller.
 
Scroller dérive de Windower et de Bitmap. Scroller est capable de scroller un Bitmap.
 
Tu veux mon code?


Message édité par jbs106 le 26-07-2010 à 18:46:32
n°2011929
jbs106
Posté le 26-07-2010 à 20:05:31  profilanswer
 

Olivthill merci à toi, je ne sais pas comment, j'obtient le compatible DC. C'est peut-être du en redemarrant le pc quoi qu'il était en veille prolongé.
J'ai modifié deux truc, (WM_ERASEBKGND et WM_MOUSEMOVE) et pourtant même en les remettant, ça fonctionne quand même. ça m'enerve de faire appel à toi Olivthill ou n'importe qui, et que mon programme se met à fonctionner par magie. là, je ne comprend pas pourquoi ça marche.
 
:D
 
merci de ton attention.

n°2012004
olivthill
Posté le 27-07-2010 à 09:59:23  profilanswer
 

Oui, c'est un peu énervant quand on a l'impression que l'ordinateur agit selon son humeur au lieu de selon la logique. On est obligé de rester vigilant pour le cas où le problème reviendrait. Mon explication est que c'était un problème de ressources système indisponibles suite à la veille, ... ou autre chose (par exemple, j'ai remarqué que si je lance un programme à partir de l'environnement de programmation, il arrive que j'aie des blocages, au bout de plusieurs lancements, que je n'ai pas si le lancement se fait en dehors ; ou bien il arrive que ce soit un problème dû à une variable non initialisée ou mal initialisée, qui prend une valeur par défaut indésirable dans certaines circonstances très spéciales, ce qui est la raison pour laquelle, je suis très prudent sur les initialisations, et par exemple, je sépare les déclarations, des initialisations elle-mêmes). En tous cas, je suis content de voir des programmeurs qui utilisent les API, et je suis content pour toi que ça marche maintenant. Bonne continuation !


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  API Win32

  CreateCompatibleDC me renvoie NULL dans WM_PAINT

 

Sujets relatifs
[RESOLU]document.getElementById() = null mais pourquoi ??[Résolu] Problème variable php qui renvoie rien
Access champ null dans une requêteIncompréhension EOF ET NULL
Condition non null pour rentrer dasn ma boucle[JSP] session.getAttribute("sUser") à null
[résolu] strtr renvoie des caractères farfelus (UTF-8)[JS] Problème: ""null":Cannot convert undefined or null to object"
paint ne s'appelle pas quand je dérive de JPanel 
Plus de sujets relatifs à : CreateCompatibleDC me renvoie NULL dans WM_PAINT


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR