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! 😃


Anmelden zum Antworten