Newsgroup: it.comp.programmare.win32
Titolo: InvalidateRect non mi forza subito il ridisegno

Ad es. al click di un pulsante ho scritto la seguente riga di codice:
mywnd.InvalidateRect(r,0);
dove mywnd è derivata dalla classe CStatic, r è un LPRECT cioè puntatore al
rettangolo di mywnd
Nel codice OnPaint della finestra di dialogo in cui è contenuto il controllo
CStatic mywnd ho inserito il mio codice di ridisegno.
La InvalidateRect dovrebbe invalidare il rettangolo r cioè forzare il suo
ridisegno e quindi inviare un messaggio WM_PAINT alla finestra di dialogo,
che a sua volta richiamerà la OnPaint. Giusto?
Perchè non viene ridisegnato subito (o dopo qualche millisecondo) il mio
rettangolo r, ma viene ridisegnato dopo che la finestra di dialogo è stata
coperta da un'altra finestra ?

 che a sua volta richiamerą la OnPaint. Giusto?
No. InvalidateRect() aggiorna soltanto la "regione invalidata", che e`
un oggetto associato a ogni DC che indica appunto quali aree del DC
dovranno essere ridisegnate al prossimo aggiornamento (non vorrei
sbagliare, ma mi sembra che esista pure una API per trovare l'attuale
regione invalidata di un DC e/o per "deinvalidarne" dei pezzi). Se vuoi
ridisegnare in modo sincrono, devi chiamare UpdateWindow() subito dopo.
---
Bye! Lorenzo Lutti
http://www.geocities.com/SiliconValley/Peaks/6258/

 che a sua volta richiamerą la OnPaint. Giusto?
Non esattamente: dopo InvalidateRect, dovrai chiamare anche UpdateWindow
se vuoi che il ridisegno avvenga subito.
Alex

 Alex
Ma con una finestra derivata dalla classe CStatic il ridisegno non avviente
subito nemmeno se dopo chiamo la UpdateWindow!!! Come mai?

 wrote in message news:8kqf66$khq$1...@nslave2.tin.it...

A chi stai mandando l'InvalidateRect e l'UpdateWindow, al controllo
o al dialogo che lo contiene?  Sono finestre separate, e di solito
il controllo copre una parte del dialogo.  L'approccio "canonico" e`
di usare come controllo (su cui si vuole disegnare da parte della
classe-dialogo) un button con stile BS_OWNERDRAW, e gestire il
WM_DRAWITEM nel genitore.  A questo punto, con InvalidateRect
*al controllo* (di solito per l'intera sua finestra) dovresti essere
a posto (normalmente anche senza UpdateWindow, al massimo puoi
aggiungere anch'essa).  Ci sono anche delle considerazioni sul
clipping (di figli e/o fratelli), ma se usi il button owner-draw
non hai bisogno alcuno di preoccupartene.
Trovi un esempio come parte del mio tutorial 
http://aleax.supereva.it
,
nei capitoli in cui sviluppo un programmino di grafico di una
funzione; sono API nude, non MFC, ma non cambia poi molto.
Alex

 non hai bisogno alcuno di preoccupartene.
L'InvalidateRect lo mando al controllo picture di tipo frame (che non è
altro che una finestra CStatic contenuta della mia finestra di dialogo.
Stranamente se uso un frame non funziona non viene invalidato, mentre se uso
un bottone si. Come mai? Forse perchè CStatic non è in grado di inviare
WM_DRAW alla finestra di dialogo, mentre un bottone si?

>CStatic mywnd ho inserito il mio codice di ridisegno.
L'OnPaint del *dialogo* (contenitore, parent) non verra` chiaramente
mai sollecitato dal fatto che lo *static* (controllo, child) si sta in un
qualche modo ridisegnando.  Se a tutti i costi vuoi farlo con lo static
invece che con il button (e onestamente non capisco perche`!) lo
dovrai subclassare e gestirti tu tutti i casi particolari che possono
sorgere.
Alex

 non hai bisogno alcuno di preoccupartene.
Ok, ho capito la differenza fra un controllo static e owner-draw, ho capito
anche l'uso della InvalidateRect, e del messaggio WM_DRAWITEM.
Sono riuscito a far ridisegnare il bottone mediante la InvalidateRect e il
gestore del messaggio WM_DRAWITEM posto nella classe della finestra di
dialogo (mi funziona tutto se faccio un'applicazione di tipo dialog).
Però in un contesto Doc/View non mi funziona, cioè non so dove mettere il
gestore del WM_DRAWITEM. Il controllo button si trova in una dialogbar
dockabile alla finestra del frame. Ho provato a mettere il gestore del
messaggio nella vista, ma non funziona cioè sembra che non viene eseguito il
gestore del messaggio (ovviamente perchè il button non si trova nella vista,
ma nella dialogbar); ho provato a crearmi una classe a parte, per la
finestra di dialogbar e mettere li un gestore di WM_DRAWITEM, ma non mi
funziona nemmeno qui.
Ho provato anche il seguente esperimento: ho inserito nel frame un gestore
di messaggio WM_DRAWITEM e dalla classe di vista ho invalidato il rettangolo
del button, ma il frame non mi ha risposto...cioè non ha eseguito il codice
contenuto nel gestore di messaggio.
Inoltre ho notato che se inserisco un bottone nella dialogbar esso risulta
disabilitato, cioè non cliccabile, nonostante lo stile sia abilitato. E'
forse per questo che non invia messaggi alla finestra genitore?
Alex mi puoi dare una dritta? Grazie.

 forse per questo che non invia messaggi alla finestra genitore?
No, i bottoni owner-draw sono molto spesso disabled (usati per puro
disegno) ma il WM_DRAWITEM lo spediscono lo stesso.  (MFC di
solito disabilita il bottone se nessuno gestisce il suo specifico
WM_COMMAND; in certi casi, OnUpdateCommandUI e` invece
la chiave della questione, anche se non so se questo sia uno
di quei casi).
Alex

Mi trovo un po' in difficoltà a gestire la dialogbar in MFC Doc/View: nella
classe frame ho il membro CDialogBar m_wndMyDialogBar (aggiunto dal Wizard
del VC++). Il Wizard però non aggiungiunge altro, oltre al codice necessario
per visualizzarla. Quindi mi chiedo come va gestita? Si gestisce dalla
classe frame, dalla classe view, dalla classe document oppure da una nuova
classe associata alla finestra della dialogbar?
Nell'editor delle risorse vi è la finestra associata alla dialogbar, in cui
è possibile inserire controlli in modo visuale. Però quando si tenta di
inserire un evento (o meglio gestore di messaggio) ad un dato controllo
nella dialogbar, appare un messaggio che dice che la risorsa-finestra non è
associata a nessuna classe e chiede se si vuole creare una nuova classe
oppure selezionarne una esistente. Mi verrebbe spontaneo selezionare la
classe frame dato che contiene il membro m_wndMyDialogBar.
Dalla documentazione MS:
Dialog bar, which is a control bar whose layout is defined by a dialog
resource template. As with any control bar, notifications from controls in
the dialog bar are routed to the owner of the dialog bar, namely the main
frame window. For example, CMainFrame::OnSelChangePalette is the handler for
the CBN_SELCHANGE notification from the combo box control in a dialog bar.
Quindi la cosa migliore forse è quello di avere una classe per la dialogbar
a cui però non è associata nessuna finestra, ma è una semplice classe C++
(che contiene eventuali operazioni da fare sulla dialogbar) e gli eventi
relativi ai controlli contenuti nella dialogbar vanno messi nella classe
frame. In effetti se gli eventi dei controlli contenuti nella dialogbar non
si mettono nella classe frame, essi vengono come "ignorari".
Il problema è che non riesco a gestire l'evento WM_DRAWITEM di un controllo
owner-draw posto nella dialog. Cioè se metto un gestore di WM_DRAWITEM nella
classe frame, esso viene "ignorato". Temo che in un contesto MFC Doc/View il
mgs WM_DRAWITEM vada gestito in maniera differente, rispetto ad
un'applicazione in stile dialog. Come? Forse la InvalidateRect di un
rettangolo di un controllo onwer-draw posto nella dialogbar non ha effetto?
Sulla documentazione VC++ c'è un esempio che mostra l'uso della dialog bar e
soprattutto l'uso dei gestori dei messaggi dei controlli della dialogbar
(dove si vede chiaramente che vengono messi nella classe frame) purtroppo
però NON vi è alcun esempio di WM_DRAWITEM di un controllo owner-draw posto
nella dialogbar. Alex puoi aiutarmi? Grazie.

 rettangolo di un controllo onwer-draw posto nella dialogbar non ha
effetto?
Ma no!  Cosi` come non usi CDialog nuda ma ne derivi una tua classe, con
la sua message map ecc ecc, cosi` lo stesso dovrai fare da CDialogBar se
vuoi fare cose sofisticate.
Alex