GDI

GDI - API Win32 - Programmation

Marsh Posté le 24-10-2010 à 12:05:03    

Bonjour,
 
Une bonne âme pourrait elle m'aider ? Je ne comprends pas pourquoi mon code ne marche pas alors que j'ai essayé de suivre les préconisations de la MSDN et de différents forums. Un truc m'échappe...
 
Pour l'instant, je veux juste écrire un code simple, pour le complexifier par la suite.
 
Je définis en global :

Code :
  1. #define tailleX 800
  2. #define tailleY 600
  3. DWORD tableau[tailleX * tailleY];


 
J'éxécute en premier dans la winmain :

Code :
  1. for (int i=0;i<tailleX*tailleY;i++) tableau[i]=0x00FF00FF;


 
Et enfin, j'intercepte le message WM_PAINT. Je transforme tableau en hBitmap, puis je le redimensionne pour la fenêtre

Code :
  1. PAINTSTRUCT ps;
  2. HDC hdc=BeginPaint(hWnd, &ps);
  3. RECT tailleFenetre;
  4. BITMAPINFO bi;
  5. bi.bmiHeader.biBitCount=32;
  6. bi.bmiHeader.biClrImportant=0;
  7. bi.bmiHeader.biClrUsed=0;
  8. bi.bmiHeader.biCompression=BI_RGB;
  9. bi.bmiHeader.biHeight=tailleY;
  10. bi.bmiHeader.biWidth=tailleX;
  11. bi.bmiHeader.biPlanes=1;
  12. bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
  13. bi.bmiHeader.biSizeImage=0;
  14. bi.bmiHeader.biXPelsPerMeter=0;
  15. bi.bmiHeader.biYPelsPerMeter=0;
  16. GetClientRect(hWnd, &tailleFenetre);
  17. SetStretchBltMode(hdc, HALFTONE);
  18. HDC hMemDC= CreateCompatibleDC(hdc);
  19. SetStretchBltMode(hMemDC, HALFTONE);
  20. HBITMAP hBitmap= CreateDIBitmap(hMemDC, &bi.bmiHeader,CBM_INIT,tableau,&bi,DIB_RGB_COLORS);
  21. SelectObject(hMemDC, hBitmap);
  22. StretchBlt(hdc, 0, 0, tailleFenetre.right, tailleFenetre.bottom, hMemDC, 0, 0, tailleX, tailleY, SRCCOPY);
  23. DeleteObject(hBitmap);
  24. DeleteDC(hMemDC);
  25. EndPaint(hWnd, &ps);
  26. break;


 
 
J'ai passé 4 heures sur les forums et à reprendre chaque paramétrage un par un pour essayer de comprendre. J'ai essayé d'intercepter les erreurs (aucun appel à une fonction ne renvoie d'erreur). Je m'attends à avoir la zone centrale de ma fenêtre toute violette (0x00ff00ff) et je me retrouve avec une fenêtre toute noire.  
 
 
Code complet :

Code :
  1. #include "stdafx.h"
  2. #include "Projet test.h"
  3. #define MAX_LOADSTRING 100
  4. #define tailleX 800
  5. #define tailleY 600
  6. // Variables globales :
  7. HINSTANCE hInst;        // instance actuelle
  8. TCHAR szTitle[MAX_LOADSTRING];     // Le texte de la barre de titre
  9. TCHAR szWindowClass[MAX_LOADSTRING];   // le nom de la classe de fenêtre principale
  10. DWORD tableau[tailleX * tailleY];
  11. // Pré-déclarations des fonctions incluses dans ce module de code :
  12. ATOM    MyRegisterClass(HINSTANCE hInstance);
  13. BOOL    InitInstance(HINSTANCE, int);
  14. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  15. INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
  16. int APIENTRY _tWinMain(HINSTANCE hInstance,
  17.                      HINSTANCE hPrevInstance,
  18.                      LPTSTR    lpCmdLine,
  19.                      int       nCmdShow)
  20. {
  21. UNREFERENCED_PARAMETER(hPrevInstance);
  22. UNREFERENCED_PARAMETER(lpCmdLine);
  23. for (int i=0;i<tailleX*tailleY;i++) tableau[i]=0x00FF00FF;
  24. MSG msg;
  25. HACCEL hAccelTable;
  26. // Initialise les chaînes globales
  27. LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  28. LoadString(hInstance, IDC_PROJETTEST, szWindowClass, MAX_LOADSTRING);
  29. MyRegisterClass(hInstance);
  30. // Effectue l'initialisation de l'application :
  31. if (!InitInstance (hInstance, nCmdShow))
  32. {
  33.  return FALSE;
  34. }
  35. hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROJETTEST));
  36. // Boucle de messages principale :
  37. while (GetMessage(&msg, NULL, 0, 0))
  38. {
  39.  if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  40.  {
  41.   TranslateMessage(&msg);
  42.   DispatchMessage(&msg);
  43.  }
  44. }
  45. return (int) msg.wParam;
  46. }
  47. //
  48. //  FONCTION : MyRegisterClass()
  49. //
  50. //  BUT : inscrit la classe de fenêtre.
  51. //
  52. //  COMMENTAIRES :
  53. //
  54. //    Cette fonction et son utilisation sont nécessaires uniquement si vous souhaitez que ce code
  55. //    soit compatible avec les systèmes Win32 avant la fonction 'RegisterClassEx'
  56. //    qui a été ajoutée à Windows 95. Il est important d'appeler cette fonction
  57. //    afin que l'application dispose des petites icônes correctes qui lui sont
  58. //    associées.
  59. //
  60. ATOM MyRegisterClass(HINSTANCE hInstance)
  61. {
  62. WNDCLASSEX wcex;
  63. wcex.cbSize = sizeof(WNDCLASSEX);
  64. wcex.style   = CS_HREDRAW | CS_VREDRAW;
  65. wcex.lpfnWndProc = WndProc;
  66. wcex.cbClsExtra  = 0;
  67. wcex.cbWndExtra  = 0;
  68. wcex.hInstance  = hInstance;
  69. wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROJETTEST));
  70. wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
  71. wcex.hbrBackground = 0;
  72. wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PROJETTEST);
  73. wcex.lpszClassName = szWindowClass;
  74. wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
  75. return RegisterClassEx(&wcex);
  76. }
  77. //
  78. //   FONCTION : InitInstance(HINSTANCE, int)
  79. //
  80. //   BUT : enregistre le handle de l'instance et crée une fenêtre principale
  81. //
  82. //   COMMENTAIRES :
  83. //
  84. //        Dans cette fonction, nous enregistrons le handle de l'instance dans une variable globale, puis
  85. //        créons et affichons la fenêtre principale du programme.
  86. //
  87. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  88. {
  89.    HWND hWnd;
  90.    hInst = hInstance; // Stocke le handle d'instance dans la variable globale
  91.    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  92.       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  93.    if (!hWnd)
  94.    {
  95.       return FALSE;
  96.    }
  97.    ShowWindow(hWnd, nCmdShow);
  98.    UpdateWindow(hWnd);
  99.    return TRUE;
  100. }
  101. //
  102. //  FONCTION : WndProc(HWND, UINT, WPARAM, LPARAM)
  103. //
  104. //  BUT :  traite les messages pour la fenêtre principale.
  105. //
  106. //  WM_COMMAND - traite le menu de l'application
  107. //  WM_PAINT - dessine la fenêtre principale
  108. //  WM_DESTROY - génère un message d'arrêt et retourne
  109. //
  110. //
  111. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  112. {
  113. switch (message)
  114. {
  115. case WM_COMMAND:
  116.         int wmId, wmEvent;
  117.  wmId    = LOWORD(wParam);
  118.  wmEvent = HIWORD(wParam);
  119.  // Analyse les sélections de menu :
  120.  switch (wmId)
  121.  {
  122.  case IDM_ABOUT:
  123.   DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
  124.   break;
  125.  case IDM_EXIT:
  126.   DestroyWindow(hWnd);
  127.   break;
  128.  default:
  129.   return DefWindowProc(hWnd, message, wParam, lParam);
  130.  }
  131.  break;
  132. case WM_PAINT:
  133.          {
  134.          PAINTSTRUCT ps;
  135.          HDC hdc=BeginPaint(hWnd, &ps);
  136.          RECT tailleFenetre;
  137.          BITMAPINFO bi;
  138.   bi.bmiHeader.biBitCount=32;
  139.   bi.bmiHeader.biClrImportant=0;
  140.   bi.bmiHeader.biClrUsed=0;
  141.   bi.bmiHeader.biCompression=BI_RGB;
  142.   bi.bmiHeader.biHeight=tailleY;
  143.   bi.bmiHeader.biWidth=tailleX;
  144.   bi.bmiHeader.biPlanes=1;
  145.   bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
  146.   bi.bmiHeader.biSizeImage=0;
  147.   bi.bmiHeader.biXPelsPerMeter=0;
  148.   bi.bmiHeader.biYPelsPerMeter=0;
  149.             GetClientRect(hWnd, &tailleFenetre);
  150.   SetStretchBltMode(hdc, HALFTONE);
  151.             HDC hMemDC= CreateCompatibleDC(hdc);
  152.   SetStretchBltMode(hMemDC, HALFTONE);
  153.   HBITMAP hBitmap= CreateDIBitmap(hMemDC, &bi.bmiHeader,CBM_INIT,tableau,&bi,DIB_RGB_COLORS);
  154.   //HBITMAP hBitmap=CreateCompatibleBitmap(hMemDC, tailleX, tailleY);
  155.   SelectObject(hMemDC, hBitmap);
  156.   SetDIBits(hMemDC, hBitmap, 0, tailleY, tableau, &bi, DIB_RGB_COLORS);
  157.   StretchBlt(hdc, 0, 0, tailleFenetre.right, tailleFenetre.bottom, hMemDC, 0, 0, 15, 15, SRCCOPY);//tailleX, tailleY, SRCCOPY);
  158.             DeleteObject(hBitmap);
  159.             DeleteDC(hMemDC);
  160.   /*
  161.   SetStretchBltMode(hdc, HALFTONE);
  162.   SetBrushOrgEx(hdc, 0, 0, 0);
  163.          
  164.   StretchDIBits(
  165.            hdc,
  166.            0, 0, 640, 480, //tailleFenetre.right, tailleFenetre.bottom,
  167.            0, 0, tailleX, tailleY,
  168.            tableau,
  169.            &bi,
  170.            0,
  171.            0
  172.          );
  173.   */
  174.          EndPaint(hWnd, &ps);
  175.          break;
  176.         }
  177. case WM_DESTROY:
  178.  PostQuitMessage(0);
  179.  break;
  180. default:
  181.  return DefWindowProc(hWnd, message, wParam, lParam);
  182. }
  183. return 0;
  184. }
  185. // Gestionnaire de messages pour la boîte de dialogue À propos de.
  186. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  187. {
  188. UNREFERENCED_PARAMETER(lParam);
  189. switch (message)
  190. {
  191. case WM_INITDIALOG:
  192.  return (INT_PTR)TRUE;
  193. case WM_COMMAND:
  194.  if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
  195.  {
  196.   EndDialog(hDlg, LOWORD(wParam));
  197.   return (INT_PTR)TRUE;
  198.  }
  199.  break;
  200. }
  201. return (INT_PTR)FALSE;
  202. }


Reply

Marsh Posté le 24-10-2010 à 12:05:03   

Reply

Marsh Posté le 25-10-2010 à 14:27:44    

La première chose à corriger est :

bi.bmiHeader.biSizeImage=0;


A la place, il faut écrire :

bi.bmiHeader.biSizeImage = bi.bmiHeader.biWidth * 4 * bi.bmiHeader.biHeight * sizeof(unsigned char);


Je n'ai pas regardé la suite en détail.
 
Edit : J'avais mis "* -1", car d'habitude on met un nombre négatif pour la hauteur pour partir du haut vers le bas, au lieu de l'inverse.


Message édité par olivthill le 25-10-2010 à 14:30:09
Reply

Marsh Posté le 25-10-2010 à 16:25:05    

Haha, GDI et son API de merde. Bon, quand je fais joujou avec les bitmaps, je préfère utiliser des DIBSection, c'est moins casse gueule. En essayant de modifier ton code, je n'ai pas réussi à le faire fonctionner non plus. Mais en utilisant des DIBSection, ça fonctionne sans problème. Suffit de réécrire ton WM_PAINT de la sorte :

Code :
  1. {
  2.     PAINTSTRUCT ps;
  3.     HDC hdc=BeginPaint(hWnd, &ps);
  4.     RECT tailleFenetre;
  5.     BITMAPINFO bi = {};
  6.  
  7.     bi.bmiHeader.biBitCount=32;
  8.     bi.bmiHeader.biCompression=BI_RGB;
  9.     bi.bmiHeader.biHeight=tailleY;
  10.     bi.bmiHeader.biWidth=tailleX;
  11.     bi.bmiHeader.biPlanes=1;
  12.     bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
  13.  
  14.     GetClientRect(hWnd, &tailleFenetre);
  15.     SetStretchBltMode(hdc, HALFTONE);
  16.  
  17.     HDC hMemDC= CreateCompatibleDC(hdc);
  18.     SetStretchBltMode(hMemDC, HALFTONE);
  19.     LPVOID data;
  20.     HBITMAP hBitmap = CreateDIBSection(hMemDC, &bi,DIB_RGB_COLORS,&data,NULL,0);
  21. //    HBITMAP hBitmap = CreateDIBitmap(hMemDC, &bi.bmiHeader,CBM_INIT,tableau,&bi,DIB_RGB_COLORS);
  22.  
  23.     memcpy(data, tableau, sizeof tableau);
  24.     HANDLE old = SelectObject(hMemDC, hBitmap);
  25.  
  26.     StretchBlt(hdc, 0, 0, tailleFenetre.right, tailleFenetre.bottom, hMemDC, 0, 0, tailleX, tailleY, SRCCOPY);
  27.     BitBlt(hdc, 0, 0, tailleX, tailleY, hMemDC, 0, 0, SRCCOPY);
  28.     SelectObject(hMemDC, old);
  29.     DeleteObject(hBitmap);
  30.     DeleteDC(hMemDC);
  31.  
  32.     EndPaint(hWnd, &ps);
  33.     break;
  34. }


 
Une petite optimisation serait d'allouer le DIBSection avant la boucle d'événement, et d'initialiser le bitmap renvoyé plutôt que d'utiliser une table statique.

Reply

Marsh Posté le 25-10-2010 à 19:57:42    

@olivthill
Ce champ peut rester à 0. Je cite la MSDN :

Citation :

biSizeImage The size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.


J'ai essayé, au cas où, de modifier ce champ mais cela n'améliore pas le résultat.
 
@tpierron
Je vais pas me prendre la tête et utiliser les DIBSection, et je vais même utiliser l'amélioration que tu me proposes. N'empêche que sur le principe mon code de départ ne me parait pas si foireux que ça.
Je dis pas que c'est simple de faire une interface graphique qui puisse adapter à tous les matériels, mais le GDI c'est une belle merde.
 
Merci les amis !

Reply

Marsh Posté le 26-10-2010 à 12:32:39    

Pour infos, voici ma version qui marche, créée en modifiant un peu la version initiale :

Code :
  1. #include <windows.h>
  2. #define MAX_LOADSTRING 100
  3. #define tailleX 800
  4. #define tailleY 600
  5. // Variables globales :
  6. HINSTANCE hInst;        // instance actuelle
  7. // TCHAR szTitle[MAX_LOADSTRING];     // Le texte de la barre de titre
  8. char szTitle[MAX_LOADSTRING];     // Le texte de la barre de titre
  9. // TCHAR szWindowClass[MAX_LOADSTRING];   // le nom de la classe de fenêtre principale
  10. char szWindowClass[MAX_LOADSTRING];   // le nom de la classe de fenêtre principale
  11. DWORD tableau[tailleX * tailleY];
  12. // Pré-déclarations des fonctions incluses dans ce module de code :
  13. ATOM    MyRegisterClass(HINSTANCE hInstance);
  14. BOOL    InitInstance(HINSTANCE, int);
  15. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  16. INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
  17. int APIENTRY WinMain(HINSTANCE hInstance,
  18.                      HINSTANCE hPrevInstance,
  19.                      LPTSTR    lpCmdLine,
  20.                      int       nCmdShow)
  21. {
  22. UNREFERENCED_PARAMETER(hPrevInstance);
  23. UNREFERENCED_PARAMETER(lpCmdLine);
  24. for (int i=0;i<tailleX*tailleY;i++) tableau[i]=(DWORD)(0x00FF00FF);
  25. MSG msg;
  26. HACCEL hAccelTable;
  27. // Initialise les chaînes globales
  28. //  ***  LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
  29. strcpy(szTitle, "Test GDI" );
  30. //  *** LoadString(hInstance, IDC_PROJETTEST, szWindowClass, MAX_LOADSTRING);
  31. strcpy(szWindowClass, "Test GDI" );
  32. MyRegisterClass(hInstance);
  33. // Effectue l'initialisation de l'application :
  34. if (!InitInstance (hInstance, nCmdShow))
  35. {
  36. return FALSE;
  37. }
  38. // *** hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROJETTEST));
  39. // Boucle de messages principale :
  40. while (GetMessage(&msg, NULL, 0, 0))
  41. {
  42. if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
  43. {
  44.  TranslateMessage(&msg);
  45.  DispatchMessage(&msg);
  46. }
  47. }
  48. return (int) msg.wParam;
  49. }
  50. //
  51. //  FONCTION : MyRegisterClass()
  52. //
  53. //  BUT : inscrit la classe de fenêtre.
  54. //
  55. //  COMMENTAIRES :
  56. //
  57. //    Cette fonction et son utilisation sont nécessaires uniquement si vous souhaitez que ce code
  58. //    soit compatible avec les systèmes Win32 avant la fonction 'RegisterClassEx'
  59. //    qui a été ajoutée à Windows 95. Il est important d'appeler cette fonction
  60. //    afin que l'application dispose des petites icônes correctes qui lui sont
  61. //    associées.
  62. //
  63. ATOM MyRegisterClass(HINSTANCE hInstance)
  64. {
  65.      int i;
  66. WNDCLASSEX wcex;
  67. wcex.cbSize = sizeof(WNDCLASSEX);
  68. wcex.style   = CS_HREDRAW | CS_VREDRAW;
  69. wcex.lpfnWndProc = WndProc;
  70. wcex.cbClsExtra  = 0;
  71. wcex.cbWndExtra  = 0;
  72. wcex.hInstance  = hInstance;
  73. // *** wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROJETTEST));
  74. wcex.hIcon   = '\0';
  75. wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
  76. wcex.hbrBackground = (HBRUSH) COLOR_BACKGROUND;;
  77. // *** wcex.lpszMenuName = MAKEINTRESOURCE(IDC_PROJETTEST);
  78. wcex.lpszMenuName = '\0';
  79. wcex.lpszClassName = szWindowClass;
  80. // *** wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
  81. // i = RegisterClassEx(&wcex);
  82. return RegisterClassEx(&wcex);
  83. }
  84. //
  85. //   FONCTION : InitInstance(HINSTANCE, int)
  86. //
  87. //   BUT : enregistre le handle de l'instance et crée une fenêtre principale
  88. //
  89. //   COMMENTAIRES :
  90. //
  91. //        Dans cette fonction, nous enregistrons le handle de l'instance dans une variable globale, puis
  92. //        créons et affichons la fenêtre principale du programme.
  93. //
  94. BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
  95. {
  96.    HWND hWnd;
  97.    hInst = hInstance; // Stocke le handle d'instance dans la variable globale
  98. //   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  99. //      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  100.    hWnd = CreateWindowEx(WS_EX_TOOLWINDOW,szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
  101.       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
  102.    if (!hWnd)
  103.    {
  104.       return FALSE;
  105.    }
  106.    ShowWindow(hWnd, nCmdShow);
  107.    UpdateWindow(hWnd);
  108.    return TRUE;
  109. }
  110. //
  111. //  FONCTION : WndProc(HWND, UINT, WPARAM, LPARAM)
  112. //
  113. //  BUT :  traite les messages pour la fenêtre principale.
  114. //
  115. //  WM_COMMAND - traite le menu de l'application
  116. //  WM_PAINT - dessine la fenêtre principale
  117. //  WM_DESTROY - génère un message d'arrêt et retourne
  118. //
  119. //
  120. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  121. {
  122. switch (message)
  123. {
  124. case WM_COMMAND:
  125.         int wmId, wmEvent;
  126. wmId    = LOWORD(wParam);
  127. wmEvent = HIWORD(wParam);
  128. // Analyse les sélections de menu :
  129. switch (wmId)
  130. {
  131. #define IDM_ABOUT 101
  132. case 101:
  133. // ***  DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
  134.  break;
  135. #define IDM_EXIT 999
  136. case IDM_EXIT:
  137.  DestroyWindow(hWnd);
  138.  break;
  139. default:
  140.  return DefWindowProc(hWnd, message, wParam, lParam);
  141. }
  142. break;
  143. case WM_PAINT:
  144.          {
  145.          PAINTSTRUCT ps;
  146.          HDC hdc=BeginPaint(hWnd, &ps);
  147.          RECT tailleFenetre;
  148.     BITMAPINFO bi;
  149. bi.bmiHeader.biBitCount=32;
  150.  bi.bmiHeader.biClrImportant=0;
  151.  bi.bmiHeader.biClrUsed=0;
  152.  bi.bmiHeader.biCompression=BI_RGB;
  153.  bi.bmiHeader.biHeight= -tailleY;
  154.  bi.bmiHeader.biWidth=tailleX;
  155.  bi.bmiHeader.biPlanes=1;
  156.  bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
  157. //  bi.bmiHeader.biSizeImage=0;
  158.     bi.bmiHeader.biSizeImage = bi.bmiHeader.biWidth * 4 * bi.bmiHeader.biHeight * sizeof(unsigned char);
  159.  bi.bmiHeader.biXPelsPerMeter=0;
  160.  bi.bmiHeader.biYPelsPerMeter=0;
  161.             GetClientRect(hWnd, &tailleFenetre);
  162. //  SetStretchBltMode(hdc, HALFTONE);
  163.     HDC hMemDC = GetDC(hWnd);
  164. //  SetStretchBltMode(hMemDC, HALFTONE);
  165.  HBITMAP hBitmap= CreateDIBitmap(hMemDC, &bi.bmiHeader,CBM_INIT,tableau,&bi,DIB_RGB_COLORS);
  166.     ReleaseDC(hWnd, hMemDC);
  167.     hMemDC = CreateCompatibleDC(hdc);
  168.  HBITMAP hbmpold = (HBITMAP)SelectObject(hMemDC, hBitmap);
  169. //    BitBlt(hdc, 0, 0,   // dest
  170. //           (int)tailleX, (int)tailleY,
  171. //                hMemDC,        // src
  172. //                0, 0, SRCCOPY);
  173.  StretchBlt(hdc, 0, 0, tailleFenetre.right, tailleFenetre.bottom, hMemDC, 0, 0, tailleX, tailleY, SRCCOPY);
  174.     SelectObject(hMemDC, hbmpold);
  175.     DeleteDC(hMemDC);
  176. //  HBITMAP hBitmap=CreateCompatibleBitmap(hMemDC, tailleX, tailleY);
  177. // SetDIBits(hMemDC, hBitmap, 0, tailleY, tableau, &bi, DIB_RGB_COLORS);
  178. //            DeleteObject(hBitmap);
  179. /*
  180.  SetStretchBltMode(hdc, HALFTONE);
  181.  SetBrushOrgEx(hdc, 0, 0, 0);
  182.          
  183.  StretchDIBits(
  184.            hdc,
  185.            0, 0, 640, 480, //tailleFenetre.right, tailleFenetre.bottom,
  186.            0, 0, tailleX, tailleY,
  187.            tableau,
  188.            &bi,
  189.            0,
  190.            0
  191.          );
  192.          */
  193.          EndPaint(hWnd, &ps);
  194.          break;
  195.         }
  196. case WM_DESTROY:
  197. PostQuitMessage(0);
  198. break;
  199. default:
  200. return DefWindowProc(hWnd, message, wParam, lParam);
  201. }
  202. return 0;
  203. }
  204. // Gestionnaire de messages pour la boîte de dialogue À propos de.
  205. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  206. {
  207. UNREFERENCED_PARAMETER(lParam);
  208. switch (message)
  209. {
  210. case WM_INITDIALOG:
  211. return (INT_PTR)TRUE;
  212. case WM_COMMAND:
  213. if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
  214. {
  215.  EndDialog(hDlg, LOWORD(wParam));
  216.  return (INT_PTR)TRUE;
  217. }
  218. break;
  219. }
  220. return (INT_PTR)FALSE;
  221. }

Reply

Marsh Posté le 26-10-2010 à 13:20:57    

tpierron a écrit :

Haha, GDI et son API de merde.

Elle est pas particulièrement merdique quand on passe un peu de temps dedans. Mais elle nécessite un peu d'apprentissage. Faut trouver des infos dans des bouquins un peu anciens comme ceux de Martin Heller (Advanced Win32 Programming, etc), mais je ne sais pas si on les trouve encore hors occase.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 26-10-2010 à 21:48:29    

gilou a écrit :

Elle est pas particulièrement merdique quand on passe un peu de temps dedans. Mais elle nécessite un peu d'apprentissage. Faut trouver des infos dans des bouquins un peu anciens comme ceux de Martin Heller (Advanced Win32 Programming, etc), mais je ne sais pas si on les trouve encore hors occase.
A+,


 
Sans doute qu'une bonne doc permet de mieux comprendre le fonctionnement de cet API. Ceci dit, j'ai essayé de comprendre pourquoi le code de olivthill marche et pas le mien. En le remodifiant un peu le code suivant marche :  

Code :
  1. PAINTSTRUCT ps;
  2. HDC hdc=BeginPaint(hWnd, &ps);
  3. RECT tailleFenetre;
  4. BITMAPINFO bi; bi.bmiHeader.biBitCount=32; bi.bmiHeader.biClrImportant=0; bi.bmiHeader.biClrUsed=0; bi.bmiHeader.biCompression=BI_RGB;bi.bmiHeader.biHeight= -tailleY; bi.bmiHeader.biWidth=tailleX;  bi.bmiHeader.biPlanes=1;  bi.bmiHeader.biSize=sizeof(bi.bmiHeader);
  5. bi.bmiHeader.biSizeImage=0;  bi.bmiHeader.biXPelsPerMeter=0;  bi.bmiHeader.biYPelsPerMeter=0;
  6. GetClientRect(hWnd, &tailleFenetre);
  7. HBITMAP hBitmap= CreateDIBitmap(hdc, &bi.bmiHeader,CBM_INIT,tableau,&bi,DIB_RGB_COLORS);
  8. hMemDC = CreateCompatibleDC(hdc);
  9. HBITMAP hbmpold = (HBITMAP)SelectObject(hMemDC, hBitmap);
  10. StretchBlt(hdc, 0, 0, tailleFenetre.right, tailleFenetre.bottom, hMemDC, 0, 0, tailleX, tailleY, SRCCOPY);
  11. SelectObject(hMemDC, hbmpold);
  12. DeleteDC(hMemDC);
  13. EndPaint(hWnd, &ps);


 
Ce qui me porte à croire qu'il faut impérativement exécuter le code 'createDIBitmap' avec le Displau device context cible, et pas avec un memory device context. Pour qui ? pour quoi ? ça... mystère.
 
En tous cas merci les gars!

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed