Note
Struttura
MFC e Visual C++
Vedremo come si realizza una applicazione con il Visual C++ e le Microsoft Foundation Classes.
L’applicazione sara’ un editor di grafi, e dara’ lo spunto per lo studio dell’ambiente Windows e dei meccanismi standard delle interfacce grafiche.
Vedremo infine come trasformare l’applicazione in un plug-in per Internet Explorer.
MFC: creazione progetto
Tipo di
Progetto
Nome
Directory
Sottotipo applicazione
Tipo:
Un solo documento (tipo Notepad)
Multidocumento (tipo Wordpad)
Dialogo (tipo calcolatrice).
Settaggi aggiuntivi
Ci sono molti settaggi aggiuntivi, che non descriveremo, ci limiteremo a premere il pulsante advanced e …
Settaggi aggiuntivi 2
… e assegnare una estensione ai file gestiti dalla nostra applicazione, l’estensione e’ gra (=grafo).
Finish
La generazione del progetto standard e’ completata.
Il Wizard si preoccupa di generare il codice sorgente necessario.
Workspace
Editor dei sorgenti
Workspace
Finestra Messaggi
Workspace (1/3)
Il tab ClassView visualizza le classi con attributi e metodi; inoltre visualizza i dati e le funzioni globali.
Workspace (2/3)
Il tab resouce visualizza (e permette di editare), le risorse dell’applicazione, come dialoghi, icone, menu’ e toolbar.
Workspace (3/3)
Il tab FileView visualizza la lista dei file del progetto, organizzati in cartelle.
Un inciso: l’MFC
Microsoft Foundation Class:
Incapsulamento elementi dell’interfaccia
Finestre
Bottoni, Dialoghi
Contesti Grafici
Penne, Colori, Font
Classi per la definizione di applicazioni
Applicazione (application)
Finestra Principale (main frame)
Vista (View)
Documento (Document)
Struttura dell’applicazione MFC
Classi che definiscono l’applicazione:
CWinApp, definisce i dati globali dell’applicazione.
CFrameWnd, definisce la finestra principale
Cview, definisce la “vista di un documento”
CDocument, definisce un documento dell’applicazione.
(CMDIChildWnd, sottofinestra per le applicazioni multidocumento).
Il MainFrame
Il MainFrame è la finestra principale, contiene:
La barra dei menù
La toolbar
La status Bar
Incornicia le finestre dell’applicazione
Il documento
La classe CDocument rappresenta l’insieme di dati che definiscono l’oggetto su cui l’applicazione opera, ad esempio:
Per un editor di testi, il documento e’ l’insieme di caratteri che forma il testo.
Per un programma di paint e’ un immagine.
Per un web-browser e’ una pagina html con tutto il suo contenuto.
La vista (fine inciso)
La classe Cview è una finestra e si occupa dell’interazione fra l’utente e il documento dell’applicazione:
Visualizza (o stampa) il documento.
Gestisce l’interazione con l’utente, reagento ai comandi del mouse o della tastiera.
Ad un documento possono corrispondere piu’ viste,  anche di tipo diverso (es. explorer: pagina e html source, powerpoint: diapositiva e struttura).
Uno sguardo ai sorgenti
Il wizard genera automaticamente i sorgenti minimi dell’applicazione.
Codice proprio del wizard, non editabile.
Eseguire l’applicazione
Lo scheletro dell’applicazione (vuota) e’ gia’ pronto.
Nel menu’ Build selezionare Execute Graphedit, il progetto viene compilato e il programma eseguito.
Opzioni di compilazione
Menu’:
Build,Setting,
Opzioni di
compilazione.
Eventuali path aggiuntivi (stl Silicon).
Aggiunta del file grafo.h  al progetto
Dal menu file selezionare new.
Tipo di file
Nome
File: grafo.h
#ifndef __GRAFO__
#define __GRAFO__
//#include <stl\vector>
//using namespace std;
class Nodo // Definizione di un nodo
{
public:
CPoint p; // Posiz. del nodo (CPoint=punto di N2)
inline Nodo() {} // Costruttori
inline Nodo( int x, int y ) { p.x=x; p.y=y; }
};
class Grafo // Definizione del grafo come …
{
public:
vector<Nodo> Nodi; // … vettore di nodi
};
#endif
Modifiche al file grapheditDoc.h
…
#endif // _MSC_VER >= 1000
#include "grafo.h"
…
// Attributes
public:
Grafo m_grafo;
// Operations
…
Messaggi e gestori di messaggi
Molte interfacce grafiche utilizzano i messaggi.
In Windows le finestre delle applicazioni ricevono (e a volta spediscono) messaggi in risposta a particolari eventi (es. comandi del mouse, apertura e chiusura finestre, etc.).
Il Class Wizard del VC++ permette di dichiarare, per ogni messaggio, una funzione da invocare in risposta al messaggio (gestore del messaggio).
Class Wizard e’ nel menu’ view.
Il Class Wizard
Classe corrente
Nome del messaggio
Indicazione della funzione
La funzione gestore default
//////////////////////////////////////////////////////////
// CGrapheditView message handlers
void CGrapheditView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
}
Il Class Wizard genera automaticamente il corpo vuoto della funzione, che deve essere personalizzata secondo le funzionalita’ previste.
Funzione gestore custom
///////////////////////////////////////////////
// CGrapheditView message handlers
void CGrapheditView::OnLButtonDown(UINT nFlags, CPoint point)
{
CGrapheditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDoc->m_grafo.Nodi.push_back(Nodo(point.x,point.y));
}
In risposta ad un click del bottone sinistro del mouse sulla finestra view, l’applicazione crea un nuovo nodo nel documento corrispondete, posizionato sul punto di click.
Gestore OnDraw defalut
void CGrapheditView::OnDraw(CDC* pDC)
{
CGrapheditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
Quando il sistema deve mostrare una finestra, manda a questa un messaggio WM_PAINT; il gestore del messaggio chiama a sua volta la funzione OnDraw, che si deve occupare di visualizzare il documento.
Un inciso: la classe CDC
La classe CDC incapsula un device context, che e’ l’oggetto utilizzato da Windows per disegnare dentro una finestra.
La classe CDC ha come membri una serie di funzioni che permettono di disegnare punti, linee, rettangoli, ellissi, … di vari colori e con varie opzioni di visualizzazione.
Gestore OnDraw custom
void CGrapheditView::OnDraw(CDC* pDC)
{
vector<Nodo>::iterator  i;
const int R = 3;
CGrapheditDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(i=pDoc->m_grafo.Nodi.begin();
      i!=pDoc->m_grafo.Nodi.end();++i)
pDC->Ellipse(i->p.x-R,i->p.y-R,
                   i->p.x+R,i->p.y+R);
}
Il sistema di Update
void CGrapheditView::OnLButtonDown(…)
{
…
pDoc->SetModifiedFlag();
pDoc->UpdateAllViews(0,0);
}
Quando un metodo della view modifica il documento deve:
Chiamare SetMofiedFlag per marcare modificato il documento
Chiamare UpdateAllViews per ridisegnare tutte le viste. Questa funzione puo’ avere un parametro che specifica il tipo di cambiamento effettuato nel documento.
Esempio di funzionamento
Si possono inserire nodi cliccando sulla finestra.
I nodi sono disegnati su tutte le finestre (menu’ window/new windows).
Il documento e’ marcato modificato: l’applicazione richiede il salvataggio.
Inserimento di archi
Per permette l’inserimento degli archi, dobbiamo definire uno stato di inserimento (archi o nodi):
Definiamo un campo della view che tiene traccia dello stato di inserimento.
Definiamo un menu’ che permette di cambiare lo stato di inserimento.
Associamo al menu’ un bottone della toolbar.
Modifiche al file graph.h (1/2)
class Arco // Classe descrizione di arco
{
public:
int a,b; // Indici dei nodi estremi
inline Arco() {} // Costr. default
inline Arco( int na, int nb ) // Costr. Init.
{
a=na; b=nb;
}
};
Modifiche al file graph.h (2/2)
class Grafo
{
public:
vector<Nodo> Nodi;
vector<Arco> Archi;
};
Aggiungiamo al grafo la descrizione degli archi.
Modifiche all view
******File view.h:
// Attributes
public:
enum {INS_NODI,INS_ARCHI};
int m_ins_stato;
******File view.cpp
CGrapheditView::~CGrapheditView()
{
m_ins_stato = INS_NODI;
}
Resource Editor: Menu’
Cliccando sul tab del resource editor appaiono le risorse dell’applicazione.
Le applicazioni multidocumento hanno due menu’: uno normale ed uno per quando non ci sono documenti aperti.
Attraverso l’interfaccia grafica e’ possibile aggiungere voci di menu’
"Doppiocliccando sul menù è possibile..."
Doppiocliccando sul menù è possibile editare le propietà del menù.
E’ importante definire:
L’identificatore della voce menù
Il  titolo del menu’
Il ClassWizard per i menù
Classe Corrente
Identificatore comando
Operazione sul comando
Funzioni definite
Editing del codice
Gestori dei messaggi menù
void CGrapheditView::OnInsertMode()
{
// TODO: Add your command handler code here
}
void CGrapheditView::OnUpdateInsertMode(CCmdUI* pCmdUI)
{
// TODO: Add your command update UI handler code here
}
Le funzioni associate ai comandi (menu’) sono due: la prima esegue l’operazione associata al comando; la seconda gestisce l’abilitazione del comando.
Gestore del menù
void CGrapheditView::OnInsertMode()
{
if( m_ins_stato==INS_NODI )
m_ins_stato=INS_ARCHI;
else
m_ins_stato=INS_NODI;
}
Gestore abilitazioni
void CGrapheditView::OnUpdateInsertMode(CCmdUI* pCmdUI)
{
pCmdUI->Enable(TRUE);
pCmdUI->SetCheck(m_ins_stato==INS_ARCHI);
}
(continua…)
Contatti
Claudio Rocchini
Istituto di Elaborazione dell’informazione
CNR, Area Ricerca di Pisa
Email: rocchini@iei.pi.cnr.it
Web: http://vcg.iei.pi.cnr.it/~rocchini
Tel. 0503152926