Πέμπτη 11 Αυγούστου 2016

Εγχειρίδιο της Μ2000 - Τεύχος 29ο

Τελευταία ανανέωση σελίδας: 17 Φεβρουαρίου 2022

17. Αντικείμενα γραφικού περιβάλλοντος (GUI)  της Μ2000. 
Ο διερμηνευτής της Μ2000 είναι γραμμένος σε γλώσσα που δίνει την δυνατότητα χρήσης παραθύρων, που έχουν προκαθοριστεί με τα στοιχεία που θέλουμε πριν την μετάφραση σε εκτελέσιμο αρχείο. Έτσι δεν είναι δυνατόν να δώσει η Μ2000 τις φόρμες και τα στοιχεία της Visual Basic, καθώς και να φορτώνει "ξένα" στοιχεία (τύπου ocx,- Object Linking and Embedding (OLE) custom control - activeX δηλαδή). Μετά την ενσωμάτωση της χρήσης γεγονότων στη γλώσσα και επειδή όλα τα στοιχεία για τις σταθερές φόρμες (φόρμες διαλόγου που είχαν ήδη φτιαχτεί, με στατικό τρόπο) στηρίζονται σε ένα στοιχείο χρήστη (user control), βρέθηκε μια διέξοδος, που έδωσε πραγματικά φόρμες με στοιχεία που θα μπορούσε να ορίσει ο χρήστης καθώς τρέχει το εκτελέσιμο του διερμηνευτή. Το πρόβλημα που παλαιότερα δεν επέτρεπε να φτιαχτεί κάτι τέτοιο ήταν η ανάγνωση των γεγονότων από την γλώσσα. Αυτό λύθηκε με την ένταξη των γεγονότων (Events) στη γλώσσα. 

Πώς λειτουργεί το γραφικό περιβάλλον:

Ουσιαστικά κάθε φόρμα που φτιάχνουμε είναι  ένα αντίγραφο μιας φόρμας GuiM2000 (ο κώδικας της γλώσσας είναι διαθέσιμος και εδώ είναι ο κώδικας της βασικής φόρμας), και πάνω σε αυτήν υπάρχουν δυο στοιχεία, η επικεφαλίδα και ένα μικρό πλαίσιο για να τραβάμε τη φόρμα από την κάτω δεξιά γωνία. Η επικεφαλίδα είναι ένα στοιχείο glist το οποίο είναι και το μοναδικό user control που δίνει όλα τα πλαίσια διαλόγου της Μ2000 (όπως το πλαίσιο διαλόγου Ρυθμίσεις, ή το Έλεγχος), αλλά και το αντικείμενο επεξεργασίας κειμένου. Ουσιαστικά το glist πάνω στη φόρμα GuiM2000 μπορεί να φορτωθεί πολλές φορές. Με το παρακάτω παράδειγμα μπαίνει κανείς στο νόημα:

Αν έχουμε μια φόρμα ΑΛΦΑ (δώσαμε αυτό το όνομα με την Όρισε) και θέλουμε να βάλουμε ένα στοιχείο Πλήκτρο (Button), τότε ένα νέο στοιχείο glist φορτώνεται σε μια φόρμα GuiM2000 (ξέρουμε ποια φόρμα είναι, γιατί το όνομα ΑΛΦΑ είναι αναφορά στη φόρμα) και σε ένα νέο αντικείμενο GuiButton παρέχεται η αναφορά στο στοιχείο glist και μια αναφορά στη φόρμα με όνομα Callback, και επιπλέον υπάρχει αντίστροφη σύνδεση, από τη φόρμα στα εξωτερικά αντικείμενα, όπως το GuiButton, στο GuiControls της φόρμας, μια συλλογή (λίστα) στο GuiM2000, όπου προστίθεται μια αναφορά για το GuiButton του παραδείγματος, (το οποίο δεν  είναι Gui στοιχείο, αλλά κάνει sub classing το glist, δηλαδή παίρνει αυτό τα γεγονότα που παράγει το στοιχείο, και τα προωθεί στο πρόγραμμά μας, επειδή έχει όλα τα στοιχεία). Όταν κάνουμε κλικ στο glist (το πραγματικό αντικείμενο) τότε το σήμα πάει στο GuiButton  και αυτό καλεί την μέθοδο CallBack του αντικειμένου CallBack (είναι η αναφορά στο GuiM2000 μέσα στο GuiButton). Η μέθοδος CallBack ανήκει στο GuiM2000 και το μήνυμα πηγαίνει εκεί (στο τμήμα) που έχει οριστεί η φόρμα με την εντολή Όρισε. Αν η φόρμα καταστραφεί, με unload, ή όταν ορίσουμε  να είναι "τίποτα", τότε αποδεσμεύονται οι αναφορές μεταξύ στοιχείων γραφικών glist και GuiM2000 και του στοιχείου GuiButton. Για το λόγο αυτό χρησιμοποιείται η λίστα GuiControls στην φόρμα GuiM2000 η οποία έχει αναφορές στο GuiButton, και σε κάθε στοιχείο καλεί τη μέθοδο deconstruct. Τα αντικείμενα αυτά "πεθαίνουν" όταν δεν υπάρχει ούτε ένας δείκτης να τα κρατάει “εν ζωή”. 

Αν δει κανείς το κώδικα του διερμηνευτή θα δει ότι οι φόρμες GuiM2000 είναι πιο πολύπλοκες από την παραπάνω περιγραφή και αυτό συμβαίνει γιατί πρέπει να εξυπηρετούν ορισμένους σκοπούς όπως την διαδοχική (πολυεπίπεδη) χρήση Modals (modal είναι η φόρμα που ανοίγει ενώ κάνει μη προσβάσιμες τις άλλες φόρμες που είναι προσβάσιμες μέχρι στη στιγμή εκείνη, μέχρι να κλείσει).
Επίσης η πολυπλοκότητα υπάρχει και σε άλλο επίπεδο: Μπορούμε να έχουμε πίνακες με φόρμες, που σημαίνει ότι τα μηνύματα από φόρμες γυρίζουν και τον αριθμό φόρμας. Και επειδή μπορούμε να έχουμε και πίνακες με στοιχεία, και πίνακες με φόρμες, μπορούμε να έχουμε με μια συνάρτηση εξυπηρέτηση γεγονότος μια εξυπηρέτηση για πολλές φόρμες και πολλά στοιχεία στη κάθε φόρμα. (Στη Visual Basic 6 δεν έχουμε πίνακες φορμών, μόνο πίνακες στοιχείων, αλλά εδώ γίνεται αφού υπάρχει προσθήκη λογικής για να διαχειρίζεται αυτό το ζήτημα).

Τα μηνύματα από τη φόρμα GuiM2000 μπορούν να είναι απλά μιας εκπομπής, ή αν χρησιμοποιούμε ειδικό στοιχείο γεγονός να είναι πολλαπλής εκπομπής (multicast), και τα δύο όμως δεν επιστρέφουν τιμές στο αντικείμενο, που έστειλε τα μηνύματα.  Υπάρχουν όμως μηνύματα για το GuiM2000 που δεν εκτελούνται με τον "απλό" τρόπο αλλά με άλλο ξεχωριστό κανάλι, κλήσεων (CallBackNow) ο οποίος περνάει by reference (μέθοδος copy in - copy out) τις τιμές.

Μια διαφορά με άλλα συστήματα για γεγονότα είναι ότι δεν χρειάζεται να γνωρίζει ο διερμηνευτής ποια γεγονότα θα εξυπηρετήσουμε. Για όλα τα γεγονότα υπάρχει εκπομπή, και αν δεν υπάρχει ανταπόκριση τότε το μήνυμα χάνεται (διαγράφεται). Με την χρήση του απλού τρόπου μπορούμε να μαζεύουμε τα μηνύματα για να τα ικανοποιήσουμε πιο μετά!  Ο άμεσος τρόπος (CallBackNow) δεν μπορεί να "μαζευτεί" αλλά αν έχουμε ανταπόκριση (συνάρτηση με το όνομα της φόρμας και το όνομα_μηνύματος) τότε θα έχουμε επιστροφή κατάστασης διαφορετικής από την "τωρινή" (δηλαδή αυτή που περιγράφουν οι τιμές που συνοδεύουν το μήνυμα).

Στις τελευταίες εκδόσεις υπάρχει ένα σύστημα που κοιτάει αν εξυπηρετήθηκαν γεγονότα, και αν όχι τότε τα αφαιρεί βάζοντάς τα σε μια black list. Αυτή η black list καθαρίζει κάθε φορά που έρχεται στο προσκήνιο η φόρμα. Ουσιαστικά δεν χάνουμε τίποτα με το καθαρισμό, γιατί πολύ γρήγορα ξαναγράφεται η λίστα και δεν γίνονται άσκοπες κλήσεις. Όμως ο καθαρισμός είναι βασικός, αφού δεν γίνεται "καταχώρηση" γεγονότος προκαταβολικά, και υπάρχει η περίπτωση να έχουμε δημιουργήσει φόρμα και στοιχεία ελέγχου πριν ορίσουμε τις συναρτήσεις για τα γεγονότα, και πριν έρθει στο προσκήνιο η φόρμα, να στείλει μηνύματα. Χωρίς το καθαρισμό της black list, θα είχαμε μη εξυπηρετούμενα γεγονότα, ενώ θα θέλαμε να τα εξυπηρετήσουμε!


Μπορούν να εμφανίζονται αρκετές φόρμες και μπορούν να τρέχουν και νήματα στο περιθώριο. Υπάρχει παράδειγμα με τριάντα παράθυρα και αυτόματη χάραξη γραμμών σε κάθε παράθυρο από νήματα, η οποία συνεχίζεται καθώς μετακινούμε ή φέρνουμε στο προσκήνιο κάποιο παράθυρο.




Στην έκδοση 11, υπάρχει επιπλέον το IMAGE στοιχείο ελέγχου που δεν είναι glist τύπος, αλλά VB.Picturebox. Και αυτό το στοιχείο έχει ένα αντικείμενο που παίρνει τα γεγονότα και τα στέλνει στο πρόγραμμά μας. Το αντικείμενο (widget) αυτό το ορίζουμε με την Όρισε ως IMAGE ή Εικόνα. Επίσης και αυτό γράφεται στο GuiContols της φόρμας τύπου GuiM2000. Το στοιχείο αυτό παρέχει μόνο Layer ή Επίπεδο για να το χρησιμοποίησουμε για εξαγωγή γραφικών (εικόνες και σχέδια), αλλά και κειμένου, καθώς επίσης για να χρησιμοποιηθεί ως κονσόλα εισαγωγής. Οι παλιότερες εκδόσεις της γλώσσας δεν είχαν αυτή τη δυνατότητα. Η εισαγωγή γίνοταν με τα  EDITBOX (Κείμενο), TEXTBOX (Εισαγωγή), LISTBOX.(Λίστα), καθώς και με χρήση γεγονότων στη φόρμα. Στην Εικόνα, εμφανίζεται όταν θέλουμε ο δρομέας σε θέση χαρακτήρα, και έτσι δίνουμε την αίσθηση της εισαγωγής. Το πώς και που θα εμφανίσουμε την εισαγωγή είναι θέμα προγραμματισμού, δεν γίνεται αυτόματα. Υπάρχει παράδειγμα που κάνουμε εισαγωγή χωρίς όριο σε μια γραμμή (η Εικόνα έχει έναν αριθμό γραμμών και έναν αριθμό χαρακτήρων ανά γραμμή). Όταν η γραμμή που γράφουμε είναι μεγαλύτερη σε χαρακτήρες από το πλάτος γραμμής σε χαρακτήρες κανονικά αλλάζει γραμμή (ή γίνεται ολίσθηση αν είμαστε στην τελευταία), αλλά κατά την εισαγωγή δεν το θέλουμε αυτό (στο παράδειγμα) οπότε κάνουμε ολίσθηση οριζόντια μόνο στη γραμμή, με το τρόπο που δείχνει το παράδειγμα (όχι έτοιμο στο στοιχείο, αλλά με κατάλληλο προγραμματισμό στη γλώσσα Μ2000).

Το στοιχείο Εικόνα μπορεί να χρησιμοποιηθεί χωρίς να παίρνει εστίαση (να μην μεταφέρεται η εστίαση σε αυτό όταν πατάμε τα Tab ή Shift Tab). Ο λόγος που δεν θέλουμε την εστίαση είναι επειδή μας ενδιαφέρει να δείχνουμε εικόνα ως ένα τύπο ετικέτας.

Επίσης και αυτό είναι αρκετά ενδιαφέρον, η Εικόνα μπορεί να χρησιμοποιηθεί για να περιέχει άλλα στοιχεία. Πριν την έκδοση 11 (εκτός από τις τελευταίες αναθεωρήσεις της 10), δεν υπήρχε δυνατότητα να έχουμε ομάδες στοιχείων ελέγχου, εκτός από την ειδική σύνδεση στοιχείων COMBOBOX ή Λίστα.Εισαγωγής για μενού (για να δουλεύουν τα βελάκια που επιλέγουμε επόμενο προηγούμενο μενού). Όταν ορίζουμε ένα στοιχείο λέμε σε ποια φόρμα θα είναι και μπορούμε να προσθέσουμε το Εικόνα και το όνομα της εικόνας πάνω στο οποίο θα είναι. Με το τρόπο αυτό φτιάχνουμε καρτέλες με στοιχεία που όλα μαζί μπορούν να κρυφτούν με μια εντολή visible. Όταν δεν θέλουμε να εμφανιστεί μια καρτέλα (εικόνα) στο άνοιγμα της φόρμας τότε δεν αρκεί το Visible για να δώσουμε false, αλλά πρέπει να έχουμε το Locked  false (έτσι δουλεύουν και τα άλλα στοιχεία). Το Enable στην Εικόνα το κάνει να δέχεται εστίαση ή όχι. Τα στοιχεία που βάζουμε πάνω (εκτός από το Checkbox ή Επιλογή που δεν έχει διαφάνεια) μπορούν να έχουν διαφάνεια η οποία δείχνει την εικόνα και όχι τη φόρμα. Τα στοιχεία θα έχουν το 0,0 στην πάνω αριστερή γωνία της εικόνας.

Τέλος η Εικόνα μπορεί να διαθέτει όπως και η φόρμα στόχους, δηλαδή πλαίσια τα οποία δεν αποτελούν πραγματικά στοιχεία ελέγχου αλλά προγραμματιστικά, και έτσι έχουν λιγότερους πόρους, και επίσης δεν παίρνουν εστίαση - δηλαδή μπορούν μόνο να μεταφέρουν μήνυμα ότι έγινε κλικ από το ποντίκι. Οι στόχοι στην Κονσόλα, στο Περιθώριο και στα 32 επίπεδα πάνω στη κονσόλα λειτουργούν μόνο με την Σάρωσε όταν θέλουμε, ενώ στις φόρμες και στις εικόνες πάνω στις φόρμες λειτουργούν συνέχεια (μπορούμε να βγάζουμε εκτός όποιο θέλουμε). Επίσης μπορούμε οποιαδήποτε στιγμή να καθαρίσουμε τους στόχους και να φτιάξουμε νέους. Προς το παρόν η 11 και οι προηγούμενες εκδόσεις δεν αφαιρούν στοιχεία (η αφαίρεση γίνεται όταν καταργηθεί η φόρμα, στο πέρας εκτέλεσης του τμήματος που τη δημιουργήσαμε). Οι στόχοι σχηματίζονται με συντεταγμένες για χαρακτήρες.  Μπορούμε σε μια εικόνα να επιλέξουμε μέγεθος χαρακτήρων. Επίσης οι στόχοι εκτός από γράμματα μπορούν να εμφανίζουν εικόνα ή εικόνα και γράμματα. Επίσης οι στόχοι μπορούν να εμφανίζουν ιστόγραμμα οριζόντιο ή κάθετο (με αλλαγή μιας τιμής έχουμε άμεση εμφάνιση στο στόχο του ιστογράμματος).

Η Μ2000 υποστηρίζει πίνακες φορμών και πίνακες στοιχείων. Αυτό σημαίνει ότι τα γεγονότα όταν καλούν τις συναρτήσεις εξυπηρέτησης δίνουν επιπλέον το νούμερο (δείκτη) στοιχείου όταν το στοιχείο ανήκει σε πίνακα στοιχείων. Οι πίνακες μπορούν να αυξηθούν σε μήκος, δηλαδή μπορούμε να προσθέσουμε στοιχεία. Υπάρχει ένα όριο 254 ονομάτων στοιχείων στη φόρμα (στη Μ2000 όλα τα στοιχεία εσωτερικά είναι με όνομα, δηλαδή δεν είναι πραγματικά στοιχεία πίνακα). Το όριο μπαίνει από την VB6 (που έχει γραφτεί η Μ2000). Δεν υπάρχει λόγος να έχουμε τόσα στοιχεία πάνω σε μια φόρμα. Με χρήση των στόχων έχουμε όσα στοιχεία, είτε για ένα "κλικ" είτε για ένα κείμενο που αλλάζει είτε για ένα ιστόγραμμα! 




17.1.  Φόρμες Χρήστη

Οι φόρμες χρήστη, είναι παράθυρα που δημιουργεί ο χρήστης, και έχουν τα παρακάτω βασικά χαρακτηριστικά:

  • Τίτλο  (Ιδιότητα "Title"). Το πλαίσιο του τίτλου μετακινεί το παράθυρο αν με το ποντίκι κρατήσουμε πατημένο το αριστερό πλήκτρο. Η πάνω αριστερή γωνία δεν μπορεί να βγει εκτός επιφάνειας εργασίας. Στο πλαίσιο αυτό υπάρχει αριστερά το πλαίσιο για το κλείσιμο (απόκρυψη) του παραθύρου. Όταν επιλέγουμε ένα παράθυρο τότε εμφανίζεται ο τίτλος ως τίτλος της εφαρμογής. Αν ο τίτλος δεν χωράει στο πλάτος του πλαισίου του, τότε αναδιπλώνει όσες γραμμές χρειάζεται αλλά δεν μεγαλώνει το πλαίσιο. Μπορούμε να αλλάξουμε μέγεθος γραμμάτων στο τίτλο, και να μεγαλώσουμε το πλαίσιό του (θα δούμε παράδειγμα σε αυτό). Υπάρχει τρόπος να επιλέξουμε το αντικείμενο του πλαισίου του τίτλου και να το "εξαφανίσουμε".
  • Επίπεδο. Είναι η επιφάνεια κάτω από το πλαίσιο, η οποία μπορεί να χρησιμοποιηθεί ως οθόνη και έχει δυνατότητα για χωριστή οθόνη (το κάτω μέρος να κάνει ολίσθηση, scroll), χωρίς να κρατάει στοιχεία που χάνονται στην ολίσθηση. Όλες οι εντολές γραφικών λειτουργούν (εκτός από τα hardware sprites, γιατί αυτά υπάρχουν μόνο για την κονσόλα, το επίπεδο πίσω από τα παράθυρα, το οποίο μπορούμε να το έχουμε φανερό ή όχι). Επίσης δεν επιτρέπονται οι εντολές για εισαγωγή. Για εισαγωγή τιμών χρησιμοποιούμε μόνο στοιχεία φορμών όπως θα δούμε παρακάτω. Με την εντολή Παράθυρο μπορούμε να δώσουμε το μέγεθος των γραμμάτων και το μέγεθος της φόρμας σε twips, μέσα από την εντολή επίπεδο. Και η εντολή φόρμα μπορεί να δώσει συγκεκριμένο αριθμό χαρακτήρων και γραμμών στη φόρμα χρήστη.
  • Μέγεθος Επιπέδου. Αν έχουμε επιλέξει την ιδιότητα "Resizable" να είναι αληθείς τότε είναι ενεργό ένα μικρό στοιχείο στην κάτω δεξιά γωνία, με το οποίο μπορούμε να αλλάξουμε μέγεθος στη φόρμα και να στείλουμε το γεγονός "Resize" ώστε να ετοιμάσουμε κατάλληλα το επίπεδο.
  • Διαφάνεια. Υπάρχει η μέθοδος"Opacity" η οποία αλλάζει την διαπερατότητα, αλλά επίσης δηλώνει και το χρώμα που θα είναι πάντα 100% διαπερατό.
  • Μέθοδος Εμφάνισης κατά τύπο Modal. Μπορούμε να επιλέξουμε την εμφάνιση της φόρμας με ταυτόχρονο πάγωμα των άλλων φορμών (μπορούν να ανανεώνουν στοιχεία, αλλά δεν μπορούμε να τα μετακινήσουμε ή να τα επιλέξουμε). Η μέθοδος εμφάνισης λέγεται "Show" και μια μη μηδενική τιμή δηλώνει ότι θα είναι Modal.
  • Μέθοδος μετακίνησης και μεγέθους. Μπορούμε με την μέθοδο "move" να μετακινήσουμε προγραμματιστικά την φόρμα μας και να δώσουμε (προαιρετικά) το μέγεθός της. (υπάρχει εξ ορισμού ένα μέγεθος, σε twips 8000 X 5000.
  • Μέθοδος για άμεσο κλείσιμο: "CloseNow".
  • Μέθοδος για ανανέωση όλων των στοιχείων: "RefreshALL"
  • Μέθοδος εμφάνισης: "Show". Καθορίζει το πώς θα εμφανιστεί μια φόρμα. (δες παραπάνω την αναφορά στο τύπο εμφάνισης Modal).
  • Μέθοδος για εμφάνιση όλων των στοιχείων: "ShowmeALL" (αν το οποιοδήποτε στοιχείο έχει την ιδιότητα enable αληθές τότε δίνει το σύστημα μια εντολή σχεδιασμού, αυτή η εντολή είναι μέρος της "Show"
  • Ιδιότητα που δείχνει αν είναι ορατή ή όχι η φόρμα: "Visible"
  • Ιδιότητα για το ύψος του τίτλου: "TitleHeight"
  • Μέθοδος για τη ρύθμιση γραμματοσειράς τίτλου: "FontAttr", δέχεται τρεις παραμέτρους, μια για τη γραμματοσειρά και προαιρετικά το μέγεθος και αν είναι φαρδιά ή όχι (εξ ορισμού είναι στην επιλογή Φαρδιά).
  • Μέθοδος για τη ρύθμιση γραμματοσειράς στοιχείων: "CtrlFontAttr" (ομοίως όπως το προηγούμενο)
  • Ιδιότητες για την γραμματοσειρά στα στοιχεία (μόνο ανάγνωση, για να δούμε τι έχουμε στα στοιχεία): "CtrlFontName", "CtrlFontsize", CtrlFontBold"
  • Άνοιγμα πρόσκαιρης φόρμας πάνω στη φόρμα με την μέθοδο "PopUp". Αν κάνουμε κλικ σε άλλη φόρμα ή στην αρχική τότε η φόρμα τύπου popup αυτόματα κλείνει. Παίρνει τρεις παραμέτρους, τη φόρμα που θα χρησιμοποιήσουμε ως Popup και δυο μεταβλητές για την θέση Χ και Υ του δείκτη την στιγμή που κάνουμε κλικ πάνω στη φόρμα (παράγεται γεγονός που μας δίνει αυτά τα στοιχεία καθώς και πιο πλήκτρο του δείκτη - ποντίκι- έχουμε πατήσει, αν έχουμε πατήσει).
  • Ιδιότητα για εμφάνιση του τίτλου και του πλαισίου για μετακίνηση: "Header", δέχεται αληθές ή ψευδές (true/false), και είναι και για ανάγνωση και για εγγραφή
Παράδειγμα με φόρμα που όταν κάνουμε κλικ εξαφανίζεται και εμφανίζεται διαδοχικά. Στο παράδειγμα μπορούμε να αφαιρέσουμε από τη πρώτη γραμμή το Γεγονός Ένα (ώστε να χρησιμοποιηθεί ένα αυτόματα αποδιδόμενο), καθώς και παρακάτω η συνάρτηση Μία και η εντολή Γεγονός που συνδέει αυτή τη συνάρτηση. Όταν βάζουμε ένα δικό μας αντικείμενο γεγονός τότε μπορούμε να παίρνουμε "ανάδραση" ή να επεκτείνουμε τον έλεγχο, αφού τα μηνύματα από τη φόρμα θα περάσουν από αυτή τη συνάρτηση. Εδώ να υπενθυμίσω ότι τα μηνύματα που δέχονται απάντηση/επιστροφή, (έχουν πέρασμα τιμών με αναφορά) δεν μπαίνουν από αυτό το γεγονός αλλά πάντα εκτελούνται με άμεσο τρόπο (δεν είναι φανερός στο χρήστη).

Στη φόρμα, στο παράδειγμα, δεν βάλαμε κάποιο στοιχείο ελέγχου. Όμως βλέπουμε τον τίτλο και το τετραγωνάκι αριστερά που κλείνει τη φόρμα (αυτό παράγει το μήνυμα Unload, και είναι άμεσο, δέχεται δηλαδή επιστροφή σε μια μεταβλητή οκ. Αν δεν είχαμε καμία χρήση του οκ στο τμήμα, τότε δεν θα υπήρχε θέμα με μια απλή Διάβασε. Αν όμως υπάρχει η οκ, τότε θα έχουμε θέμα επειδή δεν μπορούμε να αποδώσουμε νέα αναφορά σε μεταβλητή που ήδη δείχνει κάπου. Η χρήση της Διάβασε Νέο κάνει κάτι άλλο, δημιουργεί μια μεταβλητή οκ ακόμα και αν υπάρχει ήδη, και δίνει την αναφορά, και μόλις τερματίσει η συνάρτηση Απλό.unload διαγράφεται η τελευταία οκ, αυτή που δημιουργήθηκε. Να θυμίσω εδώ ότι ενώ στις κανονικές κλήσεις συναρτήσεων οι μεταβλητές σχετίζονται με τα ονόματα συναρτήσεων, σε αυτές που καλούνται από γεγονότα (αυτό το κάνει η συνάρτηση οκν$()) οι κλήσεις είναι σαν να έγιναν στο τμήμα, και για το λόγο αυτό μπορεί να προκύψει πρόβλημα, αν δεν χρησιμοποιήσουμε σωστά τις Διάβασε και τα ονόματα των μεταβλητών. 

Στην συνάρτηση Μία φαίνεται πως καλούμε μια συνάρτηση τοπικά, (η συνάρτηση μαζί με τα περιεχόμενα-παραμέτρους είναι σε αλφαριθμητικό). Εσωτερικά ο μεταφραστής αλλάζει το όνομα της συνάρτησης με το όνομα της Μία, το οποίο όμως έχει ήδη αλλάξει με μια εντολή Τμήμα που έβαλε στο κώδικα η συνάρτηση οκν$() στην εντολή Γεγονός όπου συνδέσαμε το γεγονός με την συνάρτηση! (Στα γεγονότα μπορούμε να συνδέουμε περισσότερες από μια συναρτήσεις, και αυτό είναι το λεγόμενο multicast)

Στο πρόγραμμα θέλω να φανεί το πώς συνδέουμε μια μεταβλητή με ένα αντικείμενο-ιδιότητα. Δηλαδή με την εντολή Με Απλό, "visible" ως ορατό δημιουργούμε ένα αντικείμενο propreference (έτσι ονομάζεται μέσα στο κώδικα της Μ2000 και έτσι εμφανίζεται ως τύπος) το οποίο συνδέει την ιδιότητα  ενός συγκεκριμένου αντικείμενου με ένα όνομα. Το αντικείμενο αυτό δεν δεσμεύει τη φόρμα λόγω της αναφοράς σε αυτήν, και για το λόγο αυτό μεσολαβεί για την χρήση της φόρμας. Η μεταβλητή ορατό δεν είναι μια απλή μεταβλητή, και δεν μπορούμε να την χειριστούμε ως απλή μεταβλητή, αλλά έχει την ιδιότητα της εγγραφής και της ανάγνωσης (αν πράγματι το παρέχει το αντικείμενο), και η γραφή γίνεται με το ίσον (ως αντικατάσταση τιμής) και η ανάγνωση απλά με το όνομα στο δεξί μέρος.

Όρισε Απλό Φόρμα Γεγονός Ένα
Επίπεδο Απλό {
      Διάστιχο 0 \\ 30, 60, ...
      Γραμματοσειρά "Arial Black"
      Παράθυρο 16, 8000,6000 \\ μέγεθος γραμμάτων, Χ, Υ σε twips
      \\ τα πραγματικά Χ και Υ θα είναι εδώ Χ.Σημεία και Υ.Σημεία
      \\ Η εντολή Παράθυρο κόβει ανάλογα για να κρατήσει το πλάτος όσο ακριβώς το κείμενο
      Οθόνη 1,0 \\ χρώμα όπως #AAFF22 ή Χρώμα(r,g,b), αριθμός χωρίσματος οθόνης
      Δρομέας 0, Ύψος Δια 2 \\ Ύψος Πλάτος είναι σε χαρακτήρες
      Αναφορά 2,"Hello World"
}
Μέθοδος Απλό, "Show"
Με Απλό , "visible" ως ορατό
\\ τα γεγονότα και οι μέθοδοι είναι σε μία γλώσσα, αγγλική
Συνάρτηση Απλό.Unload {
             Διάβασε Νέο &οκ
             οκ=Αληθές
}
Στη Κ=Ψευδές
Συνάρτηση Απλό.Click {
      Με Απλό, "Title", "Πάτα άλλη μια"
      Τύπωσε ορατό
      Αν Κ Τότε Πληκτρολόγιο "Α"
      Κ~
}
Συνάρτηση Μία {
      Διάβασε μνμ$
      Σημ 1 : Τύπωσε μνμ$
      Δες {Κάλεσε τοπικά μνμ$}
}
Γεγονός Ένα Νέο οκν$(&Μία())
Τύπωσε ορατό
α$=Κομ$ \\ περιμένει να πατήσουμε κάτι
Γεγονός Ένα Κράτησε \\ τώρα δεν ακούει
ορατό=Ψευδές
Τύπωσε ορατό
Για ι=1 εώς 10 {
      \\ δεν υποστηρίζει αυτό ορατό~
      \\ πρέπει να το δώσουμε κανονικά με ορατό = όχι ορατό
      \\ η ορατό είναι ειδικό αντικείμενο, που συνδέει ένα όνομα με μια ιδιότητα
      ορατό= όχι ορατό
      ανανέωση
      Αναμονή 500
}
Τύπωσε Τύπος$(ορατό)
Όρισε Απλό Τίποτα


Στο παρακάτω παράδειγμα δημιουργούμε μια απλή φόρμα με δυνατότητα να αλλάξουμε τις διαστάσεις της με το ποντίκι, από τη κάτω δεξιά γωνία:

Όρισε Απλό Φόρμα
Επίπεδο Απλό {
      Διάστιχο 0
      Γραμματοσειρά "Arial Black"
      Παράθυρο 16, 8000,6000
      Οθόνη 1,0
      Δρομέας 0, Ύψος Δια 2
      Αναφορά 2,"Γειά σου Κόσμε"
}
Με Απλό,"Sizable", Αληθές
Συνάρτηση Απλό.Resize {
      Επίπεδο Απλό {
            Τύπος 16
           
Οθόνη 1,0
            Οθόνη 1,0
            Δρομέας 0, Ύψος Δια 2
            Αναφορά 2,"Γειά σου Κόσμε"
      }
}
Μέθοδος Απλό, "Show",1
Όρισε Απλό Τίποτα


Δείτε επίσης ότι έχουμε ανοίξει τη φόρμα με τύπο modal (αυτό κάνει το 1 που δίνουμε στη "Show")

Αφού ολοκληρωθούν τα τεύχη για τα στοιχεία ελέγχου, θα υπάρξει ένα ακόμα που θα έχει όλα τα Γεγονότα, τις ιδιότητες και τις μεθόδους της φόρμας χρήστη (γιατί στην συνέχεια καθώς ετοιμάζω τα τεύχη έρχονται ιδέες και μπορεί να προσθέσω και άλλα). Άλλη λύση να μάθει κανείς τα επιπλέον γεγονότα είναι να διαβάσει το κώδικα της Μ2000. Επίσης το info αρχείο έχει πολλά παραδείγματα με χρήση γραφικού περιβάλλοντος.

Δυο προγράμματα, το καθένα τρέχει σε δικό του διερμηνευτή (μπορούμε να καλέσουμε προγράμματα με το ποντίκι, αν δηλώσουμε στο σύστημα να ανοίγουμε με το M2000.exe). Το ένα είναι ένα ρολόι με διαφάνεια (η κονσόλα έγινε στρογγυλή, και έχει και διαφάνεια!). Το άλλο είναι ένα σημειωματάριο, με τα χρώματα της Μ2000 για τα παράθυρα (το πορτοκαλί πλαίσιο). Φαίνονται και τα μενού επιλογής. Ο συγκεκριμένος επεξεργαστής κειμένου χρωματίζει διάφορες γλώσσες, εδώ είναι σε διαμόρφωση για Visual Basic και χωρίς χρώμα για απλό κείμενο. Έχει δυνατότητα να μετακινεί πολλές γραμμές μαζί αριστερά ή δεξιά (για να αφήνουμε περιθώριο), και βάζει αυτόματα εσοχή όταν έχουμε ήδη βάλει στη τρέχουσα γραμμή κατά την αλλαγή γραμμής. Επίσης έχει δυνατότητες εύρεσης και αλλαγής λέξεων, καταμέτρησης λέξεων και έχει και τρεις σελιδοδείκτες που λειτουργούν ανεξάρτητα από το αν εισάγουμε ή διαγράφουμε παραγράφους. Ο επεξεργαστής κειμένου είναι γραμμένος και αυτός από το συγγραφέα της Μ2000, από το στοιχείο χρήστη, το αντικείμενο Document (Έγγραφο), και το αντικείμενο GuiTextBox. (υπάρχει και δεύτερο αντικείμενο TextBox για τον διορθωτή τμημάτων, που λειτουργεί στην κονσόλα, και μια κύρια διαφορά είναι ότι αυτός έχει χρωματισμό μόνο για τη Μ2000 ενώ αυτός για τις φόρμες έχει δυνατότητες να ρυθμίζεται, και έχει ειδικές ρύθμισεις για να χρωματίζει κωδικα Μ2000, καθώς και html).

Στο αρχείο εγκατάστασης υπάρχει το info.gsb το οποίο έχει και το ρολόι και τέσσερις επεξεργαστές κώδικα, όπως για C# (cs), Μ2000 (m2000editor), HTML (htmlEditor), για το μάθημα της ΑΕΠΠ η ΓΛΩΣΣΑ (ΓΛΩΣΣΑ). σε παρενθέσεις τα ονόματα των τμημάτων στο info. (με F8 ξεκινάει ο m2000editor).






Όταν πρώτη φορά εγκαταστήσουμε τη γλώσσα, πάμε στη κονσόλα της (ξεκινάμε το m2000.exe) και γράφουμε στα αγγλικά (υπάρχουν και στα ελληνικά τα αντίστοιχα)
Dir Appdir$
Load Info
τώρα έχει ξεκινήσει το Info και έχει επιστρέψει ο τρέχον κατάλογος στο κατάλογο χρήστη.
Με F1 σώνουμε στο κατάλογο χρήστη
Αφού έχουμε σώσει στο κατάλογο χρήστη μπορούμε να δώσουμε το CLOCK το οποίο θα ξεκινήσει ένα δεύτερο διερμηνευτή της Μ2000, θα φορτώσει το Info χωρίς να εκτελεστούν οι εντολές εκτός από τους ορισμούς τμημάτων  και θα καλέσει το ρολόι. Έτσι το ρολόι βγαίνει σε δική του εκτέλεση. Για να κλείσει το ρολόι αφού το επιλέξουμε πατάμε διάστημα, ή με ctrl+F1 βλέπουμε τη βοήθεια). Μπορούμε να το μετακινήσουμε από το κέντρο του με το ποντίκι. Έχει ξυπνητήρι 12 ωρών το πολύ.

Τεχνικά θέματα:
Ενώ η Vb6 δεν χρησιμοποιούσε το ροδελάκι στο ποντίκι, εδώ στις φόρμες γίνεται χρήση, με ένα σύστημα που επινόησε ο συγγραφέας, αυτό της διαδοχής κυριότητας. Δηλαδή κάθε φορά που αλλάζουμε στοιχείο, ένα μοναδικό sub classing αλλάζει αντικείμενο, και ακολουθεί το τρέχον. Αυτό ήταν δυνατόν να γίνει επειδή όλα τα αντικείμενα είναι ίδια (είναι το glist) και αφού έχει φτιαχτεί από το συγγραφέα της γλώσσας έχει τα απαραίτητα γεγονότα για να υποστηρίξει αυτή τη λειτουργία. Επίσης το glist δεν έχει flickering, τρεμόπαιγμα, και αυτό φαίνεται ακόμα και με χιλιάδες γραμμές στον διορθωτή, τόσο στη κονσόλα όσο και στις φόρμες.

Στα buttons ή όπου έχουμε επιλογή πλαισίου σε στοιχείο ελέγχου κάτω από επικεφαλίδα (checkbox, listbox, combo με popup listbox) μπορούμε ή να δώσουμε κλικ (στο δεύτερο ακούει, το πρώτο είναι η επιλογή), ή να το τραβήξουμε δεξιά, με πατημένο το πλήκτρο επιλογής και να το αφήσουμε εντός του πλαισίου. 

Δεν υπάρχει χωριστό timer control. Οποιοδήποτε button μπορεί να γίνει και timer control.

Επειδή προ της εμφάνισης του GUI συστήματος η Μ2000 έφτιαχνε buttons ως TARGETS (στόχοι) στην κοσνόλα, φτιάχτηκε ένας τρόπος να βγαίνουν στόχοι και στην επιφάνεια της φόρμας. Η διαφορά των στόχων αυτόν είναι ότι ενεργοποιούν events - γεγονότα, και ότι δεν στηρίζονται σε πραγματικό User Control. Για το λόγο αυτό λειτουργούν με απλό κλικ (απευθείας). Η χρησιμότητά τους είναι διπλή αφενός ως πλήκτρα (ελαφριά έκδοση), αφετέρου ως ενδεικτικά δηλαδή να μην δουλεύουμε με τα γεγονότα (να μην ακούν δηλαδή), αλλά να αλλάζουμε το χρωματισμό τους σαν να είναι φωτεινές ενδείξεις (επειδή η Μ2000 έχει εντολή να αλλάζει τον χρωματισμό τους, γνωρίζοντας τα στοιχεία κατασκευής τους, με μια εντολή κάνουμε την αλλαγή).

Το παράδειγμα υπάρχει στο info ως FORMTARGET  (παράδειγμα με TARGET στην κοσνόλα υπάρχει ως WIND4)

Declare form1 Form
m=false
Module zz {
    \\ target call zz to own object
    \\ so we have to use Layer {} to send to console
    Layer {
        print "ok", timecount
        refresh
        }
    change A, text "ok"
}
Function form1.MouseDown {
    Stack
    refresh
}
Function form1.Target {
    \\ normal events executed to console
    \\ so we have to use Layer to redirect to Form1 layer
    Print "target:", number, A
    Refresh
    Layer Form1 {
        Target A, m
        if m then
            change A, back 2
        else
            change A, back 0
        end if
    }
    m~
}
Layer form1 {
    window 12, 12000, 8000
    form 32, 20
    motion.w; ' center window
    cls #333333, 0
    cursor 4, 4
    \\ we use immediate execution, in this module
    \\ so we call zz as this module (call local pass current scope to zz)
    target A, "call local zz", 10, 3, 2,15, 105, "press me"
    cursor 4, 8
    \\ 115 means 5 center, 10 use target event, 100 proportional font rendering
    target B,"z", 10, 3, 5,15, 115, "press me too"
}
Method form1,"show",1
Declare form1 nothing

Δευτέρα 8 Αυγούστου 2016

Γεια χαρά από Καναλλάκι Πρέβεζας

Συνεχίζω τις διακοπές για έναν ακόμα μήνα, και από Σεπτέμβριο ξεκινώ πάλι εργασία. Προς το παρόν γράφω το κεφάλαιο 17 για τις φόρμες (GUI) της Μ2000. Είναι πολύ κουραστικό θέμα και για το λόγο αυτό δεν δείχνω και πολύ ζήλο!
Οπότε καλό χειμώνα για όσους τέλειωσαν ή τελειώνουν με την άδεια και τα λέμε σύντομα!