Seite 1 von 1

Flackern bei Größenänderung des Fensters

Verfasst: 25.02.2007 16:25
von hardy
Ich erstelle mit den Winapi-Funktionen ein Fenster und fülle dieses mit einer einfachen Grafik aus. Während der Größenänderung passt sich die Grafik ständig der neuen Größe an. Dabei flackert es sehr deutlich. Kann man dieses Flackern eigentlich verhindern ?

Code: Alles auswählen

;***************************************************************
;*   WinAPI: Fenster erstellen und darin mit GDI zeichnen      *
;* =========================================================== *
;*   - Ausgabe von farbigen Rechteck, Ellipse, Linien          *
;*   - veraendert sich Fenstergroesse, wird Grafik angepasst   *
;***************************************************************   

;- Grundlage ist Beispiel aus "Einfache Windowsprogrammierung" von www.red-inferno.de


Global rc.RECT, hwnd    

Procedure WndProc(wnd,Message,wParam,lParam) 
returnval=0

Select Message 

  Case #WM_PAINT

;   ----------   bestimmen der koordinaten (groesse clientarea)  ----------    
    GetClientRect_(hwnd,rc)   
    
;   ----------   roten und gruenen pinsel definieren (fuellfarbe)   ----------
    hRedBrush = CreateSolidBrush_(RGB(255, 0, 0))   ;oder
    hgreenbrush = CreateSolidBrush_(RGB(0, 255, 0))
    
;   ----------   roten stift definieren   ----------  
    hRedPen = CreatePen_(PS_SOLID, 30, RGB(255, 0, 0));

     *DC=BeginPaint_(hwnd,ps.paintstruct) 
    
;   ----------   roten pinsel im DC eintragen und rechteck zeichnen   ----------
    SelectObject_(*DC, hRedBrush)    
    Rectangle_(*DC, rc\left, rc\top, rc\right, rc\bottom)    
    
;   ----------   gruenen pinsel im DC eintragen und ellipse zeichnen   ----------    
    SelectObject_(*DC, hgreenbrush)
    Ellipse_(*DC, rc\left+20, rc\top+20, rc\right-20, rc\bottom-20);
    
;   ----------   rote linien zeichnen   ----------
    SelectObject_(*DC,hredbrush)
    SelectObject_(*DC,hredpen)
    MoveToEx_(*DC,rc\left,rc\top,#Null)
    LineTo_(*DC,rc\right,rc\bottom)    
    MoveToEx_(*DC,rc\right,rc\top,#Null)
    LineTo_(*DC,rc\left,rc\bottom)

    EndPaint_(hwnd,@ps) 
  
  Case #WM_ERASEBKGND
    returnval=1
    
  Case #WM_CLOSE  
    DestroyWindow_(hWnd);

  Case #WM_DESTROY:
    PostQuitMessage_(0) 

  Default
    Returnval = DefWindowProc_(wnd, Message, wParam, lParam) 

EndSelect 

ProcedureReturn returnval
EndProcedure 

cn$="myclass"   ;(c)lass(n)ame 

wc.WNDCLASS 
wc\cbClsExtra = 0 
wc\cbWndExtra = 0 
wc\hbrBackground = #COLOR_BACKGROUND 
wc\hInstance = hInstance 
wc\hIcon = LoadIcon_(0,#IDI_APPLICATION) 
wc\hCursor = LoadCursor_(0, #IDC_CROSS) 
wc\lpszMenuName = 0 
wc\lpszClassName = @cn$ 
wc\lpfnWndProc = @WndProc() 
wc\style = #CS_HREDRAW | #CS_VREDRAW 

RegisterClass_(wc)
hwnd = CreateWindowEx_(0,cn$,"Zeichnen mit dem GDI",#WS_OVERLAPPEDWINDOW,150,350,600,350,0,0,hInstance,0) 

ShowWindow_(hwnd,  #SW_SHOWNORMAL) 
UpdateWindow_(hwnd)

While GetMessage_(msg.MSG, #Null, 0, 0 ) 
  TranslateMessage_(msg) 
  DispatchMessage_(msg) 
Wend

End
Hardy

Verfasst: 25.02.2007 17:06
von Fluid Byte

Code: Alles auswählen

Procedure WindowProc(hWnd.l,uMsg.l,wParam.l,lParam.l)
	Select uMsg
		Case #WM_PAINT 
		GetClientRect_(hwnd,rc.RECT)   

		hbrRed = CreateSolidBrush_(#Red)
		hbrGreen = CreateSolidBrush_(#Green)
		hPenRed = CreatePen_(#PS_SOLID,30,#Red)
				
		hdc = BeginPaint_(hwnd,ps.PAINTSTRUCT)
		
		hbmOutput = CreateCompatibleBitmap_(hdc,rc\right,rc\bottom)
		
		hdcMem = CreateCompatibleDC_(hdc)
		SelectObject_(hdcMem,hbmOutput)
		
		SelectObject_(hdcMem,hbrRed)   
		Rectangle_(hdcMem,rc\left,rc\top,rc\right,rc\bottom)   
		 
		SelectObject_(hdcMem,hbrGreen)
		Ellipse_(hdcMem,rc\left + 20,rc\top + 20,rc\right - 20,rc\bottom - 20)
		
		SelectObject_(hdcMem,hbrRed)
		SelectObject_(hdcMem,hPenRed)
		MoveToEx_(hdcMem,rc\left,rc\top,#Null)
		LineTo_(hdcMem,rc\right,rc\bottom)   
		MoveToEx_(hdcMem,rc\right,rc\top,#Null)
		LineTo_(hdcMem,rc\left,rc\bottom)
				
		BitBlt_(hdc,0,0,rc\right,rc\bottom,hdcMem,0,0,#SRCCOPY)
		DeleteDC_(hdcMem)					
		
		DeleteObject_(hbmOutput)
		
		EndPaint_(hwnd,@ps)
		
		DeleteObject_(hbrRed)
		DeleteObject_(hbrGreen)
		DeleteObject_(hPenRed)
		
		Case #WM_SIZE
		InvalidateRect_(hwnd,0,0)
		
		Case #WM_ERASEBKGND
		ProcedureReturn #True
		
		Case #WM_CLOSE 
		DestroyWindow_(hWnd)

		Case #WM_DESTROY
		PostQuitMessage_(0)
	EndSelect

	ProcedureReturn DefWindowProc_(hWnd,uMsg,wParam,lParam)
EndProcedure

wc.WNDCLASS
wc\hbrBackground = #COLOR_BACKGROUND
wc\hIcon = LoadIcon_(0,#IDI_APPLICATION)
wc\hCursor = LoadCursor_(0, #IDC_CROSS)
wc\lpszClassName = @"myclass"
wc\lpfnWndProc = @WindowProc()

RegisterClass_(wc)

hwnd = CreateWindowEx_(0,"myclass","Zeichnen mit dem GDI",#WS_OVERLAPPEDWINDOW | #WS_VISIBLE,150,350,600,350,0,0,0,0)

While GetMessage_(lpMsg.MSG,0,0,0)
	TranslateMessage_(lpMsg)
	DispatchMessage_(lpMsg)
Wend

Verfasst: 25.02.2007 19:31
von AND51
> Kann man dieses Flackern eigentlich verhindern ?
Schau dir mal den Befehl SmartWindowRefresh() an. Den Tipp gebe ich dir mal so, ohne diesen ganzen Thread gelesen zu haben.

Verfasst: 25.02.2007 19:45
von Fluid Byte
Den Tipp gebe ich dir mal so, ohne diesen ganzen Thread gelesen zu haben.
Was nicht sehr clever ist da er keine in PB erstellten Fenster benutzt. Bild

Verfasst: 25.02.2007 21:44
von Ligatur
@hardy
Wie beim Code von Fluid Byte zu sehen muß jeder Pinsel und jeder Brush nach Benutzung wieder gelöscht werden, nachdem die alten Pens/Brushes wieder selektiert wurden, die man beim ersten selektieren eines Pens/Brushes als Rückgabewert erhält (Oder beim erstellen eines Gerätekontexts nachdem dieser wieder gelöscht wurde).

Bei deinem Code würde das dann so aussehen:

Code: Alles auswählen

  Case #WM_PAINT 

;   ----------   bestimmen der koordinaten (groesse clientarea)  ----------    
    GetClientRect_(hwnd,rc)    
    
;   ----------   roten und gruenen pinsel definieren (fuellfarbe)   ---------- 
    hRedBrush = CreateSolidBrush_(RGB(255, 0, 0))   ;oder 
    hgreenbrush = CreateSolidBrush_(RGB(0, 255, 0)) 
    
;   ----------   roten stift definieren   ----------  
    hRedPen = CreatePen_(PS_SOLID, 30, RGB(255, 0, 0)); 

     *DC=BeginPaint_(hwnd,ps.paintstruct) 
    
;   ----------   roten pinsel im DC eintragen und rechteck zeichnen   ---------- 
    ABrush = SelectObject_(*DC, hRedBrush)    ; <---- Erstes selektieren eines Brushes
    Rectangle_(*DC, rc\left, rc\top, rc\right, rc\bottom)    
    
;   ----------   gruenen pinsel im DC eintragen und ellipse zeichnen   ----------    
    SelectObject_(*DC, hgreenbrush) 
    Ellipse_(*DC, rc\left+20, rc\top+20, rc\right-20, rc\bottom-20); 
    
;   ----------   rote linien zeichnen   ---------- 
    SelectObject_(*DC,hredbrush) 
    APen = SelectObject_(*DC,hredpen)    ;<--------- erstes Benutzen eines Pens
    MoveToEx_(*DC,rc\left,rc\top,#Null) 
    LineTo_(*DC,rc\right,rc\bottom)    
    MoveToEx_(*DC,rc\right,rc\top,#Null) 
    LineTo_(*DC,rc\left,rc\bottom)
    ; Alten Brush / Pen wieder selektieren
    SelectObject_(*DC, ABrush)
    SelectObject_(*DC, APen)

    EndPaint_(hwnd,@ps) 
    ; Neue Brushes /Pen löschen
    DeleteObject_(hRedBrush)
    DeleteObject_(hgreenbrush)
    DeleteObject_(hRedPen)