xsharp.eu • Miscellaneous questions about converting VO code to X#
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

Code: Select all

EXPORT PKey AS ARRAY
in one class and

Code: Select all

ACCESS PKey(NameSym)
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.