DubbleBuffering und Klangwerker...(Anfänger!)
-
Ich habe hier einen Quellkode mit der Klangwerkerklasse. Kann mir nun noch einer bei der Implementierung helfen? Ich habe schon einmal den Code von KW eingefügt...
Bitte helft mir, dass es nicht mehr flackert - bin ja schon froh, dass ich es so weit geschafft habe
#include <stdio.h> #include <windows.h> #include <stdlib.h> #include "GrafixBuffer.h" //Klangwerker LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static int d, x,y, i, j, px, py; ///////////////////////WINMAIN///////////////////////////// /////////////////////////////////////////////////////////// int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow ) { /////////////////////Objekte//////////////////////////////// WNDCLASS wc; HWND hWnd; MSG Message; /////////////////////////////////////////////////////////// wc.style = 0; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.lpfnWndProc = (WNDPROC)WndProc; wc.hInstance = hInstance; wc.hIcon = 0; wc.hCursor = LoadCursor (0,IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = "Visualisierung"; /////////////////////////////////////////////////////////// RegisterClass (&wc); /////////////////////////////////////////////////////////// hWnd = CreateWindow("Visualisierung", "Visualisierung V1.0 Lagerverwaltung", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, 0,0, hInstance, 0); /////////////////////////////////////////////////////////// ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while (GetMessage (&Message,NULL,0,0) ) { DispatchMessage (&Message); } return Message.wParam; }//ENDE WINMAIN ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////WndProc///////////////////////////////////////////// LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int loop,loop2; switch (message) { case WM_CREATE: d=1; //d=Pixelschrittweite für Animation y=0; x=0; i=0; j=0; px=2;//Fachposition auf x py=5;//Fachposition auf y // Lokale Handles auf Windows Objekte static HDC hDC; static HDC hPen1, hPen2, hPen3, hOldPen; static PAINTSTRUCT ps; static RECT rect; GetClientRect(hWnd, &rect); SetTimer(hWnd, 1, 5, 0); // Periode in ms // Bereitstellen Zeichenstifte hPen1 = (HDC)CreatePen(PS_SOLID, 1, RGB(255,0,255));//Lagerbereichfensterstift hPen2 = (HDC)CreatePen(PS_SOLID, 1, RGB(155, 100,100)); hPen3 = (HDC)CreatePen(PS_SOLID, 3, RGB(255,51,153)); hOldPen = (HDC)SelectObject(hDC, hPen1); return 0; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); // Rechteck: links, oben, rechts, unten SelectObject(hDC, hPen1); Rectangle(hDC, 5, 5, 655, 700);//Lagerfensterbereichsgröße und Position (Hauptfenster) ///////////////// 5x5 Lagerplätze zeichnen for (loop=0;loop<=4;loop++) { for (loop2=0;loop2<=4;loop2++) { SelectObject(hDC, hPen2); Rectangle(hDC, (10+loop*130),(10+loop2*110), (130+loop*130),(110+loop2*110)); } } ///////////////////////////////// SelectObject(hDC, hPen3); //Wagen zeichnen Rectangle(hDC, 8+x, 8+y, 132+x, 112+y); //EndPaint(hWnd, &ps);//?????? return 0; //////////////////////////////////// case WM_TIMER: //Aktion, so lange der Timer läuft! if(i <= (px*130)) { x = i*d; i++; InvalidateRect(hWnd, &rect, 0); } //else // KillTimer(hWnd,1); if(j <= (py*110)) { y = j*d; j++; InvalidateRect(hWnd, &rect, 0); } //else //KillTimer(hWnd,1); return 0; case WM_DESTROY: // Alter Zustand wieder herstellen SelectObject(hDC, hOldPen); // Objekte löschen DeleteObject(hPen1); DeleteObject(hPen2); DeleteObject(hPen3); ReleaseDC(hWnd, hDC); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } ///////////////WndProc Ende////////////////////////////////////////////////////////////// // ------------------------------------------------------------------------------------- // -----------------implementation of class KGrafixBuffer------------------------------- // ------------------------------------------------------------------------------------- KGrafixBuffer::KGrafixBuffer( HINSTANCE hInstance, HWND hwnd) { HDC hdc = GetDC(hwnd); // temp dc to create buffer hdcSecondaryBuffer = CreateCompatibleDC(hdc); // create buffer // init buffer size and dimension int GetClientRect(hwnd, &rcBuffer); iWidth = rcBuffer.right - rcBuffer.left; // width of buffer iHeight = rcBuffer.bottom - rcBuffer.top; // height of buffer // create bitmap for drawing-operation hBufferBitmap = CreateCompatibleBitmap( hdc, iWidth, iHeight ); GetObject(hBufferBitmap, sizeof(BITMAP), &bmBuffer); SelectObject( hdcSecondaryBuffer, hBufferBitmap); FillRect(hdcSecondaryBuffer, &rcBuffer, (HBRUSH)GetStockObject(WHITE_BRUSH)); ReleaseDC(hwnd, hdc); } int KGrafixBuffer::CopyBufferToDisplay( HWND hwnd ) { HDC hdc = GetDC(hwnd); // get dc to current display-window // finally copy secondary-buffer to display BitBlt(hdc, 0, 0, rcBuffer.right, rcBuffer.bottom, hdcSecondaryBuffer, 0, 0, SRCCOPY); ReleaseDC(hwnd, hdc); return 0; } HDC KGrafixBuffer::GetSecondaryBuffer() { // return DeviceContext of secondary-buffer return hdcSecondaryBuffer; } KGrafixBuffer::~KGrafixBuffer() { DeleteDC(hdcSecondaryBuffer); }
-
Also ich finde das mit der Klasse zwar so nicht ganz optimal, aber wenn du sie nutzen willst musst du z.B. in WM_CREATE eine Instanz erzeugen. In WM_PAINT holst du dir dann mit GetSecondaryBuffer das Handle auf den Backbuffer-DC und zeichnest da hinein. Wenn du fertig bist kopierst du diesen dann mit CopyBufferToDisplay in dein Fenster

-
Ich bekomme es nicht hin

-
Wie verwendest du die Klasse denn jetzt? Bitte um Code

-
...noch garnicht!
Habe sie nur mal vorsichtshalber in den Code eingefügt! Ich muss sie ja auch nicht verwenden. Wenn du mir eine bessere Lösung für das Flimmern geben kannst, dann wäre ich dir tierisch dankbar! Die Aufgabe ist für ein Schulprojekt und nicht mal mein Lehrer hat was von doublebuffering gehört! Und ich habe da auch keinen Plan mit meinen paar Grundkenntnissen...Code: siehe oben...dass isser (sollte funzen)..aber flimmert!
Gruß AcidRay
-
Hö? Was ist daran so schwer? Dubblebuffering ist doch ganz einfach. Du hast das Bitmap halt im Speicher und blittest es bei Bedarf auf das Fenster. Das ist IMHO alles.
-
In dem obigen Code erzeugst du doch nirgends eine Instanz dieser Klasse (und nur mit dem Reinkopieren ist es nicht getan)

Falls du das noch nicht verstanden hast: das Prinzip von DoubleBuffering ist, dass du nicht direkt in dem DC deines Fensters zeichnest, sondern in deinen BackBuffer-DC (bekommst du bei dieser Klasse über GetSecondaryBuffer). Wenn du mit dem Zeichnen fertig bist kopierst du den BackBuffer-DC mit BitBlt auf den eigentlichen DC (das macht bei dieser Klasse dann CopyBufferToDisplay).Ansonsten benutze doch einfach mal die Forensuche - da sollte sich eigentlich einiges finden lassen

-
Also ich habe jetzt mal die Klasse weggelassen! Und es manuell versucht.
CreateCompatibleDC(hDC)
CreateCompatibleBitmap(hDC,1024,768)
Habe ich auch angelegt.
Das Prog zeichnet auch in den hcompdc...aber wie bekomme ich das dann in mein hDC - Fenster? Im Moment bleibt es weiss!
langsam verzweifle ich! Kannst du mir denn den Code(siehe unten) so verändern, dass es geht! Ich habe keine Ahnung, an welcher Stelle ich was blitten muss.
Wie das alles im Prinzip geht, habe ich verstanden! Aber ein komplettes funktionierendes Bsp. wäre cool(mein Code). Wenn das funktioniert, dann kapiere ich es auch, wo ich was machen muss....Danke
#include <stdio.h> #include <windows.h> #include <stdlib.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static int d, x,y, i, j, px, py; ///////////////////////WINMAIN///////////////////////////// /////////////////////////////////////////////////////////// int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow ) { /////////////////////Objekte//////////////////////////////// WNDCLASS wc; HWND hWnd; MSG Message; /////////////////////////////////////////////////////////// wc.style = 0; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.lpfnWndProc = (WNDPROC)WndProc; wc.hInstance = hInstance; wc.hIcon = 0; wc.hCursor = LoadCursor (0,IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = "Visualisierung"; /////////////////////////////////////////////////////////// RegisterClass (&wc); /////////////////////////////////////////////////////////// hWnd = CreateWindow("Visualisierung", "Visualisierung V1.0 Lagerverwaltung", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 1024, 768, 0,0, hInstance, 0); /////////////////////////////////////////////////////////// ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); while (GetMessage (&Message,NULL,0,0) ) { DispatchMessage (&Message); } return Message.wParam; }//ENDE WINMAIN ///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////WndProc///////////////////////////////////////////// LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int loop,loop2; switch (message) { case WM_CREATE: d=1; //d=Pixelschrittweite für Animation y=0; x=0; i=0; j=0; px=2;//Fachposition auf x py=5;//Fachposition auf y // Lokale Handles auf Windows Objekte static HDC hDC; static HDC hcompdc; static HBITMAP hcompbmp; static HDC hPen1, hPen2, hPen3, hOldPen; static PAINTSTRUCT ps; static RECT rect; GetClientRect(hWnd, &rect); SetTimer(hWnd, 1, 5, 0); // Periode in ms // Bereitstellen Zeichenstifte hPen1 = (HDC)CreatePen(PS_SOLID, 1, RGB(255,0,255));//Lagerbereichfensterstift hPen2 = (HDC)CreatePen(PS_SOLID, 1, RGB(155, 100,100)); hPen3 = (HDC)CreatePen(PS_SOLID, 3, RGB(255,51,153)); hOldPen = (HDC)SelectObject(hDC, hPen1); hcompdc = CreateCompatibleDC(hDC); hcompbmp = CreateCompatibleBitmap(hDC,1024,768); GetObject( hcompbmp, sizeof(BITMAP), 0); SelectObject(hcompdc, hcompbmp); SelectObject(hcompdc, hPen1); return 0; case WM_PAINT: hDC = BeginPaint(hWnd, &ps); // Rechteck: links, oben, rechts, unten Rectangle(hcompdc, 5, 5, 655, 700);//Lagerfensterbereichsgröße und Position (Hauptfenster) ///////////////// 5x5 Lagerplätze zeichnen for (loop=0;loop<=4;loop++) { for (loop2=0;loop2<=4;loop2++) { SelectObject(hcompdc, hcompbmp); SelectObject(hcompdc, hPen2); Rectangle(hcompdc, (10+loop*130),(10+loop2*110), (130+loop*130),(110+loop2*110)); } } ///////////////////////////////// SelectObject(hcompdc, hcompbmp); SelectObject(hcompdc, hPen3); //Wagen zeichnen Rectangle(hcompdc, 8+x, 8+y, 132+x, 112+y); //EndPaint(hWnd, &ps);//?????? BitBlt(hDC, 0, 0, 1024,768, hcompdc, 0, 0, SRCCOPY); //DeleteObject(hBitmap); //DeleteDC(hcompdc); return 0; //////////////////////////////////// case WM_TIMER: //Aktion, so lange der Timer läuft! if(i <= (px*130)) { x = i*d; i++; InvalidateRect(hWnd, &rect, 0); } //else // KillTimer(hWnd,1); if(j <= (py*110)) { y = j*d; j++; InvalidateRect(hWnd, &rect, 0); } //else //KillTimer(hWnd,1); return 0; case WM_DESTROY: // Alter Zustand wieder herstellen SelectObject(hDC, hOldPen); // Objekte löschen DeleteObject(hPen1); DeleteObject(hPen2); DeleteObject(hPen3); //ReleaseDC(hWnd, hcompdc); ReleaseDC(hWnd, hDC); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } ///////////////WndProc Ende//////////////////////////////////////////////////////////////
-
Ich habe mal versucht etwas Ordnung reinzubringen - ich hoffe, dass ich nichts übersehen habe:
LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HDC hDC, hcompdc; static HBITMAP hcompbmp; static RECT rcClient; static HPEN hPen1, hPen2, hPen3, hOldPen; int loop,loop2; switch (message) { case WM_CREATE: { d=1; //d=Pixelschrittweite für Animation y=0; x=0; i=0; j=0; px=2;//Fachposition auf x py=5;//Fachposition auf y // Bereitstellen Zeichenstifte hPen1 = CreatePen(PS_SOLID, 1, RGB(255,0,255));//Lagerbereichfensterstift hPen2 = CreatePen(PS_SOLID, 1, RGB(155, 100,100)); hPen3 = CreatePen(PS_SOLID, 3, RGB(255,51,153)); GetClientRect(hWnd, &rcClient); hDC = GetDC(hWnd); hcompdc = CreateCompatibleDC(hDC); hcompbmp = CreateCompatibleBitmap(hDC,rcClient.right - rcClient.left,rcClient.bottom - rcClient.top); SelectObject(hcompdc, hcompbmp); FillRect(hcompdc, &rcClient, (HBRUSH)GetStockObject(WHITE_BRUSH)); ReleaseDC(hWnd, hDC); SetTimer(hWnd, 1, 5, 0); // Periode in ms return 0; } case WM_PAINT: { PAINTSTRUCT ps; hDC = BeginPaint(hWnd, &ps); hOldPen = (HPEN)SelectObject(hcompdc, hPen1); // Rechteck: links, oben, rechts, unten Rectangle(hcompdc, 5, 5, 655, 700);//Lagerfensterbereichsgröße und Position (Hauptfenster) ///////////////// 5x5 Lagerplätze zeichnen for (loop=0;loop<=4;loop++) { for (loop2=0;loop2<=4;loop2++) { SelectObject(hcompdc, hPen2); Rectangle(hcompdc, (10+loop*130),(10+loop2*110), (130+loop*130),(110+loop2*110)); } } ///////////////////////////////// SelectObject(hcompdc, hPen3); //Wagen zeichnen Rectangle(hcompdc, 8+x, 8+y, 132+x, 112+y); SelectObject(hcompdc, hOldPen); BitBlt(hDC, 0, 0, rcClient.right - rcClient.left,rcClient.bottom - rcClient.top, hcompdc, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); return 0; } case WM_TIMER: //Aktion, so lange der Timer läuft! { if(i <= (px*130)) { x = i*d; i++; InvalidateRect(hWnd, &rcClient, 0); } //else // KillTimer(hWnd,1); if(j <= (py*110)) { y = j*d; j++; InvalidateRect(hWnd, &rcClient, 0); } //else //KillTimer(hWnd,1); return 0; } case WM_DESTROY: { // Objekte löschen DeleteObject(hPen1); DeleteObject(hPen2); DeleteObject(hPen3); DeleteDC(hcompdc); PostQuitMessage(0); return 0; } } return DefWindowProc(hWnd, message, wParam, lParam); }
-
Im Endeffekt musst du dann evtl. auch noch die Größenänderung des Fensters entsprechend bearbeitung und ggf. den Buffer in der Größe ändern

-
Vielen Danke für die Mühe @flenders!
Du bist mein Held!