Newsgroup: it.comp.programmare.win32
Titolo: Autoredraw di una finestra

Ho una ControlBar che contiente un controllo picture in cui ci disegno
sopra.
E' possibile impostare una proprietà del controllo picture in modo che sia
automaticamente ridisegnato oppure è necessario inserire il codice di
disegno nella appropriata funzione OnDraw (o simili) ?
Il problema è che la OnDraw si riferisce alla vista, mentre io vorrei
ridisegnare una finestra figlia della vista cioè il mio controllo picture
che sta dentro ad una controlbar.
So che esiste anche la funzione Invalidate che consente di invalidare una
finestra ossia dire che il suo contenuto grafico non è più valido e quindi
costringerla a ridisegnarsi.
Vorrei sapere qual è il modo giusto di procedere sfruttando al massimo
l'architettura DOC/VIEW fornità dal VC++ che è ad un livello di astrazione
un po' più alto rispetto alle API e al "sistema dei messaggi" di Windows.

 ha scritto nel messaggio
news:8jsvcq$bdl$1...@nslave1.tin.it...


 Alex mi puoi aiutare? Grazie.
Solo se spieghi meglio cos'e` il "controllo picture" che nomini (non
esiste un tale controllo in MFC, che sembra tu stia usando senza mai
nominarlo poiche` parli di "architettura doc/view fornita dal VC++";
esiste un CPictureHolder ma non credo sia quello che usi...?), come
fa ad essere "finestra figlia della vista" se invece "sta dentro a
una controlbar", ecc ecc.  Insomma, ho visto nel tuo post una tale
confusione di concetti e terminologia che ho pensato bene di saltarlo
piuttosto che spendere la notevole quantita` di sforzo necessario a
farmi chiarire esattamente cosa stai facendo/cercando di fare.
Sarebbe bello se le domande fossero poste in termini precisi e nella
terminologia giusta, in particolare chiarendo il framework usato
(VC++ non ha solo l'antico MFC, ma vari altri framework), usando i
nomi giusti per i controlli, le classi, i metodi, ecc, ecc.
Alex

Ho creato un'applicazione col VC++ di tipo MFC in particolare DOC/VIEW.
Nell'editor delle risorse appare una finestra simile a quella di VB in cui
ci sono i controlli standard (static text, button, combo box, ecc.); io ho
inserito all'interno di una finestra dialogbar quello che viene chiamato
picture control (può essere specificato il tipo che si vuole Frame,
Rectangle, Icon, Bitmap: io ho impostato il tipo frame, che corrisponde in
pratica ad una casella col bordo in bassorilievo in cui poter disegnarci
sopra; NON è un controllo OCX!) di default gli viene assegnato
l'identificatore IDC_STATIC (che ho rinominato in IDC_IMMAGINE).
Nella mia applicazione ho la necessità di disegnare dentro il controllo
picture, però i disegni sono transitori, nel senso che se ad esempio
un'altra finestra di un'altra applicazione ci va sopra, i disegni vengono
cancellati, oppure anche quando sposto la mia dialogbar (che è di tipo
dockabile). Mi chiedevo se esisteva una funzione API che impostava lo stile
di tale controllo (che è a tutti gli effetti una finestra, infatti ogni
elemento di Windows come ad es. un pulsante, ecc. è una finestra) in modo
che fosse autoredraw cioè che i disegni fossero persisteni.
Nella classe vista esiste già preparata dal wizard del VC++ la funzione
OnDraw:
void CMyView::OnDraw(CDC* pDC)
{
 CMyDoc* pDoc = GetDocument();
 ASSERT_VALID(pDoc);
 // TODO: add draw code for native data here
}
Mi pare di aver capito, che se voglio disegnare dentro la mia vista, devo
mettere il codice di disegno dentro la OnDraw in modo che ogni volta che
scatta l'evento di ridisegno, vene eseguito anche il mio codice di disegno.
Però siccome io devo disegnare dentro al controllo picture che sta dentro
alla dialogbar e non nella finestra vista, la OnDraw associata alla vista
non va bene. Come faccio quindi a crearmi una funzione simile alla OnDraw
(Message Handler) che però si riferisca al mio control picture.

 (Message Handler) che però si riferisca al mio control picture.
Riassumendo, il mio consiglio e`: usa un BUTTON owner-draw; gestisci
WM_DRAWITEM nella tua classe di control-bar (contenitore del bottone,
che terrai disabilitato).  Se quel che devi disegnare dipende dalla
vista attiva, puoi naturalmente recuperare quest'ultima con GetActiveView
sul main-frame e delegarle cio` che vuoi o devi delegarle.
Come esempio-giocattolo, consideriamo una dialogbar con tre bottoni: due
normali pushbutton, IDC_BUTTON1 e IDC_BUTTON2, e uno disabled owner-drawn.
Al clic sui normali pushbutton vengono aggiornati dei dati (tenuti per
semplicita` dalla stessa classe dialogbar) e viene ridisegnato il terzo
bottone che funge da picture.  Sempre per semplicita` come dato teniamo
una banale CString.
Il codice e` qualcosa di simile a:
void CMyDibar::OnUpd( CCmdUI* pCmdUI )
{
    pCmdUI->Enable();
}
void CMyDibar::OnButton1()
{
    smes = "First Button";
    GetDlgItem(IDC_PICTURE)->InvalidateRect(0);
}
void CMyDibar::OnButton2()
{
    smes = "Second Button";
    GetDlgItem(IDC_PICTURE)->InvalidateRect(0);
}
void CMyDibar::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    CDC* pdc = CDC::FromHandle(lpDrawItemStruct->hDC);
    RECT* pr = &lpDrawItemStruct->rcItem;
    pdc->SaveDC();
    CPen cp(PS_DASHDOT, 0, RGB(255,0,0));
    CGdiObject* poldpen = pdc->SelectObject(&cp);
    pdc->Ellipse(pr);
    pdc->SelectObject(poldpen);
    CFont font;
    font.CreatePointFont(120, "Arial", pdc);
    pdc->SelectObject(&font);
    pdc->DrawText(smes, pr, DT_SINGLELINE|DT_CENTER|DT_VCENTER);
    pdc->RestoreDC(-1);
}
con una message-map del tipo:
BEGIN_MESSAGE_MAP(CMyDibar, CDialogBar)
 // {{AFX_MSG_MAP(CMyDibar)
 ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
 ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
    ON_UPDATE_COMMAND_UI(IDC_BUTTON1, OnUpd)
    ON_UPDATE_COMMAND_UI(IDC_BUTTON2, OnUpd)
 ON_WM_DRAWITEM()
 // }}AFX_MSG_MAP
END_MESSAGE_MAP()
Spero che il concetto sia chiaro...?
Alex