PDA

View Full Version : Using variables or UDTs to provide indexing of UI-objects (controls & windows)



ReneMiner
14-06-2020, 21:09
Windows as well as controls Can be named.
I am not sure how it is meant to evolve in the future. I remember that the idea to name the controls and use Call_IfExists onto the predefined Function names took you so much away that it was forgotten how to achieve maybe a grid of 4x6 pictures or textboxes and how to address these.

Today i know already:
It is possible to use an existing variables name.
Even the name of an as UDT-dimensioned variable can be used and give a control or a dialog a name.

Simple in basic:





Dim MyButton As Dword

myButton = Control Add Button,Name myButton, hDlg, Varptr(myButton), "Push me", 10,10,100,20 Style, ExStyle



this actually works!!! Use a dword to store the windows handle, use the name of this variable to be the name of the control at the same time and use the Pointer where my variable data starts - its VarPtr - to replace the ControlID
No other variable that will have an equal value here.

that was step 1.

Indexing? YES!

currently if i use




Dim Document(1000) As tCustomMDIChildwindow

For i = 1 to 1000
Dialog New Name Document(i), hParent, "document " & tstr$(i), -1, -1, 640,480, Ws_Border, WS_Ex_MDICHild, To Document(i).hWnd
next



all 1000 mdi windows have the same name. Thats ok.
But UI is not capable to capture the Index associated to the varptr nor to pass it as a parameter to inform the user within the callback what toolbarbutton caused the event.
Also i can not tell UI where my UDT for a dialog starts. It does not have a controlID.
If UI knew the Varptr, Index and Namethat belong together it were able to Provide the pseudo-variable "ME" within the event handler. Ui must know the varptr and store it together with the Index or Indexes...
The Callback is not a type-function. I will return to that topic later again.


Approach


Dim table(5,7)

' and create 35 controls without a name or do it like

for x = 1 to 5

for y = 1 to 7
Index$ =tstr$(x) & tstr$(y)
but that is no good way to name the controls because i can not tell UI to cut off 2 chars of the name when calling the controls callback.
on the other hand if i do it alike
Dim cell(5,7) as tMyType

i can not tell the index to ui when i create the control
UI accepts
Control Add Textbox Name cell, hDlg, varPtr(Cell(1,2)) , "text", x, y, w, h

so its legitim to use Varptr instead a ControlID. Each Varptr is different when its a different variable.
And if its the same then another name for the same object can not fool ui.
what is interesting also




Type tUIObject Quad
hWnd As Dword
End Type


this is my basetype . the template.
Every additional UI-Object is either of this type or customized to be a Type thatExtends tUIObject.
It inherits hWnd, stored exact at the position of the VarPtr.

Means
You know my Varptr? Ok, then you can read my windows handle right there.
You know my Windows-handle? ok, then you know where you can virtually place the structure that you know about Me - and you can be ME!

Those the major reasons of course

Why Quad there?


Simply the Quad (we have no QWord ) forces the Udt to be stored at a position that is divideable by 8. 8 Bits= 1 Byte.... 8*8 = 64 .
This means PtrSafe for x64 pcs and compatible. if someone with an x86er creates a script he can provide 64-bit compatibility. for his script.this way.


Types that Extends this tUIObject should Inherit this behaviour . the quad value I use either with HI-function or i place an absolute variable of type dword upon the objects pointed data-starting position. I

do not have to think about that the Varptr is not only a position where to read an important value (hWnd) but its a unique value that can be used as ID since no other variable can be there at the same time. No other variable . if control, menuitem or whatsoever will have the same position if i do not redim or reodrder memory in another way.
Nothing else will return the same value. Except the stored item at this position. And it does not matter what name the item has for the moment of request. If i put "A" as Dword onto it and ask for "A" or if i name it like i introduced it to UI previosly with the name, varptr and let it assign the hWnd- UI "knows" its the same thing without to have anything to think about it.

So far ok

UI must know to accept the parenthesis that follow the name containing indices belong with the name.
UI must know to store those indices together with the varptr.

UI knows already where to query-check 3 things at the same time. The ControlID ( if it is the actual Varptr as suggested) tells a number then. Interpreted as a position in memory the controlID points onto the value that equalls hWnd - the windows-handle.
And at the same time it his the position upon which the pseudo-variable "ME" has to be placed in a type-oriented callback function.

Type-oriented callback functions please take my 2 cents for it:

This functions called internal by UI using a Call_IfExist-approach. They are not really functions attached to the udt since any object - f.example all buttons would react the same way, no matter what their names where.
The exit-button would do the same as the "format my hd now".button because both are of type Button. To clarify this
DO NOT USE DOT NOTATION - stick with Underscore Or No seperatior between name of object and event. Dot is a sign that something will continue after a short break.
It will imply the thought there is a relation which is not reality. Please remove Dot notation again from that. I will tell you why soon.

First for the callback itself and to solve a problem with the indexing of controls and dialogs. UI must know to store an index together with the varptr. The objects name is good for calling the functions name. But within the function the objects Name were "ME"... so this indexing must be stored associated to the varptr.
Then :
Callback events names are predescribed by the rules of UI. It is OnClick() OnCallback etc. Users must follow these names. To receive Index of the object thats callback-event causes a function call the User must not only provide the correct functions name to have a successful callback.
The callback must also provide some uniform essential parameter- I am not sure if that were to leave with the users since it can lead to many errors and frustration and i suggest Callback functions for controls events like




Callback toolbarbuttonCbOnClick( Optional Byval Identification(ANY) As Long ) As Boolean



clarify
word by word:

Callback; get to get used not to use "Callback Function"
functions are what the user develops and takes parameters as he decides.
Callback is an event-notification. not invoked by the user through a certain keyword-combination.
no dot notation as said

Optional Byval Identification(ANY) As Long.

I do not use the verb Index, Indicators or Indices on purpose. all 3 Indexes together - if used - make it possible to do some identification.

Optional : of corse parameter must be optional if an object does not have index(es) it still will work for UI to call the eventhandler if it assigns
an Index or not- the index will let the user know which one of his many toolbarbuttons caused the event.
Thats why UI must know to save Indexes together with varptrs.

Variadic ? yes. You remember variadic is based upon a dynamic string . UI could as well pass MKL$(Index1, Index2, Index3) as a parameter to the eventhandler and let users find a way how to decode that...
Variadic i use for this example to point out how i came to the solution. its obvious if UI can pass optional Indexes for the user to help identify the one who caused the event.

So to remove the error-causing-source named "USER" - thats why i came to the Eventhandler - not to call it a function. The Eventhandler can provide the information (index of all 3 dimensions) in an optional function parameter that of course the user does not have to prepare to comfort him with easy usage of thinBasic. In reality sure, those stupid idots would not know how to do it right, no matter how often you will explain them. N matter how many evenings and half night you try to explain- the will not listen, they will not understand. Thats why its better you hide this optional parameters and pass them to the evethandler that provides a clearly readable wrapper for something they will not try to understand.

Its a joke- but you know what you can save yourself on troubles if you spend 30 minutes more on that just once.

to clarify:

do something as



Begin Eventhandler OnClick toolbarButton
' event handling code here


End Eventhandler


and remove the noun "callback" completely.

Do not hope for users to understand why they should reply a callback and return true to it.
Do not try to explain what performance boost that could cause.
use a stack-

They do not need to know its on top of a stack. And you will see if anyone took something of the stack.

Put it there like a key for the restroom:

"Who wants to go pottie grab yourself the key here and leave me your ID as deposit so you will return my key in order to get your ID back"...

To bring it to an end now: last point

We can have/use objects simply by using them as Variables. These have 3 indexes (3 dimensions) in thinBasic by default.

ok so far. Imagine i have a small window displaying a document. it has a static as canvas to display the picture, maybe another label containing information and whatever such a documen displaying window will need.


Picturebox1
Frame_left
frameRight
ButtonZoomIn
ButtonZoomOut
ButtonZoomreset
ButtonZoomPreferredUserSetting

etc.
my app will not have 1 mdi-child displaying the picture but my app will have more than 2000 of those mdi-windows. How to handle? No watch it:


Type tMDIChildtemplate Extends tUIObject
Picturebox1 as tCustomizedPicture
ZoomButtons(4 )as tUIObject
Picturefile as String
'-...

End Type

I will create a customized UIObject as an udt that keeps all the information about an MDI-childwindow together
It will lead to have things as:

MDIChild(1999).ZoomButton(3).SetDisabled

All controls neat arranged to an udt as branches on a tree. All windows as trees aside a road- straight clearly arranged. No
confusion. No chaos.
Can you remember what you just thought 1 minute ago when i mentioned i will have 2000 MDI-childs?
You thought: My god- what else?!

And now I say again i will create 2000 mdi-childwindows to display all my wallpapers, And now you will tell me to download another 10000 wallpapers while you're going to code a bit... you are not at all scared if i came up with 20000 wallpapers. Your comment: If your computercan handle iit- go ahead.


I am sure the post was too long for anyone to read. Leave youself a week to read it. No one forces you.
It certainly holds ideas that will solve a bunch of problems
It certainly contains ideas that will take time to realize
For sure everything can become reality if you can imagine it already.

Oh yes, before i forget:

built in VariableTypes (Long, Dword, Byte etc. that stuff)

Stay future oriented. Name it that anyone knows what it means. Like UINT32 Unsigned Integer 32 Bit...
I you develop a Vartype to avoid continuing repeatedly changing vartypes that shall be valid in 200 years and you name it
INT500 Signed integer 500 Bit or UINT1000 no one doubts what it could be. If i say just "Integer"- what will you ask
Signed? Unsigned? AtariXL? Atari St? Visual Basic ? say INT16 - all clarified.

thinBasic does not have UINT64-type
and to prepare for a future, clear the past.
Let it be INT8 and UINT8 when we use bytes in the future there will never be any doubt how to use them
And we will use Bytes in the future.
More than we used in the past. For sure


End

ErosOlmi
15-06-2020, 17:39
Ciao Rene,

first of all thanks a lot for such visionary post.

I will read in next days. I'm still working a lot on named controls, only half or so are already converted into named and events so it is the right time to see if vision is on the right path.
I'm printing your post so I can study it when I will have some concentration on the argument.

Thanks a lot
Eros

ReneMiner
24-06-2020, 02:42
I experimented a bit into that direction and ran into a few hindrances. It does not mean i would suggest something else but just to inform about what i experienced.


It runs well when i do it like creating controls as udts and attach the controls udt directly to the parenting dialogs udt. Because it allows me to call

dlgMain.ExitButton.BlinkTwice()

but if i have the ExitButton as a single UDT it wil not function to change its text when i use

ExitButton.Text ="STOP"

Then thinCore complains the property ".Text" is not available in my buttons udt. That's right because that is usage of an UI-control-function. And it tells me, that thinCore will no more look into UI after
discovering my udt-variable that fits the name "ExitButton". Maybe it were an easy thing to let thincore check (if uses UI) if there's a control with that name before telling me Error.
Besides it would be a simple nice hack to overrule UI-functions.

It were also an idea to go another way here and use a thinBasic feature or to combine it.
Extends Type...

If UI would provide very basic UDTs for Dialogs and a very basic UDT for the controls
( i call them just "UIDialogType" and "UIControlType")

and the user writes :



Type tMyButton Extends UIControlType
SpecialProperty As Byte

Function SpecialAction() as Whatever

' this were to customize a control with some special behaviour only
' usually controls will not require to extends UIControlType

End Function
End Type

Type tmyMainWindow Extends UIDialogType

SpecialButton As tMyButton
ExitButton As UIControlType

Function _Create()
' this would create the apps main window now
' as you see i attached Buttons already to the UDT!
' the udt extends what UI uses already providing few basic values as hWnd etc.
End Function

Dim dlgMain as tmyMainWindow


(really i try to keep it small to stay focused ;) )

if UI had another syntax for this ...

Then another thing that will need to forge a rule:

Its about DIALOG Indexing.

1. It will not make sense in 2 or 3 dimensions

2. It is impossible to initialize an array of windows using _Create in one go
(_Create will not initialize arrays, only the first array member will receive initial settings)
It would require some Manager within UI to handle that indexes are unique and all that stuff :(
Indexing dialogs using continous numbers is out of the question and is a nonsense

3. Using udts for Dialogs is no problem because each dialog will need a unique extension of
the UIDialogType.

4. The Exception: MDI-Children can be all of the same UDT. Indeed they have to be. And
MDI-Children have one MDI-Main-Window which is mandatory a unique item that has the privilege
to invoke the user-defined _Create function.

5. MDI-children display documents of the same type mostly. If someone makes an App that shows Movies and PDF-files he will need 2 different types of MDI-children anyway but its still display or edit document-files. All these files have ??? A filename and a path or they need one. And users will not care for indexed windows, they want to see the name of what they edit, read or watch...ever. Opening the same document twice? Risky it should be already be prevented by renaming or making a backup to open a document twice within one app.

6. The MDI-main-window is UNIQUE as said. Not two in one app. So the UIDialogtype can be flagged
(MDI Yes/no) if the window has a parents hWnd then it is probably an MDI-childwindow. If not MDI-flagged then its maybe inside a viewport or just another dialog.

7. MDI-children ( as all other dialogs ) do not need to pass an index to the Eventhandler.
Even if all have a "textbox" and a "savebutton" as long CBHNDL is present.

8. And the MDI-flagged-Window with no parent is the one who (w|c|sh)ould do the stuff about indexing the children. Internally. Users want to see filenames but not any numbers. Combination of 2 Strings as Filename & Path will serve. Have the same file backupped to another path to open it twice if something happens then - not OUR fault!

9. In Callback Function myTextbox_OnCallback()
- obvious the name who called . if it were
MDIChildname.myTextbox or MDIMain.myTextbox --- i have the strange idea to "customize"
Select Case (expression value)
into
Select Control CBCTL and Select Dialog CBHNDL
Case Control myButton(123) or Case Dialog Settingswindow

- i don't know if that will help.
Since Dialogs were unique udts it were a try to call windows-event at the windows udt.
No callback at a controls udt - but to the dialog where the UDT-Elements actually have the name as provided.
And then it were

Type tDIalogMain Extends UIDialogType
Exitbutton As UIControlType

Callback ExitButton_OnClick()
- The Dialogs name of the dimensioned variable + the
subelement that was named Exitbutton
End Callback

End Type


How about omit "Function" if ts a callback?

But ... i tell you what. I post an example here.
You think.
I will try not to confuse with too many ideas at once ;)

Appending an example later... after "beautification"


:(
sorry no more today. i searched the last 10 hours for a bug because tb claimed Function without missing End Function (or matching?) . After deleting all my comments and stripping down to Function-End Function lines
even after commenting all codelines it did not stop. Reboot - no change. Now i never gonna use #Region-#EndRegion any more - i discovered such a comment thing somewhere far away at right hands end an #EndRegion. Why does such comment, annotation, not even real code- make such a bug?