Δευτέρα 31 Ιουλίου 2017

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

17.5 Λίστα (ListBox) 
Το στοιχείο Λίστα περιέχει γραμμές ή και έναν τίτλο. Μια λίστα μπορεί να κάνει χρήση ενός εσωτερικού πίνακα γραμμών ή με κατάλληλο προγραμματισμό να δέχεται στοιχεία απ΄έξω, πιθανόν από εξωτερικό πίνακα, ή άλλη δομή.


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

Ο εσωτερικός πίνακας γραμμών έχει δυνατότητα ταξινόμησης και αναζήτησης.

Σε μια λίστα ο δρομέας εμφανίζεται με έναν από τους τρεις τρόπους:
  • Προκαθορισμένος με αλλαγή χρώματος φόντου και γραμμάτων
  • Με αλλαγή χρωματισμού του κειμένου μόνο. Αυτό χρησιμοποιούμε όταν έχουμε διάφανο φόντο στο στοιχείο
  • Με δρομέα κάθετο (Caret) που αναβοσβήνει, για εισαγωγή κειμένου
Η κίνηση του δρομέα μεταξύ των στηλών γίνεται με τα βελάκια, με την μπάρα ολίσθησης που είναι κρυμμένη και εμφανίζεται όταν χρειάζεται, με τα Home/End/PageUp/PageDown. Με χρήση του shift και τα βελάκια ή όταν πάμε στις άκρες πάνω και κάτω μπαίνει η αυτόματη αλλαγή γραμμής, και ολισθαίνει η λίστα. Από το μέσον δεξιά της λίστας λειτουργεί και το τράβηγμα της λίστας, δηλαδή κρατάμε πατημένο το αριστερό πλήκτρο του ποντικιού και σπρώχνουμε τη γραμμή πάνω ή κάτω. Αν σταματήσουμε να σπρώχνουμε και κρατάμε ακόμα πατημένο το πλήκτρο του ποντικιού μπαίνει η αυτόματη ολίσθηση. Η διαφορά του τραβήγματος με την ολίσθηση με τα βελάκια (ή με το ροδελάκι του ποντικιού) είναι στο ότι με το τράβηγμα δεν αλλάζουμε το δρομέα, απλά αλλάζουμε τη θέαση της λίστας (αυτό ισχύει σε όλα τα στοιχεία της Μ2000, που δείχνουν πολλές γραμμές, ακόμα και στον διορθωτή τμημάτων και συναρτήσεων, και αυτός έχει το ίδιο στοιχείο εσωτερικά)

Υπάρχουν γεγονότα (Scroll και Click) που μας δείχνουν έμμεσα το περιεχόμενο της γραμμής (μας δίνουν τον αριθμό στοιχείου) κατά την κίνηση του δρομέα μεταξύ των γραμμών (δεν παράγεται όταν τραβάμε τις γραμμές)

Η επιλογή γραμμής μπορεί να γίνεται και με τράβηγμα της γραμμής δεξιά (και ρύθμιση μιας ιδιότητας και με τράβηγμα στα αριστερά). Υπάρχει γεγονός  (DblClick) που παράγεται όταν σε μια επιλεγμένη γραμμή δίνουμε κλικ με το ποντίκι, ή Enter, ή τράβηγμα δεξιά. Αυτό το γεγονός είναι διαφορετικό από την απλή επιλογή (σε μη επιλεγμένη γραμμή, έχουμε το Click ή το Scroll).

Με χρήση ιδιοτήτων και γεγονότων μπορούμε να συνδέσουμε λίστες τη μια δίπλα στην άλλη και κάθε τράβηγμα ή ολίσθηση σε μία να κάνει ολίσθηση στις διπλανές.

Έτσι πρακτικά η Λίστα γίνεται στήλη σε πίνακα λιστών. Αν συνδυαστούν οι προβαλόμενες λίστες με την δυνατότητα προβολής από εξωτερικό πίνακα τότε μπορούμε να ολισθαίνουν οριζόντια οι στήλες νοητά,  αλλάζοντας μόνο το πίνακα προβολής κάθε λίστας, χωρίς να χρειαζόμαστε επιπλέον στοιχεία, από τα αρχικά που τοποθετήσαμε στη φόρμα.


Γεγονότα
  • ValidList  με αναφορά περιεχόμενο$, θέση, στοιχείο
  • About παράγεται όταν πατάμε το Ctrl+F1
  • ListCount  με αναφορά μέγεθος_λίστας (όταν δώσουμε νούμερο, τότε δείχνει η λίστα ότι έχει τα στοιχεία που ορίσαμε, και μπορούμε να τα φορτώνουμε στο γεγονός External)
  • KeyDown με αναφορά κωδικός_πλήκτρου, θέση_ειδικών_πλήκτρων (shift, control, alt)
  • DblClick  γυρίζει δυο αριθμούς το στοιχείο και τη θέση αριστερά ή δεξιά (0 ή -1) που προκύπτει  ανάλογα το τράβηγμα (αν έχουμε ορίσει PanDouble ως αληθές, μπορούμε να σπρώχνουμε την γραμμή - στοιχείο- αριστερά, και παράγεται το DblClick με 0.  Επειδή αυτό το γεγονός βγαίνει και με Enter, μπορούμε να χρησιμοποιούμε το Shift μαζί με το Enter για να δίνουμε την κατεύθυνση αριστερά. Το ίδιο γίνεται και όταν κάνουμε κλικ με το ποντίκι και έχουμε πατημένο το Shift. Έχει βάση το 1 (το πρώτο στοιχείο είναι το 1)
  • External  με αναφορά  περιεχόμενο$  (δίνουμε το περιεχόμενο, όταν έχουμε την ιδιότητα External με τιμή Αληθής)
  • Unicode  με αναφορά  χαρακτήρας_unicode$
  • Move παίρνει δυο θέση Άριστερά, θέση Άνω και προαιρετικά Πλάτος και Ύψος (σε twips)
  • Scroll γυρίζει το στοιχείο (τον αριθμό του) - έχει βάση το 0 (το πρώτο στοιχείο είναι το 0)
  • Click γυρίζει το στοιχείο (τον αριθμό του) - έχει βάση το 0
  • Color  με αναφορά  χρώμα (είναι αρνητικός αριθμός, πχ το #FF0000 (κόκκινο) είναι το -255)
  • Ascii με αναφορά  χαρακτήρας_ascii   (είναι αριθμός) 
Ιδιότητες
  • Index  αριθμός  στοιχείου Λίστας όταν έχουμε πίνακα Λιστών
  • locked κλειδώνει τη λίστα
  • Εnabled με Ψευδές δεν παράγονται τα γεγονότα ValidList, ListCount, External, Color
  • Title  βάζει/διαβάζει μια γραμμή τίτλου
  • Linespace βάζει/διαβάζει το διάστιχο
  • List() δίνει ένα πίνακα για να βάζουμε και να διαβάζουμε τα στοιχεία της λίστας
  • ListIndex  βάζει/διαβάζει το επιλεγμένο
  • ListIndex2 βάζει μόνο το επιλεγμένο χωρίς επανασχεδιασμό της λίστας.
  • listcount διαβάζει τον αριθμό των στοιχείων στη λίστα
  • Text βάζει/διαβάζει τα στοιχεία σε μια ένα κείμενο με γραμμές.
  • External βάζει/διαβάζει και με τιμή Αληθές λειτουργεί η εξωτερική λίστα
  • DisplayLines  βάζει μόνο τον αριθμό των φανερών στοιχείων στη λίστα (υπολογίζει αυτόματα το διάστιχο)
  • Transparent βάζει μόνο, με Αληθές κάνει τη λίστα διάφανη (σε αυτό το στοιχείο δεν έχουμε μέθοδο αλλά ιδιότητα Transparent
  • Center βάζει μόνο, με Αληθές κάνει τα στοιχεία να είναι κεντραρισμένα στη γραμμή
  • Edit βάζει μόνο, με Αληθές κάνει τις γραμμές της λίστας να διορθώνονται από το χρήστη
  • ScrollTo βάζει μόνο, παίρνει τον αριθμό στοιχείου στη κορυφή της φανερής λίστας
  • ScrollFrom διαβάζει μόνο, δίνει τον αριθμό στοιχείου στη κορυφή της φανερής λίστας
  • ShowAlways βάζει μόνο, με Αληθές μένει το στοιχείο με άσπρο φόντο
  • Find(), διαβάζει μόνο δέχεται ως όρισμα ένα αλφαριθμητικό (μπορεί να έχει * στο τέλος), και κάνει αναζήτηση στην εσωτερική λίστα.
  • HideCaret διαβάζει μόνο,  με Αληθές κρύβει την επιλογή (χρήση με το γεγονός Coloe)
  • PanDouble διαβάζει μόνο, με Αληθές επιτρέπει και το τράβηγμα προς τα αριστερά.

Μέθοδοι
  • GetFocus δίνει εστίαση στο στοιχείο, βάσει ονόματος (ουσιαστικά κάνει ότι και η SetFocus)
  • SetFocus δίνει εστίαση στο στοιχείο, απευθείας στο στοιχείο στη φόρμα
  • Move δέχεται δυο ορίσματα συν δυο προεραιτικά, τα δυο πρώτα είναι η θέση στη φόρμα, τα left και top, και τα άλλα δυο είναι το πλάτος και ύψος του στοιχείου (σε twips).
  • FontAttr δέχεται ένα όρισμα με το όνομα γραμματοσειράς, και προαιρετικά δυο ακόμα, το μέγεθος και αν θέλουμε να έχουμε φαρδιά γράμματα (bold) 
  • Refresh
  • Add περιεχόμενο$, προσθέτει μια γραμμή στο τέλος (στην εσωτερική λίστα/εσωτερικό πίνακα)
  • AddFast δείκτης,  περιεχόμενο$ (ο δείκτης δεν χρησιμοποιείται προς το παρόν), προσθέτει περιεχόμενο χωρίς επανασχεδιασμό της λίστας.
  • Insert περιεχόμενο, προσθέτει ακριβώς μετά το επιλεγμένο
  • Clear καθαρίζει τη λίστα
  • Delete αριθμός_στοιχείου, διαγράφει το στοιχείο (από την εσωτερική λίστα)
  • ShowThis αριθμός_στοιχείου και προαιρετικά με αληθές αν δεν θα είναι επιλεγμένο,  ρυθμίζει τη λίστα για να φαίνεται το στοιχείο με αριθμό που δίνουμε
  • Sort με προαιρετική έναν αριθμό θέσης στη κάθε γραμμή απ΄όπου θα ξεκινάει η σύγκριση για την ταξινόμηση.
  • ColorsReset ορίζουμε τα χρώματα στα εξ ορισμού.
  • Colors ορίζουμε το "άσπρο" και προαιρετικά άλλα τρια χρώματα.

Το παρακάτω παράδειγμα βάζει μια λίστα σε μια φόρμα, και η λίστα έχει ένα μόνο στοιχείο που γράφει το όνομά της Λιστ1! Όμως δεν έχει επιλεχθεί η γραμμή με το Λιστ1

Όρισε Φόρμα1 Φόρμα
Όρισε Λίστ1 Λίστα Φόρμα Φόρμα1
Μέθοδος Φόρμα1, "move", 2000,2000,10000,8000
Μέθοδος Λίστ1, "move", 2000,2000,4000,4000
Μέθοδος Φόρμα1,"Show", 1
Όρισε Λιστ1 Τίποτα
Όρισε Φόρμα1 Τίποτα

Η όρισε Λιστ1 Τίποτα μπορεί να παραληφθεί, όπως και σε όλα τα στοιχεία μιας φόρμας, ακόμα και η Όρισε Φόρμα1 Τίποτα, γιατί θα συμβούν αυτόματα στην έξοδο από το τμήμα. Όμως καλό είναι να φαίνεται, γιατί μπορεί να εννοείται αλλά διαβάζεται καλύτερα όταν δίνουμε την εντολή.

Ένα ακόμα παράδειγμα για το πώς διαβάζουμε τη λίστα, εδώ δεν δίνουμε μέγεθος και θέση στη φόρμα, θα πάρει τα εξ ορισμού θέση και μέγεθος. Στη λίστα βάζουμε το ShowAlways (το έχουμε δει και στα άλλα στοιχεία). Σε μια ιδιότητα text βάζουμε τις γραμμές που θέλουμε να δείξουμε ως γραμμές της λίστας. Συνδέουμε μια μεταβλητή με την ιδιότητα Listindex. Όταν κάνουμε κλικ στην φόρμα τότε μας γράφει στη κονσόλα (πίσω από τη φόρμα) την τιμή της Επιλεγμένο (της ιδιότητας Listindex). Χωρίς επιλογή γυρίζει το -1, ενώ αν επιλέξουμε το Αθήνα γυρίζει το 0. Θα μπορούσαμε πριν την εμφάνιση της φόρμας να δώσουμε το Επιλεγμένο=1 και έτσι να έχει γίνει η επιλογή στη γραμμή με τη πόλη Θεσσαλονίκη. Εδώ βλέπουμε μια απλή λειτουργία όπου θέτουμε την επιλογή στη λίστα, και μπορούμε να διαβάσουμε την επιλογή από κάποιο άλλο γεγονός και όχι ειδικά κατά την αλλαγή επιλογής!

Όρισε Φόρμα1 Φόρμα
Όρισε Λίστ1 Λίστα Φόρμα Φόρμα1
Μέθοδος Λίστ1, "move", 2000,1000,4000,3000
Με Λίστ1, "ShowAlways",Αληθές,"text",{Αθήνα
                                    Θεσσαλονίκη
                                    Πάτρα
                                    }
Με Λιστ1, "Listindex" ως Επιλεγμένο
Συνάρτηση Φόρμα1.Click {
      Τύπωσε Επιλεγμένο
      Ανανέωση
}
Μέθοδος Φόρμα1,"Show", 1
Όρισε Φόρμα1 Τίποτα

Στο παρακάτω παράδειγμα έχουμε αφαιρέσει το γεγονός Φόρμα1.Click και έχουμε βάλει δυο άλλα, το Λιστ1.Click και το Λιστ1.Scroll. Όταν επιλέγουμε με κλικ (αριστερό πλήκτρο του ποντικού) στη λίστα παράγεται γεγονός, το ίδιο όταν αλλάζουμε γραμμή με βελάκια άνω και κάτω ή με το ροδελάκι του ποντικού (κάνει PageUp ή PageDown αλλά όταν είναι λίγες γραμμές πάει ανά γραμμή) ή με πλήκτρα PageUp και PageDown. Όταν κρατάμε πατημένο το αριστερό πλήκτρο και το μετακινούμε πάλι παράγεται γεγονός αλλά τώρα είναι διαφορετικό. Και στις δυο περιπτώσεις αλλάζει η ίδια ιδιότητα. Δείτε επίσης ότι όταν αλλάζουμε την ιδιότητα Listintex (ως μεταβλητή εδώ είναι η Επιλεγμένο) δεν παράγεται γεγονός click ή scroll.

Όρισε Φόρμα1 Φόρμα
Όρισε Λίστ1 Λίστα Φόρμα Φόρμα1
Μέθοδος Λίστ1, "move", 2000,1000,4000,3000
Με Λίστ1, "ShowAlways",Αληθές,"text",{Αθήνα
                                    Θεσσαλονίκη
                                    Πάτρα
                                    }
Με Λιστ1, "Listindex" ως Επιλεγμένο
Συνάρτηση Λιστ1.Click {
      Τύπωσε Επιλεγμένο
      Ανανέωση
}
Συνάρτηση Λιστ1.Scroll {
      Τύπωσε Επιλεγμένο, "Ολίσθηση"
      Ανανέωση
}
Επιλεγμένο=1
Μέθοδος Φόρμα1,"Show", 1
Όρισε Φόρμα1 Τίποτα

Στο παρακάτω παράδειγμα έχουμε βάλει μια ιδιότητα που παίρνει μια παράμετρο, και φαίνεται σαν πίνακας, την Λιστ1$(). Αυτή μπορεί να παίρνει τιμές ή να δίνει τιμές. (ότι όνομα  θέλουμε βάζουμε, ακόμα και με τελεία, δηλαδή το Λιστ1.Λιστα$() θα ήταν αποδεκτό. Εδώ έχουμε επιπλέον μια προσθήκη στη λίστα με τη μέθοδο Add, και μια αλλαγή εμφάνισης στο στοιχείο της λίστας 0.
Προστέθηκε και η ιδιότητα Find η οποία λειτουργεί σαν συνάρτηση και επιστρέφει τιμή βάσει ενός αλφαριθμητικού που μπορεί να έχει χαρακτήρες όπως * και ? και άλλους (δείτε την ~ στα αλφαριθμητικά, είναι η Like της Visual Basic 6)
Επίσης μπήκε μια Αν Αληθές Τότε {} για να το δούμε και χωρίς το Αληθές, με Ψευδές,όπου στην μια περίπτωση κάνουμε ταξινόμηση και επιλέγουμε τη Θεσαλλονίκη, που εδώ δεν αλλάζει θέση, αλλά θα μπορούσε να αλλάξει, και στην άλλη απλά επιλέγουμε απευθείας το στοιχείο 1 (το δεύτερο).

Όρισε Φόρμα1 Φόρμα
Όρισε Λίστ1 Λίστα Φόρμα Φόρμα1
Μέθοδος Λίστ1, "move", 2000,1000,4000,3000
Με Λίστ1, "ShowAlways",Αληθές,"text",{Αθήνα
                                    Θεσσαλονίκη
                                    Πάτρα
                                    }
Με Λιστ1, "Listindex" ως Επιλεγμένο, "List" ως Λιστ1$(), "Find" ως Λιστ1Εύρεση()
Συνάρτηση Λιστ1.Click {
      Τύπωσε Επιλεγμένο, Λιστ1$(Επιλεγμένο)
      Ανανέωση
}
Συνάρτηση Λιστ1.Scroll {
      Τύπωσε Επιλεγμένο, Λιστ1$(Επιλεγμένο), "Ολίσθηση"
      Ανανέωση
}
Συνάρτηση Φόρμα1.click {
     τοπική Μ=Λιστ1Εύρεση("Π*")
    Αν Μ>-1 τότε Επιλεγμένο=Μ
}
Μέθοδος Λιστ1, "Add", "Καβάλα"
Λίστ1$(0)="*Αθήνα*"
Αν Αληθές Τότε {
      Μέθοδος Λιστ1, "Sort"
      Επιλεγμένο=Λιστ1Εύρεση("Θ*")
} Αλλιώς Επιλεγμένο=1
Μέθοδος Φόρμα1,"Show", 1
Όρισε Φόρμα1 Τίποτα


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

Αυτό που δεν έχουμε δει είναι το γεγονός dblclick, το οποίο παράγεται όταν κάνουμε κλικ στο επιλεγμένο, ή όταν το τραβάμε δεξιά, ή όταν πατάμε Enter.  Εδώ καλούμε το γεγονός και προγραμματιστικά όταν κάνουμε κλικ στη φόρμα, με μια κάλεσε τοπικά (η κάλεσε τοπικά βλέπει συναρτήσεις που ανήκουν στο τρέχον τμήμα ή συνάρτηση, και τις καλεί ως τμήμα - αν υπάρχει επιστροφή με = τότε θα το δει ως λάθος με το νούμερο της επιστροφής, οπότε δεν βάζουμε σε αυτές τις συναρτήσεις εξυπηρέτησης γεγονότων το = τιμή...)
Γιατί υπάρχει ξεχωριστό γεγονός, ενώ όπως είδαμε πριν μας βόλευε και τα Click και Scroll; Η απάντηση είναι ότι αυτό το γεγονός είναι το σημαντικό, ενώ τα άλλα απλά βολεύουν ορισμένες φορές όπου η χρήση τους είναι για να αλλάζουμε κατάσταση σε άλλα στοιχεία, πριν γίνει η όποια "σημαντική" επιλογή.

Όρισε Φόρμα1 Φόρμα
Όρισε Λίστ1 Λίστα Φόρμα Φόρμα1
Μέθοδος Λίστ1, "move", 2000,1000,4000,3000
Με Λίστ1, "ShowAlways",Αληθές,"text",{Αθήνα
                                    Θεσσαλονίκη
                                    Πάτρα
                                    }
Με Λιστ1, "Listindex" ως Επιλεγμένο, "List" ως Λιστ1$()
Συνάρτηση Λιστ1.DblClick {
      Τύπωσε Επιλεγμένο, Λιστ1$(Επιλεγμένο), "Διπλό κλικ"
      Ανανέωση
}
Συνάρτηση Λιστ1.Click {
      Τύπωσε Επιλεγμένο, Λιστ1$(Επιλεγμένο)
      Ανανέωση
}
Συνάρτηση Λιστ1.Scroll {
      Τύπωσε Επιλεγμένο, Λιστ1$(Επιλεγμένο), "Ολίσθηση"
      Ανανέωση
}
Συνάρτηση Φόρμα1.Click {
      Επιλεγμένο=2
      Κάλεσε Τοπικά Λιστ1.DblClick()
}
Επιλεγμένο=1
Μέθοδος Φόρμα1,"Show", 1
Όρισε Φόρμα1 Τίποτα


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

Όρισε Φόρμα1 Φόρμα
Με Φόρμα1, "Title" Ως ο_Τίτλος_μου$
Επίπεδο Φόρμα1 {
      Διάστιχο 60
      Γραμματοσειρά "Arial Black"
      Παράθυρο 16, 8000,6000
      Οθόνη 1,0
      Δρομέας 0, Ύψος δια 2
      Αναφορά 2,"Γειά σου Κόσμε"
}
Όρισε Λίστ1 Λίστα Φόρμα Φόρμα1
Μέθοδος Λίστ1, "move", 1000,1000,6000,4000
Με Λίστ1,"Text",{London
                                    Paris
                                    Athens
                                    Rome
                                    Tirana
                                    Nicosia
                                    Brussels
                                    Copenhagen
                                    Berlin
                                    Dublin
                                    Luxembourg
                                    }
Με Λίστ1, "transparent", Αληθές , "ListIndex" Ως Που
Με Λίστ1, "Find" Ως Βρες()
Με Λίστ1, "List" Ως Λίστα$()
Μέθοδος Φόρμα1, "Show"
Με Φόρμα1,"Sizable", Αληθές, "SizerWidth", 90
Συνάρτηση Λιστ1.Color {
      Διάβασε Νέο &rgb
            rgb=#FF7700
}
Συνάρτηση Λιστ1.DblClick {
            Διάβασε Τι
            Αν Δεξί$(Λίστα$(Τι),1)="✓" Τότε {
                  Λίστα$(Τι)=ΑριστερόΜέρος$(Λίστα$(Τι)+" "," ")
            } Αλλιώς {
                  Λίστα$(Τι)=ΑριστερόΜέρος$(Λίστα$(Τι)+" "," ")+" ✓"
            }
            Μέθοδος Λίστ1,"Refresh"
            ο_Τίτλος_μου$= Λίστα$(Τι)
}
Συνάρτηση Φόρμα1.click {
            Αν Που>=0 Τότε {
                  local K$=Λίστα$(Που), i
                  Μέθοδος Λίστ1,"Sort"
                  Που=Βρες(K$)
                  Επίπεδο {
                        Τύπωσε ">>", φορμα$
                        Ανανέωση
                  }
            } Αλλιώς Μέθοδος Λίστ1,"Sort"
}
Συνάρτηση Φόρμα1.Resize {
      Επίπεδο Φόρμα1 {
            Τύπος 16
            Οθόνη 1,0
            Δρομέας 0, Ύψος δια 2
            Αναφορά 2,"Γειά σου Κόσμε"
            Μέθοδος Λίστ1,"Refresh"
      }
}
Μέθοδος Φόρμα1, "Show", 1
Όρισε Φόρμα1 Τίποτα



Στο παράδειγμα παρακάτω χρησιμοποιούμε μια Κατάσταση και έχουμε ορίσει ότι θα έχει η λίστα 1000 στοιχεία. Κάθε στοιχείο μπορεί να υπάρχει ή όχι στην Κατάσταση (λίστα με κλειδί και τιμή). Αν δεν υπάρχει εμφανίζει κενή γραμμή. Με το Enter, ή με σπρώξιμο της γραμμής δεξιά, αλλάζει σε λίστα εισαγωγής και το ανάποδο, σε λίστα που προβάλει τα στοιχεία. Κάθε φορά που μετακινείται ο δρομέας της λίστας εμφανίζεται η τιμή (η γραμμή) στον τίτλο της φόρμας. Δείτε ότι η λίστα είναι σε κατάσταση διόρθωσης, τα πλήκτρα Home και End δουλεύουν για τη γραμμή, ενώ όταν γυρίσουμε σε προβολή για τη λίστα (με το End πάμε στο τελευταίο στοιχείο άμεσα). Η ιδιότητα HideCaret μπήκε πριν μερικές αναθεωρήσεις. Επειδή η ιδιότητα Edit αλλάζει την προβολή της Caret, με αληθές βγάζει επιλογή της γραμμής και βάζει την κάθετη γραμμή του δρομέα εισαγωγής, και στην αλλαγή σε ψευδές απλά αφαιρεί την κάθετη γραμμή, χρειάζεται να δώσουμε στην HideCaret τιμή Ψευδές, οπότε ανοίγει την επιλογή με χρωματισμό όλης της γραμμής.

Όρισε Φόρμα1 Φόρμα
Όρισε Λιστ1 Λίστα Φόρμα Φόρμα1
Κατάσταση Α=999:="Τέλος"
Προσθήκη Α, 0:="Πρώτο",3:="στο 3", 4:="στο 4"
Μ=Αληθές
Με Φόρμα1, "Title" ως Τιτλος$
Με Λιστ1, "Edit" ως Διόρθωση, "HideCaret" ως ΚρύψεΕπιλογή, "Listindex" ως Ποιο
Συνάρτηση Λιστ1.Scroll {
      Αν Υπάρχει(Α, Ποιο) Τότε {
             Τιτλος$=Μορφή$("{0::-4}:{1}",Ποιο, Εκφρ$(Α))
      } Αλλιώς Τιτλος$=Μορφή$("{0::-4}:",Ποιο)
}
Συνάρτηση Λιστ1.Click {
      Αν Υπάρχει(Α, Ποιο) Τότε {
             Τιτλος$=Μορφή$("{0::-4}:{1}",Ποιο, Εκφρ$(Α))
      } Αλλιώς Τιτλος$=Μορφή$("{0::-4}:",Ποιο)
}
Συνάρτηση Λιστ1.DblClick {
       Διόρθωση=Μ
       Αν Μ Αλλιώς ΚρύψεΕπιλογή=Μ
       Μ~

}
Συνάρτηση Λιστ1.ListCount {
      Διάβασε Νέο &πόσα
      πόσα=1000
}
Συνάρτηση Λιστ1.External {
      Διάβασε Νέο Που, &τι$
      Αν Υπάρχει(Α, Που) Τότε {
            τι$=Εκφρ$(Α)
      } Αλλιώς τι$=""
}
Συνάρτηση Λιστ1.ValidList {
       Διάβασε Νέο &περιεχ$, &θεσηΧ, &στοιχειο
      Αν Υπάρχει(Α, στοιχειο) Τότε {
            Επιστροφή Α, στοιχειο:=περιεχ$
      } Αλλιώς.Αν περιεχ$<>"" Τότε Προσθήκη Α, στοιχειο:=περιεχ$
  
}
Με Λιστ1, "External", Αληθές, "DisplayLines", 5
Μέθοδος Λίστ1, "move", 2000,1000,4000,3000
Μέθοδος Φόρμα1,"Show", 1
Όρισε Λιστ1 Τίποτα
Όρισε Φόρμα1 Τίποτα




Δείτε επίσης το πρόγραμμα - παράδειγμα εδώ  όπου συνδέουμε δυο λίστες, η μια δουλεύει με εξωτερικό πίνακα, και λειτουργούν ως εξής: Όταν μετακινούμε την επιλογή στη μια, μετακινείται και στην άλλη, είτε η μετακίνηση γίνει με τα βελάκια, είτε με το ροδελάκι, είτε με την μπάρα ολίσθησης (εμφανίζεται αυτόματα όταν πάμε το δείκτη του ποντικού πάνω από την περιοχή της). Για να το πετύχουμε αυτό χρειάζεται να παίρνουμε ένα γεγονός Move που δίνει την νέα πάνω γραμμή (από εκεί που ξεκινάει και εμφανίζει τις γραμμές η Λίστα). Επειδή μπορεί να μην συμβεί αυτό το γεγονός, δηλαδή να μην χρειαστεί να αλλάξει η πάνω γραμμή, χειριζόμαστε και άλλα γεγονότα όπως το Click και το Scroll. Ένα ακόμα πράγμα χρειαζόμαστε, να μπορούμε να επιλέγουμε στο δίπλα στοιχείο χωρίς να παίρνει εντολή για επανασχεδιασμό, επειδή θα το δώσουμε με την εντολή τοποθέτησης νέας πάνω γραμμής. Υπάρχει λοιπόν το ListIndex2 το οποίο μόνο διαβάζει, και κάνει νέα επιλογή στη λίστα "αθόρυβα". Στα στοιχεία είναι χρήσιμο να εκτελούμε διαδοχικές εντολές σε αυτά χωρίς να γίνεται άμεσα ανανέωση, για δυο λόγους. Ένας λόγος γιατί κάθε ανανέωση συχρονίζεται με την ανανέωση της φόρμας άρα μπαίνει καθυστέρηση, που μπορεί να φθάσει το μέγιστο του διαστήματος αυτόματης ανανέωσης, και ο δεύτερος γιατί θα δείχνουμε κάτι που δεν έχει ολοκληρωθεί, και θα προκαλεί γρήγορες εναλλαγές, σαν τρεμόπαιγμα (flickering), το οποίο δεν είναι καλαίσθητο.


Στην έκδοση 11 της γλώσσας
Παράδειγμα με πολλές στήλες και με εγγραφή σε θέσεις:

Όρισε Φόρμα1 Φόρμα
Με Φόρμα1, "Title" ως οΤίτλοςΜου$
Επίπεδο Φόρμα1 {
Διάστιχο 60
Γραμματοσειρά "Arial Black"
Παράθυρο 16, 12000,6000
Φόντο 11, 1, 0
Δρομέας 0, Ύψος δια 2
Αναφορά 2,"Hello World"
}
Όρισε Πλαίσιο1 ΕΙΚΟΝΑ Φόρμα Φόρμα1
Μέθοδος Πλαίσιο1, "move", 600,1000,9300,4300
Όρισε Λίστα1 ΛΙΣΤΑ Φόρμα Φόρμα1 Εικόνα Πλαίσιο1
Μέθοδος Λίστα1, "move", 1000,300,6900,3300
Μέθοδος Λίστα1, "Colors", 15, 0,,0,7
Με Λίστα1, "Column" ως Λίστα1.Στήλη, "Edit" ως ΔιόρθωσεΣτήλη // ,"DisplayLines", 5, "Transparent", Αληθής
Με Λίστα1, "Columns", 4, "ColumnWidth" ως α(), "NarrowSelect", Αληθής, "TextColumn" ως ΣτήληΚειμένου$()
Με Λίστα1, "TitleHeight", .2, "Title", " " , "AdjustColumns", Αληθής , "BorderStyle", 1, "wraptext", Αληθής, "TopRows", 1, "maychange", Ψευδής, "moveparent", Ψευδής
Με Λίστα1,"ListJoin" ως Listjoin()
Μέθοδος Λίστα1, "SetGrid", Αληθής, 5
Μέθοδος Λίστα1, "UseHorMove"


ΔιόρθωσεΣτήλη=Ψευδής
α(1)=3300
α(2)=0 '3300
α(3)=3300
α(4)=3300

Με Λίστα1,"text", {Header 1
Paris
Athens
Rome
Tirana
Nicosia
Brussels
Copenhagen
Berlin
Dublin
Luxembourg
One More
}
ΣτήληΚειμένου$(2)={Header 2
4Paris2
2Athens2
1Rome2
Tirana2
Nicosia2
2Brussels2
Copenhagen2
1Berlin2
Dublin2
8Luxembourg2
one more2
}
ΣτήληΚειμένου$(3)={Header 3
}
ΣτήληΚειμένου$(4)={Header 4
200
300
400
500
600
700
800
900
1000
1100
1200
}
Με Λίστα1, "listindex" ως ΔείκτηςΛίστας1, "ListCount" ως ΣτοιχείαΛίστας1, "ShowAlways", Αληθής
Με Λίστα1, "Find" ως Βρες(), "List" ως Λίστα$(), "Edit" ως Διόρθωση_οκ, "Center" ως Κέντρο_οκ
Κέντρο_οκ=Αληθής
Λίστα1.Στήλη=1
ΔείκτηςΛίστας1=Βρες("Rome")
Μέθοδος Λίστα1, "addheight", 2
ΔείκτηςΛίστας1=Βρες("Copenhagen")
Μέθοδος Λίστα1, "addheight", 1
Με Φόρμα1,"Sizable", Αληθής,"SizerWidth",90
Επίπεδο Πλαίσιο1 {
Οθόνη 5, 0
}
Συνάρτηση Λίστα1.ValidMove {
Διάβασε Νέο ,
Τύπωσε χ , ψ
Αν χ<1000 Τότε χ=1000
Ανανέωση
}
Συνάρτηση Λίστα1.container {
Διάβασε Νέο &απ
Μέθοδος Πλαίσιο1, "CopyBack"
απ=Ψευδής
}
Συνάρτηση Λίστα1.SoftClick {
Κάλεσε Τοπικά Λίστα1.CLick()
}
Συνάρτηση Λίστα1.CLick {
Διάβασε Νέο ποιος
Αν ποιος=1 Τότε
Αν ΔιόρθωσεΣτήλη Τότε ΔιόρθωσεΣτήλη=Ψευδής
Αλλιώς.Αν Λίστα1.Στήλη=1 Τότε
ΔιόρθωσεΣτήλη=Ψευδής
Αλλιώς
ΔιόρθωσεΣτήλη=Αληθής
Τέλος Αν
}
Συνάρτηση Φόρμα1.click {
Μέθοδος Λίστα1, "sort",,,4, 1
}
Συνάρτηση Φόρμα1.Unload {
Πληκτρολόγιο "!"   \\ σαν να πάτησες !
}
Συνάρτηση Φόρμα1.Resize {
Επίπεδο Φόρμα1 {
Τύπος 16 // βάζει γράμματα 16pt
Φόντο 11, 1, 0
Δρομέας 0, Ύψος δια 2
Αναφορά 2,"Γεια σου Κόσμε"
Μέθοδος Λίστα1,"Refresh"
}
Μέθοδος Πλαίσιο1, "CopyBack"
Επίπεδο { Ανανέωση}
Μέθοδος Φόρμα1, "refreshALL"
}
οΤίτλοςΜου$="Παράδειγμα"
Μέθοδος Φόρμα1, "Show"
α$=Κομ$ \\ απλά περιμένει η κονσόλα να δει ένα πλήκτρο!
Όρισε Φόρμα1 Τίποτα



Κυριακή 30 Ιουλίου 2017

Αναθεώρηση 23 (Έκδοση 8.9)

Διόρθωσα ένα πρόβλημα που μπορούσε να προκύψει, αν διορθώναμε κείμενο στη κονσόλα της Μ2000 ενώ είχαμε ανοικτή μια φόρμα χρήστη. Υπήρχε πρόβλημα με το μηχανισμό για να παίρνει ο διορθωτής το γεγονός από το ροδελάκι του ποντικιού. O μηχανισμός για να πάρει το γεγονός χρειάζεται επειδή δεν το δίνει η Visual Basic 6 στις φόρμες της. Ουσιαστικά οι φόρμες της VB6 είναι αντικείμενα πάνω στα αντικείμενα παραθύρων των Windows (παρόμοιος τρόπο δουλεύει και η Μ2000, όπου οι φόρμες χρήστη είναι αντικείμενα πάνω από τις φόρμες της VB6).
Ο μηχανισμός κάνει Hook (αγκιστρώνει) μια συνάρτηση που ελέγχει τα μηνύματα γεγονότων όπως παράγονται από το σύστημα των Windows. Όταν δεν το χρειαζόμαστε τότε γίνεται Unhook, δηλαδή βγαίνει εκτός. Για να κατανοήσει κανείς αυτό το αγκίστρωμα, αρκεί να σκεφτεί ότι κάθε παράθυρο δηλώνει μια διεύθυνση μιας συνάρτησης που εξυπηρετεί γεγονότα, την λεγόμενη και WindowProc (η διαδικασία παραθύρων). Για να γίνει subclassing, πρέπει να πάρουμε αυτή τη διεύθυνση και να την φυλάξουμε, και αυτό γίνεται γιατί γνωρίζουμε μια ιδιότητα των παραθύρων, το hWnd, ή window handler, τον χειριστή του παραθύρου, που είναι ένας αριθμός. Κάθε παράθυρο, ακόμα και στοιχείο στο παράθυρο που είναι αντικείμενο Window, έχει τον δικό του χειριστή, που ορίζεται από το σύστημα των Windows. Όπως όταν ανοίγουμε ένα αρχείο μας δίνει το σύστημα ένα χειριστή αρχείου (file handler) έτσι είναι και ο χειριστής παραθύρου.  Με αυτόν τον χειριστή βρίσκουμε πολλά πράγματα για το παράθυρο, και ένα από αυτά είναι η διεύθυνση της συνάρτησης (ή ρουτίνας αν θέλουμε να την πούμε και έτσι), που δέχεται τα μηνύματα από τα γεγονότα και οφείλει να τα αποδεσμεύσει, είτε τα ικοανοποιήσει είτε όχι, διαφορετικά το σύστημα βγάζει συμπέρασμα, μετά από κάποιο χρόνο, ότι η εφαρμογή έχει κρεμάσει! Όταν χρησιμοποιούνται χειριστές (αυτοί οι αριθμοί) σημαίνει ότι τα δεδομένα είναι εκτός διαδικασίας, ή process, δηλαδή ανήκουν κάπου αλλού. Πράγματι τα δεδομένα για τα παράθυρα ανήκουν στον Window Manager, στο πρόγραμμα που λειτουργεί τα παράθυρα και τα στοιχεία τους στο λειτουργικό. Υπάρχει περιορισμός για τα πόσα παράθυρα μπορούμε να ανοίξουμε. Μπορούμε να δούμε ένα πρόγραμμα πόσους handlers χρησιμοποιεί μια δεδομένη στιγμή από τον Windows Task Manager, στη καρτέλα Processes, αν επιλέξουμε να μας δείχνει την στήλη Handlers. H M2000 χρησιμοποιεί περίπου 240, το Notepad περίπου 78, ενώ ο explorer περνάει τους 1000. Βέβαια το νούμερο δεν μας δείχνει μόνο τους handlers του Window Manager, αλλά και όλους τους άλλους, για αντικείμενα των windows που δεν είναι απαραίτητα στοιχεία των παραθύρων.

Για να γίνει λοιπόν το subclassing πρέπει να ενημερώσουμε τον Window Manager ότι αλλάζει η ρουτίνα εξυπηρέτησης, αλλά προσοχή εδώ, η δική μας ρουτίνα πρέπει στο τέλος να καλεί την από πριν καθορισμένη! Όταν γίνεται Unhook τότε απλά ενημερώνουμε τον Windows Manager δίνοντας την καθορισμένη ως την μόνη ρουτίνα εξυπηρέτησης.

Παρακάτω είναι το πρόγραμμα που έβγαζε κόλλημα (hang), γιατί όταν ξεκίναγε ο διορθωτής στη κονσόλα (είχε γραφτεί πριν υπάρξουν φόρμες χρήστη στη Μ2000), με τρόπο κλείδωνε την φόρμα (ενώ δεν ήταν κλειδωμένη, μια σημαία (flag) εσωτερικά έκοβε την πρόσβαση στη φόρμα), με σκοπό να κάνει το στοιχείο "διορθωτής" να είναι το μόνο με το οποίο δουλεύουμε. Νήματα μπορούσαν να τρέξουν πίσω, καθώς επίσης μπορούσε το παράθυρο επιλογών (το βλέπουμε ως αναπτυσσόμενη λίστα επιλογών ή context menu), το οποίο όμως έχει ξεχωριστή ρουντίνα hook, για τη δική του μπάρα ολίσθησης). Όταν φτιάχτηκαν οι φόρμες χρήστη έπρεπε να βρεθεί ένας τρόπος, ώστε οποιοδήποτε στοιχείο πάνω στη φόρμα να παίρνει το γεγονός αλλαγής της ροδέλας του ποντικιού, χωρίς να χρειάζεται ξεχωριστή ρουτίνα hook. Το πρόβλημα με τις ρουτίνες αυτές είναι ότι απαιτούν σταθερή διεύθυνση μνήμης, πριν ακόμα εκτελεστεί το περιβάλλον της Μ2000, έτσι πώς θα ήταν δυνατόν να έχουμε οποιοδήποτε αριθμό φορμών και στοιχείων και να έχουμε μια Hook ευκολία; Το πρόβλημα λύθηκε με την ιδέα ότι η συνάρτηση αυτή θα δίνεται και θα παίρεται από το κάθε ενδιαφερόμενο στοιχείο. (και η φόρμα Ρυθμίσεις λειτουργεί έτσι, για όλα τα στοιχεία της). Όμως δεν είχε ξεκαθαριστεί το πώς θα γίνονταν στο διορθωτή κειμένου της κονσόλας (είναι διαφορετικό αντικείμενο, πάνω σε ένα κοινό αντικείμενο usercontrol της VB6, σε σχέση με το στοιχείο TextBox, ή Κείμενο), Τώρα λοιπόν ξεκαθαρίστηκε (Αφού επισημάνθηκε το πρόβλημα).




declare form1 form
declare inp1 TextBox form form1

method form1, "show"
show
document a$
\\ now open in console the editor
\\ when open move form1
\\ before revision 23 m2000 environment hang
\\ because edit.doc editor subclassing mouse enent
\\ we can't use subclassing in the mouse event while we leave console form
\\ can't work so now is fixed by unhooking subclassing when form deactivated.
edit.doc a$
print "ok"
declare form1 Nothing

Σάββατο 29 Ιουλίου 2017

Αναθεώρηση 22 (Έκδοση 8.9)

Ανέβηκε μια νέα αναθεώρηση με προχωρημένες λειτουργίες για το στοιχείο ελέγχου Λίστα (ListBox)

Το παράδειγμα έχει δυο λιστες (ListBox) το ένα δίπλα στο άλλο. Όταν μετακινούμε το ένα μετακινείται και το άλλο (ολισθαίνει δηλαδή πάνω και κάτω). Επιπλέον ο πίνακας στο δεύτερο είναι εξωτερικός. Εδώ η αλλαγή που έκανα είναι για να μπορεί να διορθώνεται ο εξωτερικός πίνακας, δηλαδή να του βάζουμε τιμές!
Το πρόγραμμα θα μπει στο τεύχος 34. Δεν έχει τελειώσει ακόμα το τεύχος αλλά σίγουρα θα γράφει πολλά πράγματα για το στοιχείο Λίστα!


Όρισε Φόρμα1 Φόρμα
Όρισε Λίστ1 Λίστα Φόρμα Φόρμα1
Όρισε Λίστ2 Λίστα Φόρμα Φόρμα1
Μέθοδος Λίστ1, "move", 2300,1000,2000,3000
Μέθοδος Λίστ2, "move", 4300,1000,4000,3000
Με Λίστ1, "ScrollTo" ως Ολισθ1, "ScrollFrom" ως Ολισθ1_τιμή, "DisplayLines", 5 ', "Transparent", Αληθές
Με Λίστ1, "listIndex2" ως Επιλ01, "listIndex" ως Επιλ1,"HideCaret", Αληθές ,  "ShowAlways", Αληθές
Με Λιστ2, "ScrollTo" ως Ολισθ2, "ScrollFrom" ως Ολισθ2_τιμή, "Edit",Αληθές,  "ShowAlways", Αληθές
Με Λίστ2, "listIndex2" ως Επιλ02, "listIndex" ως Επιλ2, "DisplayLines", 5
Με Λιστ1, "Title","Πεδία"
Με Λιστ2, "Title","Τιμές", "Center", Αληθές, "PanDouble", Αληθές
Με Λίστ1,"Text", {Όνομα
                                    Διεύθυνση1
                                    Διεύθυνση2
                                    Διεύθυνση3
                                    Πληροφορία1
                                    Πληροφορία2
                                    Πληροφορία3
                                    Πληροφορία4
                                    }
Πίνακας Βάση 0, α$(8)
α$(0)="Γιώργος"
Συνάρτηση Λιστ2.Listcount {
            Διάβασε Νέο &πόσα
            πόσα=8
}
Συνάρτηση Λιστ2.External {
      Διάβασε Νέο Που, &τι$
      τι$=α$(που)

}
Με Λίστ2, "External", Αληθές
Συνάρτηση Λιστ2.ValidList {
       Διάβασε Νέο &περιεχ$, &θεσηΧ, &στοιχειο
       Τύπωσε περιεχ$, θέσηΧ, στοιχείο : Ανανέωση
       α$(στοιχείο)=περιεχ$
}

Συνάρτηση Λιστ1.Color {
      Διάβασε Νέο &χρ
      Χρ=#FF3311
}
Συνάρτηση Λιστ2.Color {
      Διάβασε Νέο &χρ
      Χρ=#1133FF
}
Συνάρτηση Λιστ2.dblClick {
      Διαβασε που
      Τύπωσε "doule click", αριθμός, α$(που)
      Ανανέωση
}
Συνάρτηση Λιστ2.Click {
      Επιλ01=Επιλ2
      Επιλ2=Επιλ2
      Ολισθ1=Ολισθ2_τιμή
}
Συνάρτηση Λιστ1.Click {
      Επιλ02=Επιλ1
      Επιλ1=Επιλ1
      Ολισθ2=Ολισθ1_τιμή
}
Συνάρτηση Λιστ2.Scroll {
      Επιλ1=Επιλ2
      Ολισθ1=Ολισθ2_τιμή
}
Συνάρτηση Λιστ1.Scroll {
      Επιλ2=Επιλ1
      Ολισθ2=Ολισθ1_τιμή
}
Συνάρτηση Λιστ2.Move {
      Διάβασε Νέο πάνω1
      Επιλ01=Επιλ2
      Ολισθ1=πάνω1
}
Συνάρτηση Λιστ1.Move {
      Διάβασε Νέο πάνω1
      Επιλ02=Επιλ1
      Ολισθ2=πάνω1
}
Μέθοδος Φόρμα1, "Show", 1
Όρισε Φόρμα1 Τίποτα
Τύπωσε α$()