Newsgroup: it.comp.programmare.win32
Titolo: Doc/View e CDialogBar in VC++

Ho creato un'applicazione document view a singola vista con class wizard.
Nella classe frame dell'applicazione ho una barra di stato, una barra degli
strumenti e una barra di dialogo.
CStatusBar  m_wndStatusBar; // barra di stato
CToolBar    m_wndToolBar; // barra degli strumenti
CDialogBar m_wndDlgBar; // barra di dialogo
La barra degli strumenti e la barra di dialogo sono entrambi agganciabili.
Nella barra di dialogo ho inserito alcuni controlli, e quindi in pratica la
barra di dialogo la uso come se fosse una specie di barra degli strumenti
più ricca.
Ho la necessita di accedere alla barra di dialogo dalla classe view per poi
accedere ai vari controlli contenuti in essa. Il problema è che dalla classe
view, la classe frame non è visibile e quindi non posso accedere
direttamente ai suoi membri. Come devo fare?
Cioè qual è il modo più corretto nella filosofia doc/view di accedere alla
barra di dialogo.
Grazie.

 direttamente ai suoi membri. Come devo fare?
CLaTuaFrameWnd *wnd = (CLaTuaFrameWnd *)AfxGetMainWnd();
--
Bye! Lorenzo Lutti
http://www.geocities.com/SiliconValley/Peaks/6258/

 barra di dialogo.
AfxGetMainWnd() ti torna, da qualsivoglia punto del tuo codice,
la "main window", cioe` la finestra di classe frame di tuo interesse.
Naturalmente, te la torna in modo 'generico', cioe` come CWnd*.
Piuttosto che fare un cast di questo, a livello C++, al puntatore
a classe-di-tuo-specifico-interesse, un modo piu` "disaccoppiato"
(piu` aderente alla normale filosofia Windows) sarebbe quello di
definire un messaggio Windows, cui la tua classe-mainframe sa
rispondere tornando l'handle della finestra di classe-dialogbar (o
piu` specificamente implementando le precise interazioni con la
dialogbar di cui hai bisogno).
L'API RegisterWindowMessage ti permette di registrare "tuoi"
arbitrari messaggi, ad esempio, e torna il codice intero che puoi
usare con SendMessage (o PostMessage se vuoi richiedere una
azione 'ritardata').  Ma puoi anche scegliere di usare direttamente
degli offset rispetto a WM_APP.
Alex




 della mia classe frame è sconosciuto alla classe view.
Certo, devi includere l'header della classe della finestra mainframe (il Visual
C++ di default te la chiama MainFrm.h o qualcosa di simile).


Puoi spiegarmi un po' più in dettaglio come si fa, magari se è possibile
farlo con il Class Wizard di Visual C++ 6.0 ?
Grazie.

 view, la classe frame non è visibile e quindi non posso accedere
e io ti avevo suggerito l'approccio Windows-like (che disaccoppia le
classi C++ in gioco):
: AfxGetMainWnd() ti torna, da qualsivoglia punto del tuo codice,
: la "main window", cioe` la finestra di classe frame di tuo interesse.
: Naturalmente, te la torna in modo 'generico', cioe` come CWnd*.
    [snip]
: definire un messaggio Windows, cui la tua classe-mainframe sa
: rispondere tornando l'handle della finestra di classe-dialogbar (o
: piu` specificamente implementando le precise interazioni con la
: dialogbar di cui hai bisogno).
    [snip]
: usare con SendMessage (o PostMessage se vuoi richiedere una
: azione 'ritardata').  Ma puoi anche scegliere di usare direttamente
: degli offset rispetto a WM_APP.
Evidentemente, non posso darti ulteriori dettagli sulle "precise
interazioni con la dialogbar di cui hai bisogno" perche`, di cosa
tu abbia bisogno, lo sai solo tu.  E` probabilmente l'approccio
piu` furbo, ma e` specifico della tua applicazione, e, ovviamente,
nessun Wizard ti aiutera` ad implementarlo.
Supponiamo dunque che tu abbia deciso che quel che ti serve
e` ottenere il CWnd* della tua dialog-bar, e che esso sia tenuto
dal mainframe nella sua variabile-membro m_pDb; supponiamo
inoltre che tu abbia deciso di usare WM_APP+1 a questo scopo.
La classe view (o chiunque altro) puo` dunque inviare un
WM_APP+1 (con SendMessage, visto che aspetta risposta)
al mainframe, e ottenere come risultato la CWnd* cercata
(ovviamente tramite un cast).
La mainframe dovra` rispondere a questo messaggio in modo
adeguato.
E dunque, in MainFrm.cpp, subito dopo la macro BEGIN_MESSAGE_MAP
con la quale inizia la tua mappa dei messaggi, aggiungerai:
ON_MESSAGE( WM_APP+1, OnDBarRequest)
e ovviamente in MainFrm.h, entro la dichiarazione della classe,
afx_msg LRESULT OnDBarRequest(WPARAM, LPARAM);
e ancora in MainFrm.cpp l'implementazione:
LRESULT
CMainFrame::OnDBarRequest(WPARAM, LPARAM)
{
    return (LRESULT)m_pDb;
}
Tutto chiaro sin qua, spero?  Naturalmente, la ON_MESSAGE
(come insistentemente spiegato dai commenti che il Wizard ti
ha inserito nel codice) la scriverai FUORI dal blocco di commenti
che inizia con  // {{AFX_MSG_MAP(CMainFrame), se no il
Wizard stesso potra` piu` avanti eliminartela, ecc, ecc.
OK, cio` fatto, nei punti del tuo codice dove ti serve
accedere al CWnd* della dialog bar, scriverai:
    CWnd* pDb = (CWnd*)AfxGetMainWnd()->SendMessage(WM_APP+1);
Tutto chiaro anche qui, spero?
L'unico punto debole di questo approccio e` la mancanza di
type-safety, dovuta alla necessita` di passare attraverso un
tipo LRESULT come risultato della SendMessage (e del gestore
di messaggio che qui ho chiamato OnDBarRequest, ovviamente).
In cambio, hai il totale 'decoupling' fra le tue classi.
Alex

     CWnd* pDb = (CWnd*)AfxGetMainWnd()->SendMessage(WM_APP+1);
Ho capito come funziona il meccanismo... Cioè in pratica si crea un nuovo
gestore di messaggi OnDBarRequest associato al messaggio WM_APP+1 (che per
semplicita l'ho definito con WM_DBARREQUEST mediante #define).
Quindi ad es. dalla mia finestra view posso inviare il messaggio
WM_DBARREQUEST alla finestra frame ed essa mi restituisce un riferimento
alla mia barra di dialogo m_pDb contenuta della classe frame.
Il problema è che l'istruzione  return (LRESULT)m_pDb  genera un errore
perchè non può effettuare una conversione (cast) dal tipo CDialog a long.
Come devo correggere tale istruzione?
Inoltre che differenza c'è fra  i messaggi definiti a partire dall'indirizzo
WM_APP e quelli definiti a partire da WM_USER ? (Mi pare di aver capito
dalla guida in linea di VC++ che quelli definiti con WM_USER sono "privati")
Grazie.



 dalla guida in linea di VC++ che quelli definiti con WM_USER sono
"privati")
I messaggi da WM_APP in su sono a disposizione della tua applicazione,
quelli da WM_USER a WM_APP sono in parte gia` usati dalle window
procedure predefinite di alcuni controlli (puoi comunque usarli se sai
che la specifica finestra cui li stai spedendo non li usa).
Alex

 perche` non c'e` nessun CDialog da convertire, bensi` un CDialog*...!).
Hai ragione, io effettuavo un return (LRESULT)m_Db cioč restituivo
(distrattamente) la dialogbar e non il suo indirizzo.