Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    502

    [C++] Disegno di linee e flickering

    Buongiorno,
    ho un'applicazione win32 in c++ (non uso MFC) che deve fare il grafico in tempo reale, il più possibile, di dati che arrivano tramite la porta seriale (è un numero e ne arrivano molti, tra i 2000 e i 5000 per grafico).
    Ho implementato la tecnica del double buffering, disegnando prima su un'immagine e poi disegnando quest'ultima sullo schermo, ma il flickering è sempre presente.
    Mi sapete dire che tecniche usare?
    Parte del flickering nasce dal fatto che quando ridisegno, parto dagli assi cartesiani che fanno da "sfondo" al grafico; in pratica ridisegno tutto.
    Se conoscessi un qualcosa simile al glass pane del Java potrei disegnare i dati su una tale finestra e mettere sullo sfondo la parte "statica" del grafico.

    Grazie in anticipo.

    VC++ esxpress 2008 su WinXP pro SP3

  2. #2
    Se stai utilizzando la tecnica del double buffering non dovresti avere problemi dipendenti da cosa disegni prima e cosa disegni poi, visto che il disegno viene effettuato prima completamente nel buffer, e poi copiato integralmente nella finestra. Sei sicuro di aver implementato correttamente questa tecnica?
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    502
    Originariamente inviato da MItaly
    ...
    Sei sicuro di aver implementato correttamente questa tecnica?
    No non ne sono sicuro.

    Metto il codice relativo all'evento WM_PAINT, sperando sia sufficiente.

    codice:
    case WM_PAINT:
    	// Se ridimensiono o sposto la finestra non disegno
    	if(bRidimensionamento)
    		return 0;
    	// Se non voglio il grafico
    	if(!bDisegna)
    		return 0;
    	// Calcolo il rettangolo dove disegnare
    	// rBordi è un RECT
    	// rD è il rettangolo GetClientRect
    	bGenerico=calcolaRettangolo(hWnd,&rD,rBordi);
    	hdc = BeginPaint(hWnd, &ps);
    	// Creo un DC compatibile per la bitmap
    	// e creo la bitmap per il double buffering
    	hMemDC=::CreateCompatibleDC(hdc);
    	if(hMemDC!=NULL)
    	{
    		hMemBit=::CreateCompatibleBitmap(hdc,rD.right-rD.left,rD.bottom-rD.top);
    		if(hMemBit!=NULL)
    		{
    			hOldBit=(HBITMAP)::SelectObject(hMemDC,hMemBit);
    			// Se utilizzo la bitmap il punto in alto a destra è (0,0)
    			// Se non utilizzo la bitmap devo inserire i dati di rBordi
    			::Rectangle(hMemDC,0,0,rD.right-rD.left,rD.bottom-rD.top);
    			/*
    			disegnaPianoCartesiano(hMemDC,rD,10,10);
    			disegnaLinee(hMemDC,rD,valori,coloriLinee);
    			*/
    			// Disegno i dati man mano che arrivano
    			disegnaLinea(hMemDC,rD,valoriLog,coloriLinee);
    			// Copio la bitmap su schermo usando rBordi per il posizionamento voluto
    			BitBlt(hdc, rBordi.left,rBordi.top, rD.right - rD.left, rD.bottom - rD.top, hMemDC, 0, 0, SRCCOPY);
    			// Riseleziono la precedente bitmap e elimino la bitmap temporanea
    			SelectObject(hMemDC, hOldBit);
    			DeleteObject(hMemBit);
    		}
    		DeleteDC(hMemDC); // Libero il DC temporaneo
    	}
    	EndPaint(hWnd, &ps);
    	break;
    La funzione disegnaLinea si occupa di disegnare i valori del vector<double> valoriLog.
    Nei miei intendimenti e per quel poco che so del double buffering, dovrebbe essere corretta come implementazione.

  4. #4
    Anche a me pare corretta... descrivi esattamente in che termini e in che occasioni si verifica il flickering, forse non si tratta di flickering ma di qualcos'altro.
    Ah, dimenticavo, puoi rendere un pelo più efficiente la routine effettuando il BitBlt solo dell'area da ridisegnare (eventualmente disegnando solo quella anche nella bitmap, ma qui è più la fatica che il guadagno), impiegando i dati che ti fornisce BeginPaint.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    502
    Intendi quel RECT rcPaint che c'è in PAINTSTRUCT? Ci do un'occhiata su come usarlo.

    Il flickering mi si presenta poiché ogni volta che arriva un dato sulla seriale io lo aggiungo al mio vettore e poi ridisegno il grafico.
    C'è un timer che si occupa di andare a leggere ogni tot millisecondi e invalidare la finestra.
    Ora, non so perché e per come, ma lavorando a finestra non massimizzata ho visto che mi si ridisegnava tutto, ossia anche le altre finestre, il desktop ecc ecc.
    Ho provato a salvare in una variabile globale il puntatore alla mia finestra e a usare quello nella funzione InvalidateRect e adesso il flickering sembra molto ridotto.
    Era come se mi si invalidasse tutto lo schermo (sempre se sia possibile).

    Si nota ancora una parte del rettangolo che uso come piano cartesiano che resta bianco e poi compaiono le linee dei grafici, non so spiegarti cosa succede a parole. E' più una cosa visiva. Invece di avere un grafico che va via fluido, si vedono come dei tiangoli che "flashano" e poi compare il grafico.
    Adesso faccio ancora qualche esperimento e poi ricreo un progetto nuovo perché a forza di modifiche e quant'altro sono più le linee di codice da cancellare di quelle necessarie.

  6. #6
    Originariamente inviato da Rubox
    Ora, non so perché e per come, ma lavorando a finestra non massimizzata ho visto che mi si ridisegnava tutto, ossia anche le altre finestre, il desktop ecc ecc.
    MAI chiamare InvalidateRect passando NULL, se non ne hai una buona ragione.
    Ho provato a salvare in una variabile globale il puntatore alla mia finestra e a usare quello nella funzione InvalidateRect e adesso il flickering sembra molto ridotto.
    Era come se mi si invalidasse tutto lo schermo (sempre se sia possibile).
    È possibilissimo, basta chiamare InvalidateRect passando NULL come primo parametro.
    Si nota ancora una parte del rettangolo che uso come piano cartesiano che resta bianco e poi compaiono le linee dei grafici, non so spiegarti cosa succede a parole. E' più una cosa visiva. Invece di avere un grafico che va via fluido, si vedono come dei tiangoli che "flashano" e poi compare il grafico.
    Probabilmente stai passando a InvalidateRect TRUE come terzo parametro, il che causa il ridisegno dello sfondo della finestra tramite un messaggio WM_ERASEBKGND, che nel tuo caso probabilmente viene gestito da DefWindowProc, la quale provvederà a ridisegnare lo sfondo (probabilmente riempiendo la finestra di bianco). Viene inviato solo dopo il WM_PAINT.
    La soluzione sta nel chiamare InvalidateRect passando l'handle alla tua finestra, NULL come area da invalidare e FALSE al terzo parametro.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    502
    A InvalidateRect passavo come primo parametro l'handle della finestra, come secondo NULL e come terzo TRUE.
    Faccio un po' di prove :-)

  8. #8
    Basta cambiare il terzo parametro a FALSE, allora.
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Utente di HTML.it
    Registrato dal
    Feb 2009
    Messaggi
    502
    Originariamente inviato da MItaly
    Basta cambiare il terzo parametro a FALSE, allora.
    Grazie

    Ho salvato l'handle della finestra in una variabile globale (mi avevano detto che era meglio usarne poche... ma tantè, punti di vista immagino).
    In una variabile RECT tengo traccia del rettangolo che utilizzo per il grafico.
    E con il terzo parametro a FALSE della InvalidateRect non ho più flickering.

  10. #10
    Originariamente inviato da Rubox
    Grazie
    Di niente, figurati.
    Ho salvato l'handle della finestra in una variabile globale (mi avevano detto che era meglio usarne poche... ma tantè, punti di vista immagino).
    In effetti sarebbe meglio evitare... la procedura che chiama InvalidateRect è richiamata dal gestore di un messaggio della stessa finestra? In quel caso puoi usare l'hWnd fornito dalla window procedure.
    In una variabile RECT tengo traccia del rettangolo che utilizzo per il grafico.
    E con il terzo parametro a FALSE della InvalidateRect non ho più flickering.
    Ben fatto; ciao!
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.