Upload
others
View
6
Download
0
Embed Size (px)
Citation preview
ΚΕΦΑΛΑΙΟ 2
ΚΕΦΆΛΑΙΟ 2
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX(ΕΦΑΡΜΟΓΉ 1)
ΠΕΡΙΕΧΟΜΕΝΑ
ΕΙΣΑΓΩΓΗ..................................................................................................................................................27
1. ΔΗΜΙΟΥΡΓΙΑ ΤΟΥ ΣΚΕΛΕΤΟΥ ΤΗΣ ΕΦΑΡΜΟΓΗΣ.......................................................................28
2. ΧΡΗΣΙΜΕΣ ΤΑΞΕΙΣ..................................................................................................................................33
3. MENU ΚΑΙ ΠΑΡΑΘΥΡΑ ΔΙΑΛΟΓΟΥ....................................................................................................36
MENU BAR.................................................................................................................................................36
DIALOG BOXES........................................................................................................................................37
4. ΤΡΟΠΟΠΟΙΗΣΕΙΣ ΣΤΗΝ DOCUMENT CLASS..................................................................................40
5. ΤΡΟΠΟΠΟΙΗΣΕΙΣ ΣΤΗΝ VIEW CLASS..............................................................................................44
6. ΑΝΑΚΕΦΑΛΑΙΩΣΗ ΤΗΣ ΕΦΑΡΜΟΓΗΣ 1...........................................................................................47
Εισαγωγή Η παρούσα εφαρμογή, η οποία αποτελεί την εναρκτήρια για αυτές που θα ακολουθήσουν
δίνει την δυνατότητα στον αναγνώστη να εξοικειωθεί με τo περιβάλλον της Microsoft Visual
C++. Ουσιαστικά η Microsoft Visual C++ είναι ένα στοιχείο του Microsoft Developer Studio.
Οι δυνατότητες αυτού του λογισμικού είναι καταπληκτικές. Ονομάζεται “ολοκληρωμένο
περιβάλλον ανάπτυξης“ επειδή με ένα μόνο εργαλείο, ο χρήστης έχει την δυνατότητα να
δημιουργήσει εφαρμογές εκκίνησης χωρίς να γραφεί κώδικας από τον ίδιο, να εξετάσει μια
εργασία με πολλούς διαφορετικούς τρόπους και να επεξεργαστεί αρχεία πηγαίου κώδικα. Η
Visual C++ μπορεί να μεταγλωττίσει κώδικα αλλά και να δημιουργήσει. Πολλά από όσα
πρέπει να γίνουν για τον προγραμματισμό σε Windows τα αναλαμβάνουν οι διάφοροι μάγοι
(Wizards) της Visual C++. Ο χρήστης στη συνέχεια θα δημιουργήσει μια εφαρμογή των
Windows με την βοήθεια του μάγου AppWizard.
27
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
Το παράδειγμα που παρουσιάζεται παρακάτω μας δίνει την δυνατότητα να καταλάβουμε
πως δημιουργείται μια απλή εφαρμογή σε λειτουργικό σύστημα 32bit (Windows) στην οποία
ο χρήστης θα μπορεί να εισάγει κάποια δεδομένα (ένα string και ένα number) μέσω του
dialog box, να διαχειρίζεται τα δεδομένα της εισόδου, στη συνέχεια τα δεδομένα να
απεικονίζονται στην οθόνη και τέλος υπάρχει η δυνατότητα αποθήκευσης των δεδομένων.
1. Δημιουργία του σκελετού της εφαρμογής Ο χρήστης μπορεί να δημιουργήσει μια εφαρμογή των Windows σε λίγα λεπτά, με ένα
εργαλείο που ονομάζεται AppWizard. Ο AppWizard είναι ένα πολύ αποτελεσματικό
εργαλείο διότι αντιγράφει στην εφαρμογή του χρήστη τον κώδικα που απαιτούν όλες σχεδόν
οι εφαρμογές των Windows. Ο AppWizard μπορεί να δημιουργήσει πολλά είδη εφαρμογών,
αλλά αυτό που χρειάζεται ο χρήστης, τουλάχιστον κατ’ αρχήν, είναι ένα εκτελέσιμο (.exe)
πρόγραμμα. Ο χρήστης θέλει επίσης να δημιουργήσει ο AppWizard τον βασικό κώδικα-
κατηγορίες, αντικείμενα, και συναρτήσεις που πρέπει να υπάρχουν σε κάθε πρόγραμμα. Η
εφαρμογή SDI που δημιουργείται με τον AppWizard είναι εφαρμογή εγγράφου / προβολής.
Αυτό σημαίνει ότι ο AppWizard δημιουργεί μια τάξη που απορρέει από την CDocument και
δίνει ορισμένες δυνατότητες σε αυτή την νέα τάξη εγγράφου. Επίσης δημιουργεί μια τάξη
προβολής που απορρέει από την CView και τις δίνει άλλες δυνατότητες.
Χωρίς ο χρήστης να κάνει προγραμματισμό οι Wizards αναλαμβάνουν από μόνοι τους να
υλοποιήσουν μια αρχική εφαρμογή. Ο μάγος που το κάνει αυτό είναι ο AppWizard και έτσι
θα δημιουργηθεί ένα καινούργιο project τύπου MFC. Για να δημιουργηθεί ένα πρόγραμμα
όπως αυτό ο χρήστης από τη Microsoft Visual Studio 6.0, επιλέγει File, New. Στη συνέχεια
διαλέγει την καρτέλα με το όνομα Projects. Θα χρησιμοποιηθεί ο MFC Application Wizard
(exe) και θα πρέπει να δοθεί ένα όνομα στο project name καθώς και στο location, για
παράδειγμα project name : mydraw. Αφού γίνουν όλα τα παραπάνω ο χρήστης επιλέγει OK.
Microsoft Visual C++, File, New
28
ΚΕΦΑΛΑΙΟ 2
Ο AppWizard θα λειτουργήσει μέσω ενός αριθμού βημάτων. Σε κάθε βήμα, ο χρήστης
παίρνει μια απόφαση σχετικά με το είδος της εφαρμογής που θέλει και κατόπιν κάνει κλικ
στο Next.
Από εκεί και μετά ο χρήστης καλείται να επιλέξει ανάμεσα σε διάφορες προτάσεις που
αφορούν την μορφή της εργασίας του. Η πρώτη επιλογή αφορά τον τύπο της εφαρμογής
(SDI- Single Document Interface or MDI –Multiple Document Interface). Μια SDI εφαρμογή
είναι π.χ το Notepad το οποίο έχει την ικανότητα να έχει κάθε φορά ένα μόνο έγγραφο
ανοιχτό. Εν αντίθεση η MDI εφαρμογή μπορεί να ανοίξει πολλά έγγραφα μαζί και ένα τέτοιο
παράδειγμα είναι το Word και το Excel. Ένα τελευταίο είδος εφαρμογής είναι και αυτή που
βασίζεται σε παράθυρα διάλογου αυτή δεν έχει καμία σχέση με τις δυο προηγούμενες και δεν
θα μας απασχολήσει στο παρόν κεφάλαιο.
Step1: Single document, Next
29
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
Αμέσως μετά ο χρήστης καλείται να επιλέξει τι είδους υποστήριξη βάσεων δεδομένων θα
ήθελε καθώς και τι είδους σύνθετης υποστήριξης εγγράφου. Στην συγκεκριμένη εφαρμογή
δεν απαιτείται τίποτα από τα δυο και έτσι ο χρήστης επιλέγει None.
Step 2: None database, Next
Το τρίτο βήμα στην εκτέλεση του AppWizard είναι να αποφασίσει ο χρήστης τι είδους
σύνθετη υποστήριξη εγγράφου θέλει να συμπεριλάβει. Μέσω αυτής της επιλογής δίνεται η
ευκαιρία στο χρήστη να ανακαλύψει την έννοια της τεχνολογίας ActiveX. Η τεχνολογία
ActiveX επιτρέπει στο χρήστη να μοιράζει την εργασία σε διαφορετικές εφαρμογές και να τις
ρυθμίζει έτσι ώστε να επικοινωνούν. Ωστόσο στην συγκεκριμένη εφαρμογή δεν απαιτείται
τέτοιου είδους υποστήριξη επομένως απενεργοποιείται η επιλογή ActiveX και επιλέγεται
None.
Step 3: None compound document support, No ActiveX controls, Next.
Οι επόμενες επιλογές που θα πρέπει να κάνει ο χρήστης έχουν να κάνουν κυρίως με την
εμφάνιση του εγγράφου, δηλαδή αν η εφαρμογή θα έχει την μορφή τύπου Explorer ή την
30
ΚΕΦΑΛΑΙΟ 2
μορφή κλασικού παραθύρου. Ακόμα ο χρήστης ερωτάται για κάποιες επιπλέον παραμέτρους
όσον αφορά τη εμφάνιση της εφαρμογής όπως για παράδειγμα την χρήση τρισδιάστατων
γραφικών, την απεικόνιση των λειτουργιών Print και Print Preview, την απεικόνιση διαφόρων
status bar και toolbar.
Ακόμα ο χρήστης ερωτάται αν θέλει να εισάγονται σχόλια στο κώδικα, είναι προφανές
πως θα θέλει επομένως επιλέγει Yes, please. Η επόμενη ερώτηση δεν είναι και τόσο απλή. Ο
χρήστης τώρα καλείται να απαντήσει αν θέλει την βιβλιοθήκη MFC ως κοινόχρηστο DLL ή
συνδεδεμένη στατικά. Η διάφορα έγκειται στο γεγονός ότι ένα DLL (Βιβλιοθήκη Δυναμικής
Σύνδεσης) είναι μια συλλογή συναρτήσεων που χρησιμοποιούνται από πολλές διαφορετικές
εφαρμογές. Χρησιμοποιώντας ένα DLL τα προγράμματα θα είναι μικρότερα, αλλά οι
εφαρμογές θα είναι εξαρτημένες από την ύπαρξη της γλώσσας C++. Δηλαδή αν η εφαρμογή
εκτελεστεί σε κάποιον άλλο υπολογιστή δεν θα λειτουργεί αν στον συγκεκριμένο υπολογιστή
δεν υπάρχουν αποθηκευμένες οι βιβλιοθήκες της C++. Αν η σύνδεση της βιβλιοθήκης MFC
στην εφαρμογή γίνει στατικά, αυτή θα είναι μεγαλύτερη, αλλά είναι ευκολότερο να
μεταφερθεί και να αντιγραφεί. Ο χρήστης στην εφαρμογή αυτή επιλέγει As a shared DLL
άλλωστε το μικρότερο εκτελέσιμο πρόγραμμα είναι εύχρηστο γενικώς.
Αμέσως μετά ο AppWizard δημιουργεί μια σειρά από τάξεις οι οποίες ελέγχουν την
εφαρμογή ενώ ταυτόχρονα δομείται ο σκελετός της εφαρμογής και παρατίθεται μια
λεπτομερής παρουσίαση των χαρακτηριστικών της. Κάνοντας ο χρήστης κλικ στο OK
δημιουργείται πραγματικά η εφαρμογή μέσα σε λίγα λεπτά, εκπληκτικό γεγονός, αφού
δημιουργούνται εκατοντάδες γραμμές κώδικα, μενού, παράθυρα διαλόγου, κείμενο βοήθειας
και εικόνες bitmap.
Step 4: Από τα features μόνο 3D controls, Next
31
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
Step 5: Yes source file comments and shared DLL, Next
Step 6: Ενημερωνόμαστε ποιες τάξεις δημιουργεί ο Αppwizard. Finish
Η εφαρμογή χτίζεται (F7) και εκτελείται, εμφανίζεται το παράθυρο της εφαρμογής με τα
γνωστά menus τα οποία όμως δεν κάνουν και πολλά πράγματα. Οι εντολές του File menu
(New, Open, Save, Save As) είναι ενεργοποιημένες αλλά δεν λειτουργούν. Ομοίως και για τις
εντολές του Edit menu οι οποίες είναι απενεργοποιημένες και έτσι θα παραμείνουν. Ωστόσο
το παράθυρο της εφαρμογής αυτής έχει την δυνατότητα να αλλάζει τις διαστάσεις του και να
μετακινείται. Η μέχρι τώρα παραπάνω εφαρμογή επιτεύχθηκε χωρίς να να γραφεί ίχνος
κώδικα από τον προγραμματιστή. Ο Wizard έχει φτιάξει κώδικα, σπασμένο σε διάφορα
αρχεία (γι’ αυτό χρειάζονται τα projects). Μια σύντομη επεξήγηση του κώδικα του Wizard
βρίσκεται στο [1].
32
ΚΕΦΑΛΑΙΟ 2
Εικόνα 1: SDI εφαρμογή στην αρχική της μορφή
Η πρώτη εφαρμογή μοιάζει όπως οποιαδήποτε άλλη εφαρμογή των Windows. Αξίζει μια
ματιά στο Help-About το οποίο περιέχει πληροφορίες για την ονομασία της εφαρμογής
καθώς και την χρονολογία κατασκευής της. Αυτό φαίνεται στην εικόνα 2.
Εικόνα 2
2. Χρήσιμες τάξεις Στην προηγούμενη ενότητα υλοποιήθηκε ο σκελετός του προγράμματος. Για το σκοπό
αυτό ο Application Wizard έφτιαξε μερικές τάξεις. Ο κώδικας που δημιουργείται από τον
AppWizard μπορεί να μην έχει νόημα αμέσως ειδικά αν ο χρήστης δεν έχει γράψει κώδικα σε
C++ πριν. Σε αυτήν την ενότητα παρουσιάζονται με συντομία οι τάξεις αυτές, που είναι
συνολικά 5 και είναι οι ακόλουθες:
33
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
CΑboutDlg η οποία αποτελεί μια τάξη παραθύρου διαλόγου για το παράθυρο διάλογου
About.
CΜainFrame αποτελεί μια τάξη πλαισίου.
CMyDrawApp είναι μια τάξη CWinApp για ολόκληρη την εφαρμογή
CMyDrawDoc η οποία είναι τάξη εγγράφου.
CMyDrawView αποτελεί μια τάξη προβολής.
Application τάξη
Διαχειρίζεται την εφαρμογή. Οι περισσότερες διεργασίες είναι κρυμμένες από το χρήστη.
Στη τάξη αυτή σπάνια γίνονται προγραμματιστικές επεμβάσεις από τον χρήστη. Από αυτές
που φαίνονται, οι πιο σημαντική διεργασία είναι ότι αναλαμβάνει την αρχικοποίηση, όπως
για παράδειγμα το άνοιγμα παραθύρου. Γίνεται με χρήση της member μεταβλητής
m_pMainWnd.
ΠΡΟΣΟΧΗ: εδώ δεν αρχικοποιούνται δεδομένα, αυτό γίνεται μέσω της document τάξης.
Εντολές από τα menus που δεν μεταβάλλουν τα δεδομένα μπορούν να συλλαμβάνονται εδώ.
Τέτοια εντολή είναι αυτή που παρουσιάζει το About dialog box. Αν τα δεδομένα αλλάζουν
ως αποτέλεσμα της εντολής, τότε αυτή δεν μπορεί να συλληφθεί από εδώ επειδή δεν υπάρχει
τρόπος να δημιουργηθεί δείκτης της document τάξης.
Main Frame τάξη
Είναι τάξη της οποίας τα μέλη συνήθως χρησιμοποιούνται αυτόματα. Ο προγραμματιστής
σπάνια προσθέτει κώδικα εδώ. Περιέχει πληροφορίες για τα διάφορα στοιχεία της
εφαρμογής: windows, menus, toolbars και απεικονίσεις. Συλλέγει και αποστέλλει τα
μηνύματα στα έγραφα και στις απεικονίσεις της εφαρμογής.
Χρήσιμες member συναρτήσεις:
PreCreateWindow(CREATESTRUCT)
Δίνει παραμέτρους στο λειτουργικό σύστημα για το παράθυρο. Για το σκοπό αυτό
δίνονται τιμές στα μέλη της δομής τύπου CREATESTRUCT και μέσα από τη συνάρτηση
περνιόνται οι παράμετροι στο λειτουργικό σύστημα με κλήση της αντίστοιχης συνάρτησης
της βασικής τάξης.
Document τάξη
Περιέχει τα δεδομένα των documents που έχει ανοιχτά η εφαρμογή και τις συναρτήσεις
που κάνουν την επεξεργασία τους.
34
ΚΕΦΑΛΑΙΟ 2
Τα δεδομένα αποθηκεύονται ως member μεταβλητές. Η κάθε εφαρμογή μπορεί να έχει
πολλές τέτοιες τάξεις, εφόσον έχει δηλωθεί ως εφαρμογή πολλών documents (Multi-
document Interface, MDI). Όλες οι εντολές από τα menus που τροποποιούν τα δεδομένα
πρέπει να συλλαμβάνονται μέσα από την document τάξη. ΠΡΟΣΟΧΗ: Δεν τοποθετούνται
εδώ οι συναρτήσεις που απεικονίζουν τα δεδομένα. Αυτό αναλαμβάνεται από τη view τάξη.
Χρήσιμες member συναρτήσεις:
OnNewDocument()
περιέχει την αρχικοποίηση των δεδομένων.
SetModifiedFlag()
δείχνει ότι το έγγραφο έχει μεταβληθεί. Καλείται μετά από κάθε επεξεργασία δεδομένων,
έτσι ώστε η εφαρμογή να είναι ενήμερη ότι τα δεδομένα πρέπει να σωθούν πριν τον
τερματισμό, και να το ζητήσει από το χρήστη.
UpdateAllViews(NULL)
σηματοδοτεί την ανάγκη για επανασχεδίαση της απεικόνισης των δεδομένων καθώς αυτά
άλλαξαν. Έτσι με την κλήση της λαμβάνει το ανάλογο μήνυμα η αντίστοιχη απεικόνιση
(δηλαδή κάποια view τάξη).
Serialize(CArchive&)
Αποθηκεύει και φορτώνει δεδομένα.
View τάξη
Φροντίζει την απεικόνιση των δεδομένων κάποιου εγγράφου σε ένα παράθυρο. Η κάθε
εφαρμογή μπορεί να έχει πολλές τέτοιες τάξεις, συνήθως τόσες όσα τα documents που είναι
ανοιχτά.
Χρήσιμες member συναρτήσεις:
GetDocument()
επιστρέφει δείκτη στο έγγραφο με το οποίο είναι συνδεδεμένη η απεικόνιση, δηλαδή συνδέει
την view τάξη με την αντίστοιχη document τάξη. Αυτό είναι απαραίτητο έτσι ώστε να
μπορούν να χρησιμοποιηθούν τα δεδομένα, που είναι member μεταβλητές της document
τάξης, από τη view τάξη.
Invalidate()
γνωστοποιεί η view τάξη ότι η απεικόνιση χρειάζεται ενημέρωση. Έτσι αποστέλλεται το
κατάλληλο μήνυμα, που το συλλαμβάνει η ίδια η view τάξη.
OnPaint()
35
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
συλλαμβάνει την εντολή για σχεδίαση. Προετοιμάζει τη σχεδίαση και καλεί την
OnDraw(CDC *) για να κάνει την δουλειά. Ο προγραμματιστής δεν την πειράζει.
OnDraw(CDC *)
είναι η συνάρτηση που καλείται όταν λαμβάνεται μήνυμα για σχεδίαση. Χρησιμοποιεί άλλες
member συναρτήσεις της view τάξης για να κάνει τη σχεδίαση τόσο κειμένου όσο και
γραφικών.
Dialog Box τάξεις
Είναι οι τάξεις που περιέχουν τις συναρτήσεις χειρισμού των dialog boxes. Παράγονται
από την μητρική CDialog. Η κάθε εφαρμογή μπορεί να έχει πολλές ή και καμία τέτοια τάξη.
Οι Member μεταβλητές συνδέονται με όλα τα αντικείμενα που μπορεί να χειριστεί ο χρήστης
(edit boxes, buttons list boxes, κλπ.) Οι member μεταβλητές είτε είναι τύπου Value και
κρατούν τα δεδομένα αυτών των αντικειμένων (είναι τύπου int, CString, BOOL, κλπ.) είτε
είναι τύπου control και χρησιμοποιούνται για την μεταβολή των ιδιοτήτων των αντικειμένων.
Χρήσιμες member συναρτήσεις:
DoModal()
αναλαμβάνει το σχεδιασμό και τις διάφορες λειτουργίες του dialog box. Στην πιο απλή
περίπτωση ελέγχει αν πατήθηκε το OK ή το CANCEL.
DoDataExchange()
αναλαμβάνει την επικοινωνία με το χρήστη. Πάντα καλείται η αντίστοιχη συνάρτηση της
μητρικής τάξης CDialog.
3. Μενού και Παράθυρα διαλόγουΣε αυτή την ενότητα ο χρήστης ασχολείται με τα παράθυρα διαλόγου και το μενού της
εφαρμογής. Με τα windows, η λήψη των δεδομένων από το χρήστη δεν είναι απλή και το
μεγαλύτερο μέρος της εισόδου λαμβάνεται από τα παράθυρα διαλόγου.
Menu Bar
Πρώτη ενέργεια του χρήστη είναι να προσθέσει μία εντολή στο menu για να μπορεί να
εισάγει τα δεδομένα. Με το μενού ο χρήστης μπορεί να πει στο πρόγραμμα τι να κάνει,
δηλαδή η εφαρμογή δέχεται τις εντολές μέσω των μενού. Ο AppWizard δημιουργεί τα τυπικά
μενού για μια νέα εφαρμογή, ωστόσο υπάρχει η δυνατότητα δημιουργίας νέων τα οποία θα
βοηθήσουν στην επικοινωνία με το πρόγραμμα. Για να βρεθεί το υπάρχον menu πρέπει ο
36
ΚΕΦΑΛΑΙΟ 2
χρήστης να ζητήσει να δει τα Resources του προγράμματος (project window, Resource tab),
και από αυτά να ανοίξει τα menus. Με διπλό click στο IDR_MAINFRAME παρουσιάζεται το
menu. Ανοίγεται το Edit και με δεξί click στην τελευταία κενή επιλογή του menu εμφανίζεται
ένα menu που στο τέλος έχει τις properties.
Το dialog box (του περιβάλλοντος της Visual C++ και όχι της εφαρμογής) που
εμφανίζεται μπορεί να καρφωθεί μόνιμα στην οθόνη με την πινέζα στο πάνω αριστερό τμήμα
του αν και δεν είναι απαραίτητο. Στη συνέχεια αλλάζονται οι properties. Έτσι το ID γίνεται
ID_EDIT_INSERT, και το Caption "Insert data".
Εικόνα 3
Dialog Boxes
Στη συνέχεια ο χρήστης θα ασχοληθεί με τα dialog boxes (παράθυρα διαλόγου). Συνήθως
οι εφαρμογές των Windows έχουν πολλά παράθυρα διαλόγου, καθένα προορισμένο να
λαμβάνει ένα συγκεκριμένο τύπο πληροφοριών από το χρήστη. Για κάθε παράθυρο διαλόγου
που εμφανίζεται στην οθόνη, υπάρχουν δυο οντότητες που χρειάζεται να σχεδιαστούν: Έναν
πόρο παραθύρου διαλόγου και μια τάξη παραθύρου διαλόγου. Ο πόρος παραθύρου διαλόγου
χρησιμοποιείται για την σχεδίαση του παραθύρου διαλόγου και των στοιχείων του στην
οθόνη. Η τάξη φέρει τις τιμές του παραθύρου διαλόγου και είναι μια συνάρτηση μέλος της
τάξης που προκαλεί την σχεδίαση του παραθύρου διαλόγου στην οθόνη. Λειτουργούν μαζί
για να επιτύχουν το συνολικό αποτέλεσμα: Να κάνουν την επικοινωνία με το πρόγραμμα
ευκολότερη για τον χρήστη.
Υπάρχει ένα έτοιμο, το About box που θα μετατραπεί για να προσαρμοστεί στην
εφαρμογή, και χρειάζεται ένα ακόμα, αυτό που θα δέχεται τα δύο μοναδικά δεδομένα του
προγράμματος, τον αριθμό (number) και το string.
37
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
About box
Η εικόνα 2.4 δείχνει το παράθυρο διαλόγου About που ο AppWizard δημιουργεί για τον
χρήστη. Περιέχει το όνομα της εφαρμογής και το έτος κατασκευής της. Για να βρεθεί το
about dialog box πρέπει ο χρήστης να ζητήσει να δει τα Resources του προγράμματος και από
αυτά να ανοίξει τα dialog boxes και θα βρει το IDD_ABOUTBOX. Με διπλό click ανοίγει το
about dialog box. Αν ο χρήστης επιθυμεί να αλλάξει το About mydraw box αρκεί να κάνει
δεξί click πάνω στο about box στο string copywrite και επιλέγει properties. Εμφανίζεται και
καρφώνεται μόνιμα στην οθόνη το dialog box των properties. Επεξεργάζεται το Caption και ο
χρήστης προσθέτει Visual C++ στο τέλος.
Το πρόγραμμα χτίζεται ξανά (μόνο τα αλλαγμένα μέρη του) εκτός αν επιλεγεί η Rebuild
All από το menu bar της Visual C++ το Build όποτε χτίζεται από την αρχή. Η αλλαγή έχει
γίνει χωρίς ακόμα να γραφεί καθόλου κώδικας. Το παράθυρο διαλόγου About θα έχει τώρα
την μορφή που απεικονίζεται στην εικόνα 2.5.
Εικόνα 4 Εικόνα 5
Παρατήρηση:
Υπάρχει η τάξη CAboutDlg, παιδί της CDialog, που διαχειρίζεται το dialog box, με έναν
constructor και το overloading της συνάρτησης της μητρικής τάξης CDataExchange(). Αυτά
φαίνονται από το Class Tab του περιβάλλοντος της Visual C++.
Στη συνέχεια περιγράφεται η διαδικασία με την οποία ο χρήστης μπορεί να προσθέσει μια
δική του εικόνα στο about dialog box. Στη καρτέλα Resource View στο παράθυρο χώρου
εργασίας ο χρήστης κάνει δεξί κλικ στο IDD_ABOUTBOX, Insert, bitmap, import και
επιλέγει με τον browser η εικόνα που θέλει (.bmp) ή δημιουργεί ο ίδιος μια εικόνα. Στο
ResourceView, Bitmap εμφανίζεται το ID της εικόνας (IDB_BITMAP1). Διπλό κλικ στο
IDD_ABOUTBOX, στο εικονίδιο που βρίσκεται η ζωγραφιά, δεξί κλικ και επιλέγεται
properties. Οι properties της εικόνας πρέπει να έχουν : ID: IDB_BITMAP1, Type: Bitmap
και Image: IDB_BITMAP1. Το αποτέλεσμα φαίνεται παρακάτω.
38
ΚΕΦΑΛΑΙΟ 2
Insert box
Το πρώτο βήμα στην προσθήκη ενός παραθύρου διαλόγου στην παρούσα εφαρμογή είναι
η δημιουργία του παραθύρου διαλόγου, που ενεργεί ως ένα είδος προτύπου για τα Windows.
Όταν τα Windows βλέπουν τον πόρο για το παράθυρο διαλόγου στο πρόγραμμα,
χρησιμοποιούν τις εντολές στον πόρο για να δομήσουν το παράθυρο διαλόγου για τον
χρήστη.
Τώρα θα δημιουργηθεί ένα dialog box για την εισαγωγή των δύο δεδομένων. Με δεξί
click στο dialog του Resource tab και επιλογή Insert Dialog-New δημιουργείται το καινούριο
dialog box. Από τα Properties (δεξί click πάνω στο νεοδημιουργημένο box) αλλάζει το ID σε
IDD_INSERTBOX και το caption σε "Insert user data".
Πρέπει να προστεθούν δύο static text και δύο edit box controls. Τα βρίσκουμε στο
πινακάκι δίπλα (αν δεν εμφανιστεί το πινακάκι controls ο χρήστης πηγαίνει στο toolbar την
Visual C++ και με δεξί click επιλέγει controls).
Μόλις τα τοποθετήσουμε στο box, με δεξί click και properties αλλάζουμε τις λέξεις static.
Τα static text είναι οι ετικέτες των edit boxes. Η ετικέτα του ενός θα είναι "String:" και του
άλλου "Number:". Χρησιμοποιώντας τις όποιες καλλιτεχνικές φλέβες, όλα τα controls (και τα
δύο buttons που ήδη υπήρχαν) τοποθετούνται όμορφα.
39
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
Μόλις είναι έτοιμη η ζωγραφιά, πρέπει να κατασκευαστεί η τάξη που θα αναλάβει το
dialog box. Για το σκοπό αυτό χρησιμοποιείται ο Class Wizard από το menu View ο οποίος
βοήθα να δημιουργηθεί μια τάξη παραθύρου διαλόγου, που τυπικά απορρέει από την τάξη
MFC CDialog και να συνδεθεί στον πόρο της τάξης. Συνήθως, κάθε στοιχείο ελέγχου στο
παράθυρο διαλόγου αντιστοιχεί σε μια μεταβλητή μέλος στην τάξη. Για να προβληθεί το
παράθυρο διαλόγου, καλείται μια συνάρτηση μέλος της τάξης. Για να οριστούν οι τιμές
στοιχείου ελέγχου στις προεπιλογές, πριν την προβολή του dialog box, ή για να καθοριστούν
οι τιμές των στοιχείων ελέγχου αφού τελειώσει ο χρήστης με το παράθυρο, χρησιμοποιούνται
οι μεταβλητές μέλη της τάξης. Εντοπίζεται αυτόματα το νέο resource και ο πρόθυμος μάγος
προτείνει να φτιάξει μία νέα τάξη που θα χειρίζεται το παράθυρο διαλόγου. Έτσι, Create new
class και ΟΚ. Εμφανίζεται το παράθυρο διαλόγου New Class δίνεται το όνομα CInsDialog
και οι υπόλοιπες επιλογές μένουν όπως έχουν έτσι ώστε η νέα τάξη να παραχθεί από την
CDialog. Ο Class Wizard δημιουργεί μια νέα τάξη, προετοιμάζει το αρχείο πηγαίου κώδικα
(InsDialog.cpp) και το αρχείο επικεφαλίδων (InsDialog.h) και τα προσθέτει στην εργασία.
Για να γίνει ο χειρισμός των edit boxes πρέπει να συνδεθούν με αυτά κάποιες member
μεταβλητές. Στο Member variables tab θα συνδεθούν τα IDC_EDIT1 και IDC_EDIT2
controls με τις μεταβλητές m_s για το string και m_n για τον αριθμό. Γίνεται διπλό click στο
όνομα του control και συμπληρώνεται το όνομα της μεταβλητής. Επιλέγεται Value στο
αναπτυσσόμενο πλαίσιο Category και στο Variable type επιλέγεται CString για τη μεταβλητή
m_s και double για την m_n. Ο χρήστης κάνει κλικ στο OK και η σύνδεση ολοκληρώνεται.
Περισσότερες πληροφορίες για πιο σύνθετα dialog boxes βρίσκονται στο [1].
Controls Variable name Variable Type Category Meaning
IDC_EDIT1 m_s CString Value string
IDC_EDIT2 m_n double Value numberΠΙΝΑΚΑΣ 1: Σύνδεση των στοιχείων του παραθύρου Insert user data
40
ΚΕΦΑΛΑΙΟ 2
4. Τροποποιήσεις στην Document classΤο να δημιουργούνται πράγματα χωρίς να γράφεται κώδικας είναι ευχάριστο, και στον
προγραμματισμό σε Windows μπορεί να γίνει συνήθεια. Η Visual C++ είναι ότι καλύτερο
έχει να παρουσιάσει η Microsoft και βοηθάει σε αυτό.
Για να δημιουργηθεί μια εφαρμογή που να κάνει περισσότερα, από το να φαίνεται ωραία
στην επιφάνεια εργασίας, χρειάζεται να τροποποιηθεί ο κώδικας που έχει δημιουργήσει ο
AppWizard. Η εργασία αυτή μπορεί να είναι εύκολη ή πολύπλοκη, ανάλογα με τον τρόπο με
τον οποίο θέλει ο χρήστης να εμφανίζεται και να ενεργεί η εφαρμογή του. Στο στάδιο αυτό
αρχίζει ο προγραμματισμός.
Στην παράγραφο αυτή θα εμπλουτιστούν οι τάξεις CInsDialog και η CMyDrawDoc που
είναι η Document τάξη της εφαρμογής. Σκοπός είναι όταν ο χρήστης επιλέγει Edit, Insert data
θα πρέπει να προβάλλεται το παράθυρο διαλόγου Insert Data, να γίνεται η εισαγωγή των
δεδομένων και να γνωστοποιούνται οι τιμές τους στο πρόγραμμα.
Document τάξη
Η CMyDrawDoc πρέπει να έχει δύο member μεταβλητές, μία για το string και μία για τον
αριθμό. Από το Class tab και με δεξί click στο όνομα της τάξης επιλέγεται το Add member
variable. Η μία είναι CString με όνομα str και η άλλη double με όνομα num. Και οι δύο είναι
public, κατά παράβαση των συνηθισμένων, για να μη χρειάζεται να γραφεί member
συνάρτηση που απλά να δίνει προς τα έξω τις τιμές. Τώρα χρειάζεται να δοθούν οι
κατάλληλες αρχικές τιμές σε αυτές τις μεταβλητές. Αυτό θα γίνεται κάθε φορά που
δημιουργείται ένα νέο document. Τότε καλείται η συνάρτηση μέλος OnNewDocument() της
τάξης εγγράφου και δίνονται αρχικές τιμές στις μεταβλητές μέλη. Με διπλό click στο όνομά
της από το Class tab εμφανίζεται ο κώδικας της. Προστίθενται οι δύο γραμμές αρχικοποίησης
μετά το σχόλιο // TODO: add reinitialization code here
num=0;str="";
Επίσης, η CMyDrawDoc πρέπει να συλλάβει το μήνυμα ότι επιλέχθηκε από το Edit το
παράθυρο διαλόγου Insert data από το menu. Πάλι ο Class Wizard θα κάνει τη δουλειά. Από
το Message maps tab επιλέγεται η CMyDrawDoc. Από τα Object IDs επιλέγεται το
ID_EDIT_INSERT που είναι το ID της εντολής που προστέθηκε στο menu. Από τα
διαθέσιμα Messages επιλέγεται το Command. Μόνο δυο μηνύματα συσχετίζονται με κάθε ID
41
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
πόρου COMMAND και COMMAND_UI. Το πρώτο δίνει τη δυνατότητα στο χρήστη να
προσθέσει μια συνάρτηση για το χειρισμό της επιλογής στοιχείου μενού από τον χρήστη ή
του κλικ σε ένα κουμπί δηλαδή, για να πιάσει την εντολή. Το δεύτερο δίνει την δυνατότητα
να προσθέσει μια συνάρτηση για να ορίσει την κατάσταση του στοιχείου μενού, του
κουμπιού, ή άλλου στοιχείου ελέγχου, ακριβώς όπως πρόκειται να το προβάλλει το
λειτουργικό σύστημα-δηλαδή, για να ενημερώσει την εντολή. Αν οι εντολές είναι σε έντονη
γραφή (Bold) αυτό σημαίνει ότι ήδη συλλαμβάνεται αυτή η εντολή.
Κάνοντας κλικ ο χρήστης στο Add Function για να προσθέσει μια συνάρτηση που να
συλλαμβάνει ή να ενημερώνει μια εντολή, εμπλέκει ένα πρόσθετο βήμα. Ο ClassWizard δίνει
μια ευκαιρία να αλλαχτεί το προεπιλεγμένο όνομα συνάρτησης. Αυτό δεν είναι σχεδόν ποτέ
κατάλληλο. Υπάρχει ένα κανονικό πρότυπο για τα προτεινόμενα ονόματα και οι
προγραμματιστές MFC υπολογίζουν τα ονόματα συναρτήσεων που έπονται αυτού του
προτύπου. Οι συναρτήσεις χειρισμού εντολών, όπως οι χειρισμοί μηνυμάτων, έχουν ονόματα
που αρχίζουν με το On. Τυπικά το υπόλοιπο του ονόματος της συνάρτησης διαμορφώνεται με
αφαίρεση του ID και των υπογραμμίσεων από το ID πόρου και με κεφαλαίο το πρώτο
γράμμα κάθε λέξης. Οι χειρισμοί ενημέρωσης εντολών έχουν ονόματα που αρχίζουν με
OnUpdate και χρησιμοποιούν τις ίδιες συμβάσεις με τα ονόματα των υπολοίπων
συναρτήσεων. Για παράδειγμα, η συνάρτηση που πιάνει το ID_APP_EXIT θα πρέπει να
ονομάζεται OnAppExit() και η συνάρτηση που ενημερώνει το ID_APP_EXIT θα πρέπει να
ονομάζεται OnUpdateAppExit(). Επομένως με την Add Function προστίθεται μία member
συνάρτηση που διαχειρίζεται τη συγκεκριμένη εντολή. Το προτεινόμενο όνομα OnEditInsert
είναι καλό και δεν υπάρχει λόγος να αλλάξει. Με Edit code το περιβάλλον μεταφέρει το
χρήστη στο σημείο που θα πρέπει να εισαχθεί κώδικας για τη συνάρτηση αυτή (αμέσως μετά
το TODO σχόλιο).
42
ΚΕΦΑΛΑΙΟ 2
#include “InsDialog.h” // στην αρχή του αρχείου mydrawDoc.cppvoid CMydrawDoc::OnEditInsert(){// TODO: Add your command handler code hereCInsDialogdlg;dlg.m_n = num;dlg.m_s = str;if(dlg.DoModal() == IDOK){str = dlg.m_s;num = dlg.m_n;SetModifiedFlag();UpdateAllViews(NULL);}}
Χρήση του dialog box
Η πρώτη δουλειά της συνάρτησης OnEditInsert() όπως φαίνεται από τον παραπάνω κώδικα
είναι να ορίσει ένα αντικείμενο της τάξης CΙnsDialog. Έπειτα αρχικοποιούνται οι δύο
member μεταβλητές, παίρνοντας τιμές από τα δεδομένα του προγράμματος που βρίσκονται
στην Document τάξη. Όταν εισάγεται κώδικας σε αυτό το σημείο ο χρήστης επωφελείται από
ένα χαρακτηριστικό της Visual C++: την αυτόματη συμπλήρωση. Ο χρήστης δεν είναι
υποχρεωμένος να θυμάται όλες τις μεταβλητές μέλη και τις συναρτήσεις κάθε τάξης, αφού
πληκτρολογώντας dlg εμφανίζεται ένα παράθυρο το οποίο συμπεριλαμβάνει όλες τις
μεταβλητές μέλη και συναρτήσεις της τάξης CΙnsDialog. Στη συνέχεια πρέπει να κληθεί η
DoModal() για να σχεδιαστεί το dialog box και να φροντιστούν οι χειρισμοί του χρήστη. Το
παράθυρο διαλόγου προβάλλει στην οθόνη καλώντας την συνάρτηση DoModal(), η οποία
επιστρέφει έναν αριθμό που αναπαρίσταται από το IDOK. Αν επιλεγεί το ΟΚ, τότε θα πρέπει
να αλλάξουν τα δεδομένα, να ενημερωθεί η τάξη ότι άλλαξαν (για save), και να ενημερωθεί η
view τάξη για την επανασχεδίαση του παραθύρου. Η ενημέρωση και η επανασχεδίαση του
παραθύρου γίνεται με την κλήση των συναρτήσεων SetModifiedFlag() και
UpdateAllViews(NULL) αντίστοιχα.
Τέλος, ο compiler πρέπει να ενημερωθεί για το τι είναι η τάξη CInsDialog και να την
κάνει compile. Αυτό επιτυγχάνεται με την ενσωμάτωση του κατάλληλου header που έχει
δημιουργηθεί αυτόματα. Έτσι στην αρχή του αρχείου, μαζί με τα υπόλοιπα #include
προστίθεται η: #include "InsDialog.h". Τώρα πια το πρόγραμμα κάνει κάτι. Με build και
execute φαίνεται τι ακριβώς κάνει.
43
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
Εικόνα 6: SDI εφαρμογή
Απεικονίζεται το Insert User Data dialog box όπου ο χρήστης εισάγει ένα string και ένα
number, ωστόσο το πρόγραμμα δεν έχει την δυνατότητα απεικόνισης των αποτελεσμάτων
στην οθόνη ούτε την αποθήκευση αυτών.
Προσοχή πρέπει να δοθεί στο ότι τη δεύτερη φορά που καλείται το dialog box έχει πράγματι
τα δεδομένα που είχαν εισαχθεί την πρώτη φορά, και ότι κατά την έξοδο από το πρόγραμμα,
ο χρήστης καλείται να αποθηκεύσει τα δεδομένα.
Αποθήκευση και φόρτωση δεδομένων
Μια από τις σημαντικότερες λειτουργίες ενός προγράμματος είναι η αποθήκευση των
δεδομένων του χρήστη. Ο AppWizard για την δημιουργία μιας εφαρμογής παρέχει μεγάλο
μέρος του αναγκαίου κώδικα για την αποθήκευση και φόρτωση των δεδομένων. Ωστόσο ο
χρήστης καλείται να προσθέσει κώδικα ο ίδιος ώστε να έχει την δυνατότητα ενημέρωσης των
αρχείων του.
Οι διαδικασίες της αποθήκευσης και φόρτωσης γίνονται μέσω της Serialize(). Ορίζονται
οι τελεστές >> και << για την μεταβίβαση συμβολοσειρών σε και από μια αρχειοθήκη, η
διαδικασία αποθήκευσης και ανάκτησης των δεδομένων της τάξης εγγράφου γίνεται
αυτόματα απλή υπόθεση. Για την απλή περίπτωση του συγκεκριμένου προγράμματος, τα
μόνα που πρέπει να γίνουν, είναι να προστεθεί η εντολή αποθήκευσης και η αντίστοιχη
ανάγνωσης στα κατάλληλα σημεία της Serialize() (στα οποία οδηγείται ο προγραμματιστής
από τα σχόλια του Application Wizard)
44
ΚΕΦΑΛΑΙΟ 2
void CMydrawDoc::Serialize(CArchive& ar){
if (ar.IsStoring()){
// TODO: add storing code herear << num << str;
}else{
// TODO: add loading code herear >> num >> str;
}}
Μόνο με τις δύο αυτές γραμμές δουλεύει πλέον όλο το σύστημα Open, Save και Save As. Τα
απαραίτητα dialog boxes είναι κατασκευασμένα στην MFC βιβλιοθήκη.
5. Τροποποιήσεις στην View classΗ τάξη προβολής δίνει την δυνατότητα στο χρήστη να απεικονίζει τα δεδομένα στην
οθόνη και στη συνέχεια να τα επεξεργάζεται. Τα μηνύματα τα σχετικά με σχεδίαση
συλλαμβάνονται από τη View τάξη. Καλείται η OnPaint() και αυτή καλεί την OnDraw() με
όρισμα ένα δείκτη σε αντικείμενο από την τάξη DC. Αυτός ο δείκτης χρησιμοποιείται για να
είναι δυνατή η πρόσβαση στις member συναρτήσεις αυτής της τάξης που είναι απαραίτητες
για τη σχεδίαση. Οι συναρτήσεις που σχεδιάζουν στην οθόνη το κάνουν μέσω του γενικού
πλαισίου συσκευής (DC-device context). Ο προγραμματιστής ασχολείται μόνο με την
OnDraw(). Η OnDraw() κάνει την πραγματική εργασία της οπτικής αναπαράστασης του
εγγράφου. Στις περισσότερες περιπτώσεις θα γραφεί ο κώδικας της OnDraw() και η
OnPaint() δεν θα υποστεί καμία μεταβολή. Η απεικόνιση των δεδομένων πολλές φορές
απαιτεί γραφήματα. Εδώ η απεικόνιση θα γίνει με γράμματα. Φυσικά πρέπει να οριστούν τα
arrays χαρακτήρων str1 και str2. Αμέσως μετά πρέπει να ρυθμιστεί το LOGFONT structure.
Οι εντολές φαίνονται παρακάτω:
// TODO: add draw code for native data herechar str1[100], str2[50];LOGFONT lf;lf.lfHeight=16;lf.lfWidth=0;lf.lfEscapement=0;lf.lfOrientation=0;
lf.lfWeight=FW_NORMAL;lf.lfItalic=0;
45
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
lf.lfUnderline=0;lf.lfStrikeOut=0;lf.lfCharSet=ANSI_CHARSET; lf.lfOutPrecision=OUT_DEFAULT_PRECIS;lf.lfClipPrecision=CLIP_DEFAULT_PRECIS; lf.lfQuality=PROOF_QUALITY;lf.lfPitchAndFamily=VARIABLE_PITCH | FF_ROMAN;strcpy(lf.lfFaceName, "Times New Roman");CFont font, *oldFont;font.CreateFontIndirect(&lf);oldFont=pDC->SelectObject(&font);pDC->TextOut(10,0, "The data are:");strcpy(str1, "String: ");strcat(str1, pDoc->str);pDC->TextOut(50,16, str1);strcpy(str1, "Number: ");_gcvt(pDoc->num,8,str2);strcat(str1, str2);pDC->TextOut(50,32, str1);pDC->SelectObject(oldFont);
Μια γραμματοσειρά των Windows είναι μια δομή structure. Στη συνέχεια χρησιμοποιείται
structure για να δημιουργηθεί η νέα γραμματοσειρά (στη μεταβλητή font). Ορίζεται το ύψος
της γραμματοσειράς σε 16 pixels. Επίσης σώζεται και η υπάρχουσα γραμματοσειρά (στο
δείκτη oldFont) ώστε με το τέλος των εντολών σχεδιασμού να ξαναγίνει ενεργή. Η σχεδίαση
γίνεται με απεικόνιση strings στην οθόνη χρησιμοποιώντας την member συνάρτηση
TextOut() πάλι της DC. Τα δυο πρώτα ορίσματα της TextOut() είναι οι συντεταγμένες X και
Y στις οποίες θα προβληθεί το κείμενο. Το τρίτο όρισμα είναι το κείμενο που θα προβληθεί.
Η νέα γραμματοσειρά γίνεται ενεργή με την SelectObject(), member συνάρτηση της τάξης
DC
Τώρα το πρόγραμμα είναι ολοκληρωμένο και χτίζεται για τελευταία φορά, με build (F7)
και Execute Program (Ctrl+F5) .
46
ΚΕΦΑΛΑΙΟ 2
Εικόνα 7: Εφαρμογή SDI στην τελική της μορφή
Με την εφαρμογή που αναπτύχθηκε παραπάνω δίνεται στο χρήστη η δυνατότητα να εισάγει
κάποια δεδομένα, και να στη συνέχεια να τα αποθηκεύσει. Η συγκεκριμένη εφαρμογή είναι
μια απλή εφαρμογή, εναρκτήρια ωστόσο για αυτές που θα ακολουθήσουν. Σ’ αυτήν την
εφαρμογή μαθαίνουμε καλά τις τάξεις που χρησιμοποιεί ο AppWizard διότι θα μας
χρειαστούν και παρακάτω.
Αναφορά
[1]. Kate Gregory, “Special Edition Using Visual C++ 6”, 1998
6. Ανακεφαλαίωση της εφαρμογής 1
47
ΕΊΣΟΔΟΣ ΑΠΛΏΝ ΔΕΔΟΜΈΝΩΝ ΑΠΌ DIALOG BOX
48