Newsgroup: it.comp.programmare.win32
Titolo: [VC++ 6.0] Finestre e WM_PAINT

Programmo sotto Win98 SE con VC++ 6.0.
Ho fatto una finestra nella quale vado a disegnare dei rettangoli che voglio
creare trascinando il mouse.
Ho intercettato il messaggio WM_MOUSEMOVE mandato alla finestra e se il
tasto SX del mouse č premuto vado a disegnare il rettangolo, in questo modo:
case WM_MOUSEMOVE:
  {
   INT xPos,yPos;
   HPEN hpen,holdPen;
   HANDLE hdc;
   PAINTSTRUCT ps;
   RECT imgRect;
   xPos = GET_X_LPARAM(lParam);
   yPos = GET_Y_LPARAM(lParam);
   if (xPos>=50 && yPos>=50 && xPos<50+(VIDEO_SOURCE_WIDTH)-NCCF_QUAD &&
        yPos<50+(VIDEO_SOURCE_HEIGHT)-NCCF_QUAD)
   {
    if (premuto)          // Se il tasto SX del mouse č premuto...
    {
     xPos=((xPos-50)/NCCF_QUAD+1)*NCCF_QUAD+50;
     yPos=((yPos-50)/NCCF_QUAD+1)*NCCF_QUAD+50;
     SetRect(&imgRect,0,20,650,350);
     InvalidateRect(hwnd,&imgRect,FALSE) ;
     hdc = BeginPaint(hwnd,&ps);
       hpen = CreatePen(PS_SOLID, 1, 0x000000);      // Cancello il quadrato
di prima
       holdPen = (HPEN)SelectObject(hdc, hpen);
       if (quadrato[0].x!=0)
       Polyline(hdc,quadrato,5);
     quadrato[1].x=xPos;                                //  Disegno il nuovo
quadrato
     quadrato[1].y=quadrato[0].y;
     quadrato[2].x=xPos;
     quadrato[2].y=yPos;
     quadrato[3].x=quadrato[0].x;
     quadrato[3].y=yPos;
     quadrato[4]=quadrato[0];
     hpen = CreatePen(PS_SOLID, 1, 0xb0b0b0);
     holdPen = (HPEN)SelectObject(hdc, hpen);
     Polyline(hdc,quadrato,5);
       EndPaint(hdc,&ps);
       }
   }
  }
  break;
Dopo alcuni minuti di lavoro il programma o si pianta o incomincia a
disegnarmi tutto in nero.
Ho provato anche a richiamare la WM_PAINT con una SendMessage, ma il
risultato non cambia.
Per ultimo ho provato a fare un ciclo di 1000 SendMessage alla pressione di
un tasto, la stessa cosa.
Pensando che le varie WM_PAINT si annidassero ho provato a mettere un
semaforo prima della chiamata di SendMessage-WM_PAINT, ma nulla!!
Sapete darmi consigli?

Ciao, Diego!
Il giorno 14/11/2003 alle ore 10:28 hai scritto:
 D>      hdc = BeginPaint(hwnd,&ps);
[...]
 D>        EndPaint(hdc,&ps);
 D> Dopo alcuni minuti di lavoro il programma o si pianta o incomincia a
 D> disegnarmi tutto in nero.
Pazzo !!! BeginPaint/EndPaint si usano *solo* in risposta al messaggio
WM_PAINT, se vuoi l'hdc della finestra usa GetWindowDC.
Bye


Hai ragione, grazie per evermi corretto.
Però come ho già scritto prima ho lo stesso problema se uso la SendMessage
come ho scritto sotto, e ti assicuro che così non ho altre
BeginPaint/EndPaint se non all'interno del case WM_PAINT:
Hai mai provato a fare un ciclo stretto di questo tipo?:
for (i=0;i<1000;i++)
{
    if (WaitForSingleObject(hFlagPaint,0)==WAIT_OBJECT_0)    // L'ho messo
per evitare chiamate annidate
    {
       SendMessage(hwnd,WM_PAINT,0,0);
       ReleaseMutex(hFlagPaint);
    }
}
case WM_MOUSEMOVE:
  {
   INT xPos,yPos;
   xPos = GET_X_LPARAM(lParam);
   yPos = GET_Y_LPARAM(lParam);
   if (xPos>=50 && yPos>=50 && xPos<50+(VIDEO_SOURCE_WIDTH)-NCCF_QUAD &&
        yPos<50+(VIDEO_SOURCE_HEIGHT)-NCCF_QUAD)
   {
    if (premuto)          // Se il tasto SX del mouse è premuto...
    {
     xPos=((xPos-50)/NCCF_QUAD+1)*NCCF_QUAD+50;
     yPos=((yPos-50)/NCCF_QUAD+1)*NCCF_QUAD+50;
     quadrato[1].x=xPos;
     quadrato[1].y=quadrato[0].y;
     quadrato[2].x=xPos;
     quadrato[2].y=yPos;
     quadrato[3].x=quadrato[0].x;
     quadrato[3].y=yPos;
     quadrato[4]=quadrato[0];
     SendMessage(hwnd,WM_PAINT,0,0);
       }
   }
  }
  break;
Grazie e, sai mica dirmi se su internet si possano trovare info su queste
cose? Se si dove?
BYE.

Ciao, Diego!
Il giorno 14/11/2003 alle ore 11:39 hai scritto:
 D> Però come ho già scritto prima ho lo stesso problema se uso la
 D> SendMessage come ho scritto sotto, e ti assicuro che così non ho altre
 D> BeginPaint/EndPaint se non all'interno del case WM_PAINT:
 D> Hai mai provato a fare un ciclo stretto di questo tipo?:
WM_PAINT non lo puoi chiamare con SendMessage e' un messaggio gestito dal
sistema in automatico o tramite InvalidateRect e funzioni collegate.
 D> Grazie e, sai mica dirmi se su internet si possano trovare info su
 D> queste cose? Se si dove?
msdn.microsoft.com
Bye

 risultato non cambia.
No. In WM_PAINT devi inserire il disegno "normale" del rettangolo, qui devi
cancellare il vecchio e ridisegnare il nuovo al volo e senza chiamare la
WM_PAINT, altrimenti diventa una cosa assurda (e poi le WM_PAINT non vengono
eseguite correttamente perché arriva comunque una sfilza di WM_MOUSEMOVE).
Sostituisci BeginPaint e EndPaint con GetDc e ReleaseDc.
-- 
/* Costantino Grana                                */
main(int c,char**o){char*s=c?"+L7?+;:7?+:OKIK+9?;9=;"
":+9?;:<:;+9?;;;:;+9<:;<::;+RLJ;K9+":1[o],t,a=!c,m;do
for (m=*s-'0',t=a?m/c:m%c;m>>7?c=1<<m+8,!a&&puts(&a)*
*&a:t--;printf("  \0/*"+a));while ((a^=3)||a[++s]);;}
/* Original code due to Chris Brown... impressive! */

 Sostituisci BeginPaint e EndPaint con GetDc e ReleaseDc.
Ho fatto come mi hai detto: ho usato GetWindowsDC e ReleaseDC e le
SelectObject e DeleteObject ma il risultato non cambia.
Ho poi tolto anche la InvalidateRect(hwnd,&imgRect,FALSE) ; che se non ho
letto male dovrebbe richiamare WM_PAINT, ma nulla.
Provando e riprovando ho notato che per far disegnare tutte le linee nere mi
basta muovere velocemente il mouse, cercando di creare un rettangolo, per
alcuni seconti.
Quindi direi che il problema sta in qualcosa che faccio quando ricevo
WM_MOUSEMOVE, forse.
Grazie lo stesso comnque.

Grazie a tutti che mi avete prima messo sulla buona strada e quindi risolto
il problema.
Ho ancora fatto un piccolo sbaglio quando andavo a fare la
Mi spieghi perchè non basta fare:
hpen = CreatePen(PS_SOLID, 1, 0x000000);
holdPen = (HPEN)SelectObject(hdc, hpen);
....
DeleteObject(holdPen);
Come facevo subito pensando che la DeletObject fosse legata alla
SelectObject.
Ma bisogna fare:
hpen = CreatePen(PS_SOLID, 1, 0x000000);
holdPen = (HPEN)SelectObject(hdc, hpen);
....
SelectObject(hdc,holdPen);
DeleteObject(hpen);
?????
Grazie ancora.

Ciao, Diego!
Il giorno 14/11/2003 alle ore 14:57 hai scritto:
 D> Mi spieghi perchč non basta fare:
Perche' SelectObject seleziona l'oggetto nel hdc specificato e ritorna
l'handle dell'oggetto che era precedentemente selezionato (holdPen != hpen),
poiche' non puoi cancellare gli oggetti in uso devi di nuovo selezionare
l'oggetto precedente per liberare quello che vuoi cancellare.
Consiglierei una scorsa alla documentazione...
Bye