Flackern beim zeichnen mit WinAPi

Hallo alle zusammen,

ich habe ein Problem und hoffe ihr könnt mir helfen.

Also Grundproblem:
Ich soll mit der WinAPi ein von einer externen Software berechnetes 3D - Wellenbild grafisch darstellen. Dafür baue ich mir eine 2dimensionale Matrix auf die dann dann über eine 2D-Array die Höheninformationen erhält die anschließend dann als Farbiges Feld ausgegeben werden sollen, wobei die Farbe abhängig von der Höhe ist.

Aktuell arbeite ich an der optischen Aufbau der Matrix. Ich habe für Testwecken mir ein Feld von 100x100 Rechtecken aufgebaut sowie eine Funktion die dynamisch die Farbe ändert. Den Quellcode findet ihr im Anhang.

Ich hab dabei nun 2 Probleme.

1. Wie kann ich von den Rechtecken den Rand entfernen, so das es am Ende bei gleicher Farbe wie ein großes Rechteck aussieht?

2. Das Bild flackert ziemlich. Ich hab gelesen das man das durch oppelbuffering verhindern kann, aber kein Vernünftiges Material dazu gefunden, vielleicht könnte mir das jemand ganz kurz erklären. :D

Und achja ich MUSS es mit WinAPI machen, klare Aneisung von oben, gibts kein drumrum. :D

Mein Code:
Code:
#define STRICT
#include <Windows.h>
#include <math.h>
const char szAppName[] = "drawObect";
#define ID_TIMER_COLOR  1
const double pi = 3.14159;
int ifarbe = 255;
bool bchange = true;

LRESULT CALLBACK WndProc(
                    HWND,
                    UINT,
                    WPARAM,
                    LPARAM);

int WINAPI WinMain (
                    HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    PSTR szCmdLine,
                    int iCmdShow)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS wc;
                wc.style = CS_HREDRAW | CS_VREDRAW;
                wc.lpfnWndProc = WndProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = hInstance;
                wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
                wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
                wc.lpszClassName = szAppName;
                wc.lpszMenuName = NULL;
                RegisterClass(&wc);

    hWnd = CreateWindow(
        szAppName,
        "DrawObject",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static RECT     rect;
    static double   dGrad;

   
    switch (message)
    {
    case WM_CREATE:
      {
         SetTimer(hWnd, ID_TIMER_COLOR, 30, NULL);
         return 0;
      }
   case WM_SIZE:
      {
         rect.right  = LOWORD(lParam);
         rect.bottom = HIWORD(lParam);
         return 0;
      }
   case WM_PAINT:
      {
         PAINTSTRUCT    ps;
         HDC            hDC;
         
         hDC = BeginPaint(hWnd, &ps);
         {
             HBRUSH hOldBrush;

             for (int j = 0; j <=100; j++) { 
             for (int i = 0; i <=100; i++) { 
            hOldBrush = (HBRUSH)SelectObject(hDC, 
                                             CreateSolidBrush(RGB(ifarbe,ifarbe,225)));

            RoundRect(hDC, rect.left + rect.right / 100 *i  , rect.top  + rect.bottom/5 + rect.bottom / 100 *j  ,
                           rect.left + rect.right / 100 + rect.right / 100 *i , rect.top + rect.bottom / 100 + rect.bottom/5 + rect.bottom / 100 *j , 0, 0);
                                    DeleteObject(SelectObject(hDC, hOldBrush));
             }
             }

         }
         EndPaint(hWnd, &ps);
         return 0;
      }
   case WM_TIMER:
      {

         switch (wParam)
         {
            case ID_TIMER_COLOR:
            {

               
               
               if (ifarbe == 0)
                bchange = false;

                   if (ifarbe == 255) 
                    bchange = true;
               
                if (bchange == true)
               ifarbe--; 
                else
                    ifarbe++;

                InvalidateRect(
                    hWnd,
                    NULL,
                    TRUE);

               break;

            }
            }
         return 0;
     }    
       
   case WM_DESTROY:
      {
         KillTimer(hWnd, ID_TIMER_COLOR);
         PostQuitMessage(0);
         return 0;
      }
    }

   return DefWindowProc(hWnd, message, wParam, lParam);

}
 
1. Wie kann ich von den Rechtecken den Rand entfernen, so das es am Ende bei gleicher Farbe wie ein großes Rechteck aussieht?
FillRect
2. Das Bild flackert ziemlich. Ich hab gelesen das man das durch oppelbuffering verhindern kann, aber kein Vernünftiges Material dazu gefunden, vielleicht könnte mir das jemand ganz kurz erklären. :D
Also kleine Spiele nur mit der GDI gehen ganz gut ;)
Es sollte noch WM_ERASEBKGND abgefangen werden:
Code:
   case WM_ERASEBKGND:
     return 1;

Code:
   case WM_ERASEBKGND:
     return 1;
   case WM_PAINT:
      {
         PAINTSTRUCT    ps;
         HDC            hDC;
         RECT           mini_rect;
         
         hDC = BeginPaint(hWnd, &ps);
         {
             HBRUSH hOldBrush;

             for (int j = 0; j <=100; j++) { 
             for (int i = 0; i <=100; i++) { 
            //hOldBrush = (HBRUSH)SelectObject(hDC, 
            //                                 CreateSolidBrush(RGB(ifarbe,ifarbe,225)));  ? was soll hier herauskommen?
            HBRUSH myBrush = CreateSolidBrush(RGB(ifarbe,i+100,j+100));  // schaut cooler aus :)

            
            mini_rect.left = rect.left + rect.right / 100 *i;
            mini_rect.top = rect.top  + rect.bottom/5 + rect.bottom / 100 *j;
            mini_rect.right = rect.left + rect.right / 100 + rect.right / 100 *i;
            mini_rect.bottom = rect.top + rect.bottom / 100 + rect.bottom/5 + rect.bottom / 100 *j;
            FillRect(hDC, &mini_rect, myBrush);
            //RoundRect(hDC, rect.left + rect.right / 100 *i  , rect.top  + rect.bottom/5 + rect.bottom / 100 *j  ,
              //             rect.left + rect.right / 100 + rect.right / 100 *i , rect.top + rect.bottom / 100 + rect.bottom/5 + rect.bottom / 100 *j , 0, 0);
            DeleteObject(myBrush);
             }
             }

         }
         EndPaint(hWnd, &ps);
         return 0;
      }
 
Danke für deine Antwort CDW,

sorry das ich es erst jetzt sehe, mein Emailpostfach hat die Abo-Email in den Spam Ordner getan. :rolleyes:

Ich bin inzwischen auf Pixel umgestiegen und habe versucht das ganze mit Double Buffering hinzubekommen, hänge da aber irgentwie fest.

Quellcode:
Code:
hDC = BeginPaint(hWnd, &ps);  //Zeichenfenster hDC erstellen
{
HDC hDC2 = CreateCompatibleDC(hDC); //Zeichenfesnter hDC2 erstellen
HBITMAP hBM = CreateCompatibleBitmap(hDC, rect.right, rect.bottom);  
                                                  //Eigenschaften festlegen
SelectObject(hDC2, hBM);     // hDC2 auswhälen

TextOut(    // Text in hDC2 schreiben
hDC2,
0,
40,
szBeschreibung1,
sizeof(szBeschreibung1)-1);

TextOut(    // Text in hDC2 schreiben
hDC2,
0,
60,
szBeschreibung2,
sizeof(szBeschreibung2)-1);

TextOut(    // Text in hDC2 schreiben
hDC2,
0,
80,
szBeschreibung3,
sizeof(szBeschreibung3)-1);
             
DrawText(hDC2,    // Text in hDC2 schreiben
szTitel,
lstrlen(szTitel),
&rect,
DT_SINGLELINE | DT_CENTER);
             

// Pixelmatrix in hDC2 schreiben

HBRUSH hOldBrush;
            
for (int j = 0; j <=500; j++) { 
for (int i = 0; i <=500; i++) { 
hOldBrush = (HBRUSH)SelectObject(hDC2, CreateSolidBrush(RGB( matrix[i][j] , matrix[i][j], 225)));

SetPixel( hDC2, i, j+100, RGB(matrix[i][j],matrix[i][j],255) ); 

DeleteObject(SelectObject(hDC2, hOldBrush)); //Pinsel freigeben
BitBlt(hDC, 0, 0, rect.right, rect.bottom, hDC2, 0, 0, SRCCOPY);  //hDC mit hDC2 überschreiben
DeleteObject(hBM);  //Eigenschaften feigeben
DeleteDC(hDC2); // hDC2 freigeben
}
}

}
EndPaint(hWnd, &ps); //Zeichnen Ende
return 0;
}


So sollte das aussehen (bzw. so sieht es aus mit setPixel)
http://www.apload.de/images-i188313bbhjdc.png

Aussehen tut es aber ungefähr so:
http://www.apload.de/images-i188314b44v7l.png

Also grundlegend scheint das mit dem übergeben ja zu funktionieren sonst wäre die Schrift nicht da. Aber bei der Animation funktioniert das nicht.

Hat jemand eine Idee? Da der Combpiler keine Fehler meldung ausspuckt sitze ich bustäblich planlos da.
 
BitBlt + SetPixel ist wie ein Ferrary mit Solarantrieb :)
Einfachste Lösung:
wie schon gesagt - einfach
Code:
case WM_ERASEBKGND:
     return 1;
abfangen und direkt mit SetPixel in HDC zeichnen.
Eventuell GDI+ Funktionen ansehen (bin nie dazu gekommen,
weil man irgendwann keine Lust auf "low-level pixelschubserei" hat :))

BitBlt würde ich in dem Zusammenhang eher mit einem
"komplett manuellen" Zeichnen in ein Array betrachten
my_bmp_arry[x + y*WIDTH], welches man
dann direkt als Bitmap mit BitBlt kopiert.
Hier mal Code aus dem ersten Posting, welcher einen Speichblock reserviert,
direkt die RGB Werte schreibt und dann den kompletten Block in
einem Rutsch rüberkopiert.
Vorteil: schnell (bei SetPixel kann man dagegen den Bildaufbau sehen ;) )
Reicht sogar für kleine 2D Spiele aus (wenn man es mag das Rad neu zu erfinden und/oder seine
Mathekenntnisse auffrischen möchte und daher alle Primitiv-Zeichenfunktionen (Gerade, Kreis, Füllen, Textur zeichnen/skalieren)
selber schreibt)
Code:
#define STRICT
#include <Windows.h>
#include <math.h>
const char szAppName[] = "drawObect";
#define ID_TIMER_COLOR  1
const double pi = 3.14159;
int ifarbe = 255;
bool bchange = true;

// new
BITMAPINFO bmi;
HDC hCompDC = 0;
HBITMAP hCopyImage = 0;
HDC hDC = 0;
DWORD *display = 0;




LRESULT CALLBACK WndProc(
                    HWND,
                    UINT,
                    WPARAM,
                    LPARAM);

int WINAPI WinMain (
                    HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    PSTR szCmdLine,
                    int iCmdShow)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS wc;
                wc.style = CS_HREDRAW | CS_VREDRAW;
                wc.lpfnWndProc = WndProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = hInstance;
                wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
                wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
                wc.lpszClassName = szAppName;
                wc.lpszMenuName = NULL;
                RegisterClass(&wc);

    hWnd = CreateWindow(
        szAppName,
        "DrawObject",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

void create_bitmap_stuff(HWND hWnd, int width, int height)
{
   bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
   bmi.bmiHeader.biWidth = width;
   bmi.bmiHeader.biHeight = height;
   bmi.bmiHeader.biPlanes = 1;

   bmi.bmiHeader.biBitCount = 32;
   bmi.bmiHeader.biCompression = 0;
   bmi.bmiHeader.biSizeImage = 0;
   bmi.bmiHeader.biXPelsPerMeter = 0;
   bmi.bmiHeader.biYPelsPerMeter = 0;
   bmi.bmiHeader.biClrImportant = 0;
   if (hCompDC != 0)
   {
       ReleaseDC(hWnd, hCompDC);
       DeleteObject(hCompDC);
   }
   if (hCopyImage != 0)
       DeleteObject(hCopyImage);
       
   if (display != 0)
       free(display);
       
   hCompDC = CreateCompatibleDC(GetDC(hWnd));
   hCopyImage = CreateCompatibleBitmap(GetDC(hWnd),width, height);
   SelectObject(hCompDC, hCopyImage);   
   display = (DWORD*)malloc(width * height * sizeof(DWORD)+1);
   
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static RECT     rect;
    static double   dGrad;

   
    switch (message)
    {
    case WM_CREATE:
      {
         SetTimer(hWnd, ID_TIMER_COLOR, 30, NULL);
         create_bitmap_stuff(hWnd, rect.right, rect.bottom);
         return 0;
      }
   case WM_SIZE:
      {
         rect.right  = LOWORD(lParam);
         rect.bottom = HIWORD(lParam);
         create_bitmap_stuff(hWnd, rect.right, rect.bottom);
         return 0;
      }
   case WM_ERASEBKGND:
     return 1;
   case WM_PAINT:
      {
         PAINTSTRUCT    ps;
         HDC            hDC;
         RECT           mini_rect;
         
         hDC = BeginPaint(hWnd, &ps);  //Zeichenfenster hDC erstellen          
         for (int y = 0; y <=500; y++) 
           for (int x = 0; x <=500; x++)
           // hier sollte man beachten, dass 'display' eine bestimmte größe hat
           // also noch irgendeine Umwwandlung vornehmen, wenn man z.B feste größe 500
           // auf eine variable Größe blitten möchte...
             display[x + y * rect.right] = RGB(ifarbe,x,y);
           
         SetDIBits(hCompDC,hCopyImage,0,rect.right,
                     display,&bmi,DIB_RGB_COLORS);
    
         BitBlt(hDC, 0, 0, rect.right, rect.bottom, 
                hCompDC, 0, 0, SRCCOPY);  
         EndPaint(hWnd, &ps); //Zeichnen Ende
    return 0;
}
   case WM_TIMER:
      {

         switch (wParam)
         {
            case ID_TIMER_COLOR:
            {

               
               
               if (ifarbe == 0)
                bchange = false;

                   if (ifarbe == 255) 
                    bchange = true;
               
                if (bchange == true)
               ifarbe--; 
                else
                    ifarbe++;

                InvalidateRect(
                    hWnd,
                    NULL,
                    TRUE);

               break;

            }
            }
         return 0;
     }    
       
   case WM_DESTROY:
      {
         KillTimer(hWnd, ID_TIMER_COLOR);
         PostQuitMessage(0);
         return 0;
      }
    }

   return DefWindowProc(hWnd, message, wParam, lParam);

}
PS: Keine Garantie, dass es keine Memory- oder Handlerleaks gibt.
Und man sollte grundsäztlich Rückgabewerte prüfen - so lassen sich Fehler schneller finden ;)
 
Ha Danke für die Antwort, hab garnicht gewusst das Visual Express C++ 2010 beim Debuggen automatisch speichert und man auch nicht emhr zurückkehren kann. Hab gerade meinen Quellcode mit deinem Überschrieben und damit meine ganze Arbeit gelöscht. :rolleyes::D

Musste mir jetzt erstmal wieder alles zusammenfriemeln.^^

Ich hab dann versucht meine Sachen an deinen Quelltext anzugleichen und zu übertragen. Mit dem Ergebnis das er keine Fehler anzeigt aber beim Debuggen schwere Fehler verursacht, genauer gesagt folgenden:

Windows hat einen Haltepunkt in BAWWELLE.exe ausgelöst.

Dies kann auf eine Beschädigung des Heaps zurückzuführen sein, die auf ein Problem in BAWWELLE.exe oder in einer der geladenen DLLs hinweist.

Dies kann auch darauf zurückzuführen sein, dass der Benutzer F12 drückt, während BAWWELLE.exe den Fokus hat.

Weitere Analyseinformationen finden Sie möglicherweise im Ausgabefenster.

Ich hasse es wenn Fehlermeldungen einfach so auftauchen. Hast du eine Idee woran das liegen könnte?

Hier nochmal der aktuelle Quellcode.

Code:
#define STRICT
#include <Windows.h>
#include <math.h>
const char szAppName[] = "drawObect";
#define ID_TIMER_COLOR  1
const double pi = 3.14159;
int ifarbe = 255;
bool bchange = true;
const char szTitel[] = "BAW Wellenmodell 1";
const char szBeschreibung1[] = "Linke Maustaste drücken = Wellenmodell pausieren";
const char szBeschreibung2[] = "Linke Maustaste gedrückt halten, ziehen und loslassen = Linie zeichnen";
const char szBeschreibung3[] = "Rechte Maustaste drücken = Linien entfernen, Wellenmodell fortsetzen";
short matrix[500][500] = { 0 };
double z = 1;


// new
BITMAPINFO bmi;
HDC hCompDC = 0;
HBITMAP hCopyImage = 0;
HDC hDC = 0;
DWORD *display = 0;




LRESULT CALLBACK WndProc(
                    HWND,
                    UINT,
                    WPARAM,
                    LPARAM);

int WINAPI WinMain (
                    HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    PSTR szCmdLine,
                    int iCmdShow)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS wc;
                wc.style = CS_HREDRAW | CS_VREDRAW;
                wc.lpfnWndProc = WndProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = hInstance;
                wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
                wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
                wc.lpszClassName = szAppName;
                wc.lpszMenuName = NULL;
                RegisterClass(&wc);

    hWnd = CreateWindow(
        szAppName,
        "DrawObject",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        500,
        700,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

void create_bitmap_stuff(HWND hWnd, int width, int height)
{
   bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
   bmi.bmiHeader.biWidth = width;
   bmi.bmiHeader.biHeight = height;
   bmi.bmiHeader.biPlanes = 1;

   bmi.bmiHeader.biBitCount = 32;
   bmi.bmiHeader.biCompression = 0;
   bmi.bmiHeader.biSizeImage = 0;
   bmi.bmiHeader.biXPelsPerMeter = 0;
   bmi.bmiHeader.biYPelsPerMeter = 0;
   bmi.bmiHeader.biClrImportant = 0;
   if (hCompDC != 0)
   {
       ReleaseDC(hWnd, hCompDC);
       DeleteObject(hCompDC);
   }
   if (hCopyImage != 0)
       DeleteObject(hCopyImage);
       
   if (display != 0)
       free(display);
       
   hCompDC = CreateCompatibleDC(GetDC(hWnd));
   hCopyImage = CreateCompatibleBitmap(GetDC(hWnd),width, height);
   SelectObject(hCompDC, hCopyImage);   
   display = (DWORD*)malloc(width * height * sizeof(DWORD)+1);
   
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static RECT     rect;
    static double   dGrad;

   
    switch (message)
    {
    case WM_CREATE:
      {
         SetTimer(hWnd, ID_TIMER_COLOR, 30, NULL);
         create_bitmap_stuff(hWnd, rect.right, rect.bottom);
         return 0;
      }
   case WM_SIZE:
      {
         rect.right  = LOWORD(lParam);
         rect.bottom = HIWORD(lParam);
         create_bitmap_stuff(hWnd, rect.right, rect.bottom);
         return 0;
      }
   case WM_ERASEBKGND:
     return 1;
   case WM_PAINT:
      {
         PAINTSTRUCT    ps;
         HDC            hDC;
         RECT           mini_rect;
         
         hDC = BeginPaint(hWnd, &ps);  //Zeichenfenster hDC erstellen          
         for (int i = 0; i <=500; i++) 
           for (int j = 0; j <=500; j++)
           // hier sollte man beachten, dass 'display' eine bestimmte größe hat
           // also noch irgendeine Umwwandlung vornehmen, wenn man z.B feste größe 500
           // auf eine variable Größe blitten möchte...
             display[i + j * rect.right] = RGB(255,matrix[i][j],matrix[i][j]);
           
         SetDIBits(hCompDC,hCopyImage,0,rect.right,
                     display,&bmi,DIB_RGB_COLORS);
    
         BitBlt(hDC, 0, 0, rect.right, rect.bottom, 
                hCompDC, 0, 0, SRCCOPY);  
         EndPaint(hWnd, &ps); //Zeichnen Ende
    return 0;
}
   case WM_TIMER:
      {

         switch (wParam)
         {
            case ID_TIMER_COLOR:
            {

               
       if (z >= 255)
                    bchange = true; 

                if (z <= 1) {
                    bchange = false; }
            for (int j = 0; j <=500; j++) { 
            for (int i = 0; i <=500; i++) { 
                double x = i;
                double y = j;


                double formel = ((150 - z)/150*((sin(x/160)*cos(y/300)) + 1)*(255/2));
                int ergebnis = formel;
                matrix[i][j] =  255-ergebnis;
             }}
                if (bchange == false)
                    z--;

                if (bchange == true)
                    z++;

                    InvalidateRect(
                    hWnd,
                    NULL,
                    FALSE);

                break;

            }
            }
         return 0;
     }    
       
   case WM_DESTROY:
      {
         KillTimer(hWnd, ID_TIMER_COLOR);
         PostQuitMessage(0);
         return 0;
      }
    }

   return DefWindowProc(hWnd, message, wParam, lParam);

}
 
Ich hasse es wenn Fehlermeldungen einfach so auftauchen. Hast du eine Idee woran das liegen könnte?
1. Wenn das Bild eher 1:1 der Matrix entsprechen soll, so kann man sich das reallozieren des "display" sparen (fest vorgeben auf 500 * 500 * RGB_size).
2. Die Zeichenroutine in diesem Code prüft nicht, ob das Bild auch reinpasst (sprich: aktuell wird das "display" in Abhängigkeit von der Fenstergröße alloziert - kann auch kleine 500 * 500 sein)
Deswegen meinte ich, dass man hier "mappen" bzw. scalieren könnte, so dass die Matrix in Abhängigkeit von der Fenstergröße dargestellt wird.
Oder eben festsetzt.

3. "Off By One" sollte man schon vermeiden ;)
Code:
short matrix[[COLOR=black]500[/COLOR]][[COLOR=black]500[/COLOR]] = { 0 };
...
for (int i = 0; i <=[COLOR=black]500[/COLOR]; i++) 
           for (int j = 0; j <=[COLOR=black]500[/COLOR]; j++)
Worauf greift man bei matrix[500][500] nun zu?
 
1. Wenn das Bild eher 1:1 der Matrix entsprechen soll, so kann man sich das reallozieren des "display" sparen (fest vorgeben auf 500 * 500 * RGB_size).

Soll es ja nicht, sollen zwei teile sein, einmal 500x200 für einen Weißen Bereich wo Text hinkommt und dann 500x500 direkt dadrunter.

2. Die Zeichenroutine in diesem Code prüft nicht, ob das Bild auch reinpasst (sprich: aktuell wird das "display" in Abhängigkeit von der Fenstergröße alloziert - kann auch kleine 500 * 500 sein)

Deswegen meinte ich, dass man hier "mappen" bzw. scalieren könnte, so dass die Matrix in Abhängigkeit von der Fenstergröße dargestellt wird.
Oder eben festsetzt.

Soll es im Grunde auch nicht, weil ich die Umrandung fest vorgeben und nicht verändern werde. Muss ich noch ändern. :D

3. "Off By One" sollte man schon vermeiden ;)

Was meinst du damit?
Code:
short matrix[[COLOR=black]500[/COLOR]][[COLOR=black]500[/COLOR]] = { 0 };
...
for (int i = 0; i <=[COLOR=black]500[/COLOR]; i++) 
           for (int j = 0; j <=[COLOR=black]500[/COLOR]; j++)
Worauf greift man bei matrix[500][500] nun zu?

Na ich erstelle eine 3D Matrix mit x und y die 100 Stellen haben. im Case Timer soll die Matrixx anhand der Formel mit Höheninformationen gefüllt werden die dann im paint in Echtzeit gezeichnet werden sollen.
 
Soll es ja nicht, sollen zwei teile sein, einmal 500x200 für einen Weißen Bereich wo Text hinkommt und dann 500x500 direkt dadrunter.
'display' kann man dann trotzdem als DWORD Array der Größe 500 * 500 definieren. Das ist nämlich nur der Teil, wohin die Matrix gezeichnet wird. Den Text kann man weiterhing mit DrawText oder ähnlihcem zeichnen ;)
display = malloc(foo) macht nur Sinn, wenn das Bild unterschiedliche Größe haben soll.

Soll es im Grunde auch nicht, weil ich die Umrandung fest vorgeben und nicht verändern werde. Muss ich noch ändern. :D
Ariane4 Softwareentwickler hat gesagt.:
Die Zahl wird eher nie größer als 2^15!!!
Ariane5
Ariane%205.gif




Was meinst du damit?
matrix wird als
matrix[500][500] definiert. Die Indizes gehen also von 0..499, 0..499
Zugegriffen wird aber in einem Loop, in dem i = j = 500 sein kann.
Damit greift man auf den Speicher außerhalb der Matrix zu.
 
'display' kann man dann trotzdem als DWORD Array der Größe 500 * 500 definieren. Das ist nämlich nur der Teil, wohin die Matrix gezeichnet wird. Den Text kann man weiterhing mit DrawText oder ähnlihcem zeichnen ;)
display = malloc(foo) macht nur Sinn, wenn das Bild unterschiedliche Größe haben soll.

Wird die Größe vom Display den nicht durch die Forschleifen angegeben? So hätte ich das jetzt verstanden, die Forschleifen geben die x/y Koordinaten an die dann im ersten Term von display[i + j * rect.right] = RGB(255,matrix[j],matrix[j]); von der Function erfasst und anschließend mit der Farbe aufgefüllt werden. Scheint aber nicht so zu sein. Ich habe festgestellt das die Funktion scheinbar alles andere trotzdem schwarz rendert, was beim weißen Hintergrund und der Schrift ab und zu zu flackern führt...

So sieht meine Paintfunktion aktuell aus:
Code:
case WM_PAINT:
      {
         PAINTSTRUCT    ps;
         HDC            hDC;
         RECT           mini_rect;
         
         hDC = BeginPaint(hWnd, &ps);  //Zeichenfenster hDC erstellen  


         for (int i = 0; i <=499; i++) 
           for (int j = 0; j <=499; j++)
           // hier sollte man beachten, dass 'display' eine bestimmte größe hat
           // also noch irgendeine Umwwandlung vornehmen, wenn man z.B feste größe 500
           // auf eine variable Größe blitten möchte...
             display[i + j * rect.right] = RGB(255,matrix[i][j],matrix[i][j]);
           
         SetDIBits(hCompDC,hCopyImage,0,rect.right,
                     display,&bmi,DIB_RGB_COLORS);
    
         BitBlt(hDC, 0, 0, rect.right, rect.bottom, 
                hCompDC, 0, 0, SRCCOPY);  

                RoundRect(hDC, rect.left, rect.top,
                rect.left + 500, rect.top + 175, 0, 0);

            TextOut(
                hDC,
                10,
                40,
                szBeschreibung1,
                sizeof(szBeschreibung1)-1);

                TextOut(
                hDC,
                10,
                60,
                szBeschreibung2,
                sizeof(szBeschreibung2)-1);

                TextOut(
                hDC,
                10,
                80,
                szBeschreibung3,
                sizeof(szBeschreibung3)-1);
             
             DrawText(hDC,
                szTitel,
                lstrlen(szTitel),
                &rect,
                DT_SINGLELINE | DT_CENTER);


         EndPaint(hWnd, &ps); //Zeichnen Ende
    return 0;
}


ich finde es ziemlich ärgerlich, dass es dafür kein vernünftiges Tutorial gibt.


Ist das so zwecklos mit mir? :D

matrix wird als
matrix[500][500] definiert. Die Indizes gehen also von 0..499, 0..499
Zugegriffen wird aber in einem Loop, in dem i = j = 500 sein kann.
Damit greift man auf den Speicher außerhalb der Matrix zu.

Ei, mit der dümmste Fehler den ein Programmierer fabrizieren kann. :D

Ok jetzt scheint es zu laufen, bis auf das Flackern des weißen rechtecks und der Schrift.

Kannst du mir eigentlich ein gutes Buch dazu empfehlen?
 
Wird die Größe vom Display den nicht durch die Forschleifen angegeben?
Hm, ich rede nur vom "DWORD *display" Speicherblock, der als "Bitmap" missbraucht wird. Wenn dieser immer das Bild gleicher Größe anzeigen muss, dann reicht auch eine konstante Größe/Definition ala
Code:
DWORD display[500 * 500] oder gleich display[500][500]

Ich habe festgestellt das die Funktion scheinbar alles andere trotzdem schwarz rendert, was beim weißen Hintergrund und der Schrift ab und zu zu flackern führt...
Ich denke das Blitting ist falsch - als Ausrede kann ich nur erwähnen, dass bei meinen "Zeichenanwendngen" alles überzeichnet wurde, nicht nur
ein Teil des Fensters :)

Formatierung von Notepad2 (also "irgendwie"), hässlich viele globale Variablen, die am Ende nicht freigegeben werden und
selbstverständlich auf Sand gebaut (also mit der Annahme, dass das Fenster nicht vergrößert/verkleinert wird) :)
Aber das Prinzip sollte klar sein.
Code:
#define STRICT
#include <Windows.h>
#include <math.h>
#include <stdio.h>
const char szAppName[] = "drawObect";
#define ID_TIMER_COLOR  1
const double pi = 3.14159;
int ifarbe = 255;
bool bchange = true;
const char szTitel[] = "BAW Wellenmodell 1";
const char szBeschreibung1[] = "Linke Maustaste drücken = Wellenmodell pausieren";
const char szBeschreibung2[] = "Linke Maustaste gedrückt halten, ziehen und loslassen = Linie zeichnen";
const char szBeschreibung3[] = "Rechte Maustaste drücken = Linien entfernen, Wellenmodell fortsetzen";
short matrix[501][501] = { 0 };
double z = 1;


// new
BITMAPINFO bmi;
HBITMAP hCopyImage = 0;
HDC hDC = 0;
HDC hBufferDC = 0;
HBRUSH back_brush = 0;

#define IMG_POS_X 10 
#define IMG_POS_Y  200
#define IMG_WIDTH 500
#define IMG_HEIGHT 500
#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 800

DWORD display[IMG_WIDTH][IMG_HEIGHT] = {0};

LRESULT CALLBACK WndProc(
                    HWND,
                    UINT,
                    WPARAM,
                    LPARAM);

int WINAPI WinMain (
                    HINSTANCE hInstance,
                    HINSTANCE hPrevInstance,
                    PSTR szCmdLine,
                    int iCmdShow)
{
    HWND hWnd;
    MSG msg;
    WNDCLASS wc;
                wc.style = CS_HREDRAW | CS_VREDRAW;
                wc.lpfnWndProc = WndProc;
                wc.cbClsExtra = 0;
                wc.cbWndExtra = 0;
                wc.hInstance = hInstance;
                wc.hCursor = LoadCursor(NULL, IDC_ARROW);
                wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
                wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
                wc.lpszClassName = szAppName;
                wc.lpszMenuName = NULL;
                RegisterClass(&wc);
                
    
        bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
        bmi.bmiHeader.biWidth = IMG_WIDTH;
        bmi.bmiHeader.biHeight = IMG_HEIGHT;
        bmi.bmiHeader.biPlanes = 1;

        bmi.bmiHeader.biBitCount = 32;
        bmi.bmiHeader.biCompression = 0;
        bmi.bmiHeader.biSizeImage = 0;
        bmi.bmiHeader.biXPelsPerMeter = 0;
        bmi.bmiHeader.biYPelsPerMeter = 0;
        bmi.bmiHeader.biClrImportant = 0;
        

    hWnd = CreateWindow(
        szAppName,
        "DrawObject",
        (WS_OVERLAPPEDWINDOW | WS_SYSMENU) - (WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME),
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        NULL,
        NULL,
        hInstance,
        NULL);

    ShowWindow(hWnd, iCmdShow);
    UpdateWindow(hWnd);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}


  

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static RECT     rect;
    static double   dGrad;

   
    switch (message)
    {
    case WM_CREATE:
      {
        hBufferDC = CreateCompatibleDC(GetDC(hWnd));
        hCopyImage = CreateCompatibleBitmap(GetDC(hWnd),
                                            WINDOW_WIDTH, WINDOW_HEIGHT);
        SelectObject(hBufferDC, hCopyImage); 
        back_brush = CreateSolidBrush(RGB(255,182,193));
         SetTimer(hWnd, ID_TIMER_COLOR, 30, NULL);
         return 0;
      }
   case WM_SIZE:
      {
         rect.right  = LOWORD(lParam);
         rect.bottom = HIWORD(lParam);
         return 0;
      }
   case WM_ERASEBKGND:
     return 1;
     
   case WM_PAINT:
      {
         PAINTSTRUCT    ps;
         HDC            hDC;
         RECT           mini_rect;
        
         hDC = BeginPaint(hWnd, &ps);  //Zeichenfenster hDC erstellen  

         // Hintergrund löschen
         FillRect(hBufferDC, &rect, back_brush);
         
         for (int i = 0; i <=499; i++)
           for (int j = 0; j <=499; j++)
           // hier sollte man beachten, dass 'display' eine bestimmte größe hat
           // also noch irgendeine Umwwandlung vornehmen, wenn man z.B feste größe 500
           // auf eine variable Größe blitten möchte...
             display[i][j] = RGB(255,matrix[j][i],matrix[j][i]);
          
         SetDIBitsToDevice(hBufferDC, 
             IMG_POS_X, IMG_POS_Y,
             IMG_WIDTH, IMG_HEIGHT,
             0,0,0,
             bmi.bmiHeader.biHeight, display,&bmi,DIB_RGB_COLORS);
         
         RoundRect(hBufferDC, rect.left, rect.top,
              rect.left + 500, rect.top + 175, 0, 0);
         
            TextOut(
                hBufferDC,
                10,
                40,
                szBeschreibung1,
                sizeof(szBeschreibung1)-1);

                TextOut(
                hBufferDC,
                10,
                60,
                szBeschreibung2,
                sizeof(szBeschreibung2)-1);

                TextOut(
                hBufferDC,
                10,
                80,
                szBeschreibung3,
                sizeof(szBeschreibung3)-1);
            
             DrawText(hBufferDC,
                szTitel,
                lstrlen(szTitel),
                &rect,
                DT_SINGLELINE | DT_CENTER);
                
 


              
              BitBlt(hDC, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
                     hBufferDC, 0, 0, SRCCOPY); 





         EndPaint(hWnd, &ps); //Zeichnen Ende
    return 0;
}
   case WM_TIMER:
      {

         switch (wParam)
         {
            case ID_TIMER_COLOR:
            {

               
       if (z >= 255)
                    bchange = true; 

                if (z <= 1) {
                    bchange = false; }
            for (int j = 0; j <=500; j++) { 
            for (int i = 0; i <=500; i++) { 
                double x = i;
                double y = j;


                double formel = ((150 - z)/150*((sin(x/160)*cos(y/300)) + 1)*(255/2));
                int ergebnis = formel;
                matrix[i][j] =  255-ergebnis;
             }}
                if (bchange == false)
                    z--;

                if (bchange == true)
                    z++;

                    InvalidateRect(
                    hWnd,
                    NULL,
                    FALSE);

                break;

            }
            }
         return 0;
     }    
       
   case WM_DESTROY:
      {
         //throw("free all gui-stuff handles :)");
         KillTimer(hWnd, ID_TIMER_COLOR);
         PostQuitMessage(0);
         return 0;
      }
    }

   return DefWindowProc(hWnd, message, wParam, lParam);

}


Ist das so zwecklos mit mir? :D
Ich meinte die impliziten Annahmen ala "sowas wird nie passieren, also muss man es auch nicht behandeln" ;)
Kannst du mir eigentlich ein gutes Buch dazu empfehlen?
Über ein gutes Buch dazu hätte ich mich vor ein paar Jahren auch gefreut :).
 
Ist das so zwecklos mit mir? :D
Nö, wegen einer falschen Umwandlung eines Floats in einen Int in einem überflüssigen Programm von der Ariane 4, was bei der Ariane 5 halt überflüssig war, ist selbige in die Luft geflogen. Man nahm an, dass die Zahl immer in die 15-Wertbits des Ints passen würden (1 Zeichenbit).
 
Zurück
Oben