Παρασκευή, 4 Αυγούστου 2017

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

Προσθήκες συναρτήσεων για ιδιότητες αντικειμένων τύπου COM, ιδιότητα(), ιδιότητα$(), property(), property$()

declare form1 form
declare list1(3) listbox form form1
controls=(,)
link controls to controls$()
inventory listindex, titlelist
for i=0 to 2 {
      Method list1(i), "move", 2000,1100+i*1000, 5000,900
      With list1(i), "list" as new list$(), "DisplayLines", 2, "listindex" as new listind, "title" as new mTitle$
      With list1(i), "text", {aaaaaaa
            bbbbbbbbbb
            cccccccc
            }
      Append titlelist, i:=property$(mTitle$)
      Append listindex, i:=property(listind)
      Print listindex(i), type$(listind)
      Append controls, (list$(),)
      Print len(controls$())
      controls$(i)(0)="ok"+str$(i)
      Print list$(0), "ok", controls$(i)(0)
}
     listindex(0)=2
     titlelist$(0)="ok..."
Print len(listindex)
function form1.click {
     listindex(0)=2
}
function list1.dblclick {
      Read New Who, what
      Print listindex(who), who, what
      Refresh
}
method form1, "show",1
declare list1() nothing
declare form1 nothing



Το παρακάτω πρόγραμμα δουλεύει καλά τώρα, και χρησιμοποιεί ένα εξωτερικό αντικείμενο, το vbRichClient 5 από εδώ  http://www.vbrichclient.com/, το οποίο έχει ένα σωρό αντικείμενα και συνάμα έχει δικές του φόρμες, του συστήματος Cairo. Δείτε πως παίρνουμε τα γεγονότα για φόρμες που ανήγουμε προσωρινά με Modal τρόπο:
Κάθε φορά που κάνουμε click στη κίτρινη φόρμα, ανοίγουν έξι "κόκκινες" Modal φόρμες, και κάθε φορά πρέπει να κλείσουμε την πιο μπροστά για να πάμε στην πιο πίσω μέχρι να φτάσουμε στην κίτρινη πάλι. Συνάμα αν κάνουμε κλικ στην κόκκινη φόρμα


Δείτε κάτι ακόμα: Υπήρχε πρόβλημα όταν ξεκίναγα μια "κόκκινη" φόρμα μέσα στην συνάρτηση εξυπηρέτησης γεγονότος, μπορούσε να ανοίξει τέσσερις φόρμες και μετά για άνγωστη αιτία δεν άνοιγε άλλη! Το σκέφθηκα λοιπόν και έβαλα την εντολή After miliseconds {} ή Μετά χιλιοστά_δευτερολέπτου {}, το οποίο είναι νήμα που θα τρέξει αφού το γεγονός θα έχει επισρέψει!

Επίσης από αυτή την αναθεώρηση έβαλα στα γεγονότα που στέλνονται στην Μ2000 (συναρτήσεις με όνομα αντικειμένου μετά μια κάτω παύλα και μετά το όνομα του γεγονότος, να ακολουθεί στο τέλος το αντικείμενο (μια αναφορά του) που στέλνει το γεγονός! Έτσι η Form2_Click δουλεύει με τη σειρά για όλες τις φόρμες που ανοίγουν η μία μετά την άλλη (έξι τον αριθμό)

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

Επίσης δείτε το  πως δημιουργούμε το Form2. Επειδή θέλουμε να βγει 6 φορές με 6 νήματα, και κάθε νήμα θα μπλοκάρει για όσο η φόρμα Form2 θα είναι ανοιχτή, σημαίνει ότι στο τμήμα θα υπάρχουν 6 Form2, δηλαδή με ίδιο όνομα και σε αναζήτηση θα βρίσκεται το τελευταίο που γράφτηκε.ενώ η διαγραφή δεν θα γίνεται στο νήμα! Το νήμα δηλαδή δεν διαγράφει ότι τυχόν φτιάχνει. Αν ανοίξουμε 600 φόρμες θα υπάρχουν 600*Ν μεταβλητές όπου Ν είναι όσες χρειάστηκε να φτιαχτουν ως νέες στο κάθε νήμα.
Τώρα πώς ξέρουμε ότι θα καθαρίσουν οι μεταβλητές αυτές με την ανάποδη σειρά; Οι φόρμες άνοιξαν σαν Modal δηλαδή πρέπει να κλείσουμε την τελευταία που άνοιξε, και μετά την προτελευταία, και αυτή είναι η σειρά που πρέπει να "καθαρίσουν" και τα αντικείμενα.

Δείτε επίσης πως όταν κρατάμε πατημένο το [X] για κλείσιμο της φόρμας στο RC5 σταματάνε ακόμα και τα νήματα στην Μ2000. (πράγμα που δεν συμβαίνει με τις φόρμες της Μ2000, αφού το τετραγωνάκι στις φόρμες για το κλείσιμο δεν είναι το ίδιο με το κουμπί στις φόρμες της VB6). Ουσιαστικά η Μ2000 έχει ένα μέρος δικό της σε σχέση με τον Window manager, και αυτό ευθύνεται για το πώς χειρίζεται το κλείσιμο και τα modal παράθυρα (πχ η φόρμα ¨Ελεγχος είναι ανεξάρτητη από τα παράθυρα χρήστη που μπορεί να ανοίξουμε με modal τρόπο. Επίσης μπορούμε να ανοίξουμε μη modal παράθυρα από ένα modal παράθυρο, και μετά αν ανοίξουμε ένα Modal θα κλείσει όλα τα προηγούμενα και όταν το κλείσουμε θα ανοίξει μόνο τα αμέσως προηγούμενα που ήταν ανοιχτά, μέχρι να κλείσουμε και το ένα modal, που άνοιξε τα μη modal, οπότε θα ελευθερωθούν τα κάτω από αυτό! Το παράθυρο της βοήθειας είναι και αυτό εκτός των Modal παραθύρων.Τα modal παράθυρα απενεργοποιούν και την κονσόλα. Το κώδικα για αυτό το σύστημα το έχω γράψει εδώ και καιρό, αλλά είναι μια ιδέα με "μαγικούς" αριθμούς, στην ουσία τυχαίους, που διαλέγει το σύστημα, με "νόημα" που δηλώνουν το ποιος έχει το πάνω χέρι. Οπότε όταν ένα modal παράθυρο κλείνει στέλνει στα άλλα το μήνυμά του. Ένα παράθυρο που έχει "απενεργοποιηθεί", ουσιαστικά μπορεί να δουλεύει κανονικά, εκτός από το να δέχεται κλικ και πλήκτρα, δηλαδή μπορεί να μετακινηθεί, ακόμα και να κλείσει! Ακόμα και το messagebox είναι της Μ2000, το Ask() ή Ρώτα(), και βγαίνει πάνω από όλα τα άλλα, ως modal και αυτό. Εδώ έχει μια ιδιαιτερότητα η Μ2000, δεν επιτρέπει δεύτερο messagebox να βγει. Δηλαδή αν το βάλουμε σε ένα νήμα (τα νήματα μπορούν να τρέχουν πίσω από το messagebox) θα βγει λάθος αν ήδη είναι ανοικτό. Ενώ οι φόρμες της Μ2000 είναι GuiM2000 αντικείμενα, οι διάλογοι της Μ2000 όπως το messagebox και για άνοιγμα φακέλων, αρχείων, επιλογής χρώματος και επιλογής γραμματοσειράς είναι ξεχωριτά αντικείμενα (είχαν γραφτεί πριν φτιαχτουν οι φόρμες χρήστη). Αυτά τα αντικείμενα έχουν την ιδιότητα να αλλάζουν μέγεθος με μεγέθυνση των στοιχείων τους και αυτά έχουν το ένα και μοναδικό glis4, ένα user control  γραμμένο στη VB6, με "ζωγραφιές"...δηλαδή δεν έχει κανένα άλλο control πανω στο user control, είναι μια επιφάνεια που σχεδιάζει ότι χρειάζεαι, ακόμα και το scoll bar...είναι ζωγραφιστό! Αποφεύγοντας την χρήση εξωτερικών στοιχείων, ή και βιβλιοθηκών η Μ2000 μπορεί να λειτουργεί το ίδιο από Xp ως και Windows 10, για όσο το βοηθητικό dll της VB6 τρέχει σε αυτά (μέχρι τον Οκτώβριο του 2025, αν και πιστεύω ότι δεν θα πάψει να υποστηρίζεται). Στην ουσία το M2000.exe και το Μ2000.dll (η γλώσσα μπορεί να φορτωθεί σε άλλες γλώσσες και να τρέχει από αυτές), χρειάζονται το msvbvm60.dll γιατί παρέχει συναρτήσεις κοινές αλλά και γιατί έχει το σύστημα των γεγονότων που λειτουργεί ως ενδιάμεσος με τις "πραγματικές" φόρμες των Windows. (στην ουσία κάθε φόρμα της Μ2000 είναι πάνω σε μια άδεια φόρμα της VB6 η οποία είναι ένα πραγματικό παράθυρο των Windows, και τα μηνύματα που λαμβάνει προωθούνται στη φόρμα της VB6, και από εκεί η M2000 τα προωθεί στο πρόγραμμα του χρήστη, τα δυο πρώτα μέρη είναι compiled, ενώ το τρίτο, ο κώδικας σε Μ2000 είναι Interpreted, αλλά ο διερμηνευτής είναι και αυτός compiled, δηλαδή δεν τρέχει ως interpreted Visual Basic 6, αλλά ως γλώσσα μηχανής.


Παρατηρήστε ότι οι συναρτήσεις για γεγονότα σε Com αντικείμενα έχουν _ και όχι τελεία όπως στις φόρμες της Μ2000. Αυτό συμβαίνει γιατί υπάρχει ξεχωριστό σύστημα "εσωτερικό". Ενώ τα γεγονότα για τα Com χρησιμοποιούν το Shink object, για μεταφορά γεγονότων από διαφορετικές διεργασίες


Ακόμα η χρήση του συγκεκριμένιυ εξωτερικού αντικειμένου είναι πειραματική.

clear
' cConstructor
'Title "",0
Declare AppForm Application Form
Declare New_c "{CAECC935-9C70-4176-8BED-C39B2E33B31F}"
Method New_c, "Cairo" as Cairo
'Print Type$(New_c)
'Print Type$(Cairo)
With Cairo, "WidgetForms" as Cairo.WidgetForms
Method Cairo.WidgetForms, "Create", 1,"My Main-Form Caption, Click Me!" withevents as Form1

Print type$(Form1)
vbYellow=65535
vbRed=255
vbFixedDialog=3
vbSizableToolWindow=5

Print Type$(Form1)
With Form1, "WidgetRoot" as Form1.WidgetRoot, "visible" as visible
Print type$(Form1.WidgetRoot)
With Form1, "hWnd" as Form1.hWnd
With Form1.WidgetRoot, "BackColor", vbYellow
          
Method Cairo.WidgetForms, "Create", vbSizableToolWindow, "MyToolWindow - Resize Me!", -1, 800, 600 as Form3
Method Form3,"SetMinMaxDimensions", 200, 400, 300, 600
With Form3, "visible" as Form3.visible
mClicks=0
\\ events
Function Form2_Click {
      drop
      read new form111
      mClicks++
      With form111, "Caption", "Click-Count so far:" +Str$(mClicks)
}
Function Form1_Move {
      Read New &X, &Y
      Print X, Y
      refresh
}
Function Form2_Move {
      Read New &X, &Y
      Print X, Y
      refresh
}
Function Form1_Click {
      Refresh
      \\ After start a new thread after 100 msec, and run once
      for i=1 to 6 {
      After 100 {
            Report "First we show a modal Dialog-Window, and count the Clicks on it"
            Method Cairo.WidgetForms, "Create", vbFixedDialog,"MyDialog ... Click Me!",-1 , 800, 600 withevents as new Form2
            With Form2, "WidgetRoot" as new Form2.WidgetRoot
            With Form2.WidgetRoot, "BackColor", vbRed
            Refresh
            Method Form2 "Show", 1
            Refresh
            Report format$("The Dialog was clicked {0} times.", mClicks)
            Report  {Now we show a non-modal ToolWindow, which remains in the ForeGround of this Form
                              and will close itself automatically, when the MainForm is destroyed
                              }
            Print
            refresh
            Declare Form2.WidgetRoot Nothing
            Declare Form2 Nothing
      }      
      }
     
}
Thread {
try {
      If pos>0 then print
      Print now, visible
      }
      refresh
} as alfa interval 100
Print Visible
Method Form1, "Show", 0, AppForm
Print Visible
\\\  not used here Method Cairo.WidgetForms, "EnterMessageLoop"
Task.Main 100 {
      if Form1.hWnd else exit
}
Threads erase
Declare form1 nothing
Declare form3 nothing
Declare cairo nothing
declare New_c nothing
Show  \\ to get focus to M2000 console