Page 1 of 2
Miscellaneous questions about converting VO code to X#
Posted: Thu Jan 18, 2024 2:21 pm
by Kees Bouw
Hi Everyone!
In this topic I would like to discuss smaller issues not big enough to have a topic on its own
To begin with:
In my VO code are the functions __ObjectCastClassPtr() and __GetClassPtr(). In VO these are defined as:
Code: Select all
_DLL FUNCTION __ObjectCastClassPtr(lpO AS OBJECT, lpClassPtr AS PTR) AS OBJECT PASCAL:VO28RUN.__ObjectCastClassPtr
_DLL FUNCTION __GetClassPtr (symClassName AS SYMBOL) AS PTR PASCAL:VO28RUN.__GetClassPtr
So they are in VO28RUN.DLL. But I don't see something like VO28RUNClasses.dll to reference in my X# project. So what should I add as reference in my project to use these functions? Perhaps even more important: how can I find the answer to a question like this myself?
Kees.
Re: Miscellaneous questions about converting VO code to X#
Posted: Thu Jan 18, 2024 2:24 pm
by robert
Kees,
These 2 function are VERY low level in VO and there is no easy alternative in .Net.
What are you using these for ?
Robert
Re: Miscellaneous questions about converting VO code to X#
Posted: Thu Jan 18, 2024 2:36 pm
by Kees Bouw
Hi Robert,
That was an extremely fast reply! This is one of the methods where they are used:
Code: Select all
METHOD Dispatch(oEvent) CLASS BPDataListView
LOCAL oKE AS KeyEvent
LOCAL oEvt AS @@Event
LOCAL Result AS LONG
oEvt := oEvent
Result := 0L
DO CASE
CASE oEvt:Message = WM_KEYUP
oKE := __ObjectCastClassPtr(oEvt, __GetClassPtr(#KeyEvent))
DO CASE
CASE oKE:ASCIIChar = 13 // CtrlM
IF SELF:ContextMenu <> NULL_OBJECT
SELF:ContextMenu:ShowAsPopUp(SELF)
ENDIF
ENDCASE
ENDCASE
Result := SUPER:Dispatch(oEvt)
RETURN Result
Which brings me to another small question: what do the double at-signs in "@@Event" mean?
Kees.
Re: Miscellaneous questions about converting VO code to X#
Posted: Thu Jan 18, 2024 4:28 pm
by robert
Kees,
- @@ in front of a name makes sure that the name is not seen as a keyword (EVENT is a keyword now)
- In this code you should write:
oKE := KeyEvent{oEvt}
This was changed in VO 2.8 (2009)
Robert
Re: Miscellaneous questions about converting VO code to X#
Posted: Thu Jan 18, 2024 4:45 pm
by Kees Bouw
Hi Robert,
Thank you VERY much for the fast and clear answers!
Kees.
Re: Miscellaneous questions about converting VO code to X#
Posted: Mon Jan 22, 2024 10:37 am
by Kees Bouw
Another (hopefully) easy question:
I have
in one class and
in a class that inherits from the first class.
So I get warning XS0108 which says "Use the new keyword if hiding was intended."
The "new keyword" presumably is "VIRTUAL", I have used this before when one method hides another.
But VIRTUAL does not seem to be correct when used on EXPORT line, no matter where I put it.
What should I change in the code to get rid of the warning? I prefer not to set a compiler option.
Re: Miscellaneous questions about converting VO code to X#
Posted: Mon Jan 22, 2024 10:59 am
by robert
Kees,
DotNet does not allow to have a public field (EXPORT pKey) and a property (Access PKey) with the same name.
I would recommend to rename one of the two
Robert
Re: Miscellaneous questions about converting VO code to X#
Posted: Wed Jan 24, 2024 10:08 am
by Kees Bouw
There seems to be a difference in behaviour between VO and X# regarding Init and Constructor methods. If there is a class A and a class B that inherits from A, both with Init methods, and an object of class B is created, then in VO only the Init of class B is executed. But in X#, when both A and B have Constructors, first the Constructor of A (the parent) is executed and after that the Constructor of B (the child). It gets even stranger if both Init's call a PostInit. In VO, the Init of B is executed and after that the PostInit of B. But in X# the Constructor of A is executed and after that the PostInit of B and the Constructor of B and then again the PostInit of B. Because both Constructors are executed, the PostInit of B is executed twice. If I am correct, then this is certainly something to be aware of when converting from VO to X#.
Re: Miscellaneous questions about converting VO code to X#
Posted: Wed Jan 24, 2024 10:35 am
by robert
Kees,
KeesIC2 wrote: ↑Wed Jan 24, 2024 10:08 am
There seems to be a difference in behaviour between VO and X# regarding Init and Constructor methods. If there is a class A and a class B that inherits from A, both with Init methods, and an object of class B is created, then in VO only the Init of class B is executed. But in X#, when both A and B have Constructors, first the Constructor of A (the parent) is executed and after that the Constructor of B (the child). It gets even stranger if both Init's call a PostInit. In VO, the Init of B is executed and after that the PostInit of B. But in X# the Constructor of A is executed and after that the PostInit of B and the Constructor of B and then again the PostInit of B. Because both Constructors are executed, the PostInit of B is executed twice. If I am correct, then this is certainly something to be aware of when converting from VO to X#.
It should not work this way. We support the delayed call to SUPER(). C# does not, but we have actually made some changes in the Roslyn code to allow this.
The generated code for the GUI forms depends on that. They follow the pattern:
Code: Select all
CONSTRUCTOR(params)
SELF:PreInit(params)
SUPER(params)
.. // initialization code
SELF:PostInit(params)
RETURN
So if you are seeing that the parent constructor is called before the init of the child class, then there must be something wrong.
However, if your code is NOT calling the super() constructor, then you may see a compiler generated call to the constructor of the super class.
Btw: the Roslyn code adds the initialization of class variables to the constructor. In the debugger however you will see that the locations are linked to the actual initialization code in the class.
Can you produce a (small) example?
Robert
Re: Miscellaneous questions about converting VO code to X#
Posted: Wed Jan 24, 2024 11:16 am
by Kees Bouw
This is the code I used to test:
Code: Select all
USING System
USING System.Collections.Generic
USING System.ComponentModel
USING System.Data
USING System.Drawing
USING System.Linq
USING System.Text
USING System.Threading.Tasks
USING System.Windows.Forms
BEGIN NAMESPACE WindowsFormsApplication1
PUBLIC PARTIAL CLASS Form1 ;
INHERIT System.Windows.Forms.Form
PUBLIC CONSTRUCTOR() STRICT//Form1
InitializeComponent()
RETURN
END CONSTRUCTOR
PRIVATE METHOD button1_Click(sender AS System.Object, e AS System.EventArgs) AS VOID STRICT
LOCAL oObjectChild AS DisplayInheritChild
oObjectChild := DisplayInheritChild{}
oObjectChild:Finished() // Just to prevent warning XS0219.
RETURN
END METHOD
END CLASS
CLASS DisplayInheritParent
CONSTRUCTOR() CLASS DisplayInheritParent
MessageBox.Show("DisplayInheritParent - Constructor()", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
SELF:PostInit()
RETURN
VIRTUAL METHOD PostInit() AS VOID CLASS DisplayInheritParent
MessageBox.Show("DisplayInheritParent - PostInit()", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
RETURN
END CLASS
CLASS DisplayInheritChild INHERIT DisplayInheritParent
CONSTRUCTOR() CLASS DisplayInheritChild
MessageBox.Show("DisplayInheritChild - Constructor()", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
SELF:PostInit()
RETURN
METHOD PostInit() AS VOID CLASS DisplayInheritChild
MessageBox.Show("DisplayInheritChild - PostInit()", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information)
RETURN
METHOD Finished() AS VOID CLASS DisplayInheritChild
RETURN
END CLASS
END NAMESPACE
The order in which the message boxes appear is:
DisplayInheritParent - Constructor()
DisplayInheritChild - PostInit()
DisplayInheritChild - Constructor()
DisplayInheritChild - PostInit()
But if you say "it should not work this way" then probably I am doing something wrong and I am curious to know what it is.
I have also attached the complete solution.