Miscellaneous questions about converting VO code to X#

This forum is meant for questions and discussions about the X# language and tools
User avatar
Kees Bouw
Posts: 97
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Miscellaneous questions about converting VO code to X#

Post 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.
Last edited by Kees Bouw on Thu Jan 18, 2024 2:26 pm, edited 1 time in total.
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
User avatar
Kees Bouw
Posts: 97
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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.
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
User avatar
Kees Bouw
Posts: 97
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post by Kees Bouw »

Hi Robert,

Thank you VERY much for the fast and clear answers!

Kees.
User avatar
Kees Bouw
Posts: 97
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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.
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
User avatar
Kees Bouw
Posts: 97
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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#.
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
User avatar
Kees Bouw
Posts: 97
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: Miscellaneous questions about converting VO code to X#

Post 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.
Attachments
WindowsFormsApplication1.zip
(338.77 KiB) Downloaded 31 times
Post Reply