|
|
|
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. |
|
|
|
|
|
|
Tipo di |
|
Progetto |
|
|
|
Nome |
|
|
|
Directory |
|
|
|
|
Tipo: |
|
Un solo documento (tipo Notepad) |
|
Multidocumento (tipo Wordpad) |
|
Dialogo (tipo calcolatrice). |
|
|
|
|
Ci sono molti settaggi aggiuntivi, che non
descriveremo, ci limiteremo a premere il pulsante advanced e … |
|
|
|
|
… e assegnare una estensione ai file gestiti
dalla nostra applicazione, l’estensione e’ gra (=grafo). |
|
|
|
|
La generazione del progetto standard e’
completata. |
|
Il Wizard si preoccupa di generare il codice
sorgente necessario. |
|
|
|
|
Editor dei sorgenti |
|
Workspace |
|
Finestra Messaggi |
|
|
|
|
|
|
Il tab ClassView visualizza le classi con
attributi e metodi; inoltre visualizza i dati e le funzioni globali. |
|
|
|
|
Il tab resouce visualizza (e permette di
editare), le risorse dell’applicazione, come dialoghi, icone, menu’ e
toolbar. |
|
|
|
|
Il tab FileView visualizza la lista dei file del
progetto, organizzati in cartelle. |
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
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 è la finestra principale, contiene: |
|
La barra dei menù |
|
La toolbar |
|
La status Bar |
|
Incornicia le finestre dell’applicazione |
|
|
|
|
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 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). |
|
|
|
|
|
|
Il wizard genera automaticamente i sorgenti
minimi dell’applicazione. |
|
|
|
Codice proprio del wizard, non editabile. |
|
|
|
|
Lo scheletro dell’applicazione (vuota) e’ gia’
pronto. |
|
Nel menu’ Build selezionare Execute Graphedit,
il progetto viene compilato e il programma eseguito. |
|
|
|
|
|
|
Menu’: |
|
Build,Setting, |
|
Opzioni di |
|
compilazione. |
|
|
|
Eventuali path aggiuntivi (stl Silicon). |
|
|
|
|
Dal menu file selezionare new. |
|
|
|
Tipo di file |
|
|
|
Nome |
|
|
|
|
|
|
#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 |
|
|
|
|
… |
|
#endif // _MSC_VER >= 1000 |
|
|
|
#include "grafo.h" |
|
… |
|
// Attributes |
|
public: |
|
Grafo m_grafo; |
|
|
|
// Operations |
|
… |
|
|
|
|
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. |
|
|
|
|
Classe corrente |
|
|
|
Nome del messaggio |
|
|
|
Indicazione della funzione |
|
|
|
|
////////////////////////////////////////////////////////// |
|
// 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. |
|
|
|
|
|
|
/////////////////////////////////////////////// |
|
// 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. |
|
|
|
|
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. |
|
|
|
|
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. |
|
|
|
|
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); |
|
} |
|
|
|
|
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. |
|
|
|
|
|
|
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. |
|
|
|
|
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. |
|
|
|
|
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; |
|
} |
|
}; |
|
|
|
|
|
|
class Grafo |
|
{ |
|
public: |
|
vector<Nodo> Nodi; |
|
vector<Arco> Archi; |
|
}; |
|
|
|
Aggiungiamo al grafo la descrizione degli archi. |
|
|
|
|
******File view.h: |
|
// Attributes |
|
public: |
|
enum {INS_NODI,INS_ARCHI}; |
|
int m_ins_stato; |
|
******File view.cpp |
|
CGrapheditView::~CGrapheditView() |
|
{ |
|
m_ins_stato = INS_NODI; |
|
} |
|
|
|
|
|
|
|
|
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 editare le
propietà del menù. |
|
E’ importante definire: |
|
L’identificatore della voce menù |
|
Il
titolo del menu’ |
|
|
|
|
Classe Corrente |
|
|
|
Identificatore comando |
|
|
|
Operazione sul comando |
|
|
|
Funzioni definite |
|
|
|
Editing del codice |
|
|
|
|
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. |
|
|
|
|
|
|
void CGrapheditView::OnInsertMode() |
|
{ |
|
if( m_ins_stato==INS_NODI ) |
|
m_ins_stato=INS_ARCHI; |
|
else |
|
m_ins_stato=INS_NODI; |
|
} |
|
|
|
|
|
|
void CGrapheditView::OnUpdateInsertMode(CCmdUI*
pCmdUI) |
|
{ |
|
pCmdUI->Enable(TRUE); |
|
pCmdUI->SetCheck(m_ins_stato==INS_ARCHI); |
|
} |
|
|
|
(continua…) |
|
|
|
|
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 |
|