When I hear people who want to generate the same code into every instance of a WindowManager, I find myself thinking why not change the base class for ThisWindow and write the code just once.
To get the new behavior that appears in MyWindowManagerType
! change this ---v
ThisWindow CLASS(WindowManager)
! to this ---v
ThisWindow CLASS(MyWindowManagerType)
Steps to replace WIndowManager with MyWindowMangerType
- write MyWindowManagerType (some technical details below)
- place MyWindowManagerType.inc in a folder that ScanABC knows about
FYI: ScanABC is a list of folders where the IDE looks when you click on Refresh Classes.
The list of folders is set in:- IDE > Tools > Options > Clarion > Clarion For Windows > Version > list of “Directories scanned for ABC Classes”
- Refresh Classes
- In your APP > Global Properties > Actions > Tab[ Classes ] >
press button: Refresh Application Builder Class Information
- In your APP > Global Properties > Actions > Tab[ Classes ] >
- Select the new Class
- In your APP > Global Properties > Actions > Tab[ Classes ] >
press button: General
Select new Class for Window Manager
- In your APP > Global Properties > Actions > Tab[ Classes ] >
- Regenerate
- Compile
I wish there were embed points to create the derived class, but there are not as I write this.
There are embed points for some global objects, but those are instances, vs types.
For the ,TYPEs like the MyWindowManagerType above,
I think it would be great if we had something like:
-
Use the embeds in one APP to derive WindowManager (or other classes)
-
Generate the inc/clw into a special folder,
the folder is listed as a ScanABC
the folder appears in the .RED -
Then for other APPs, in Global Properties > Actions > Tab[ classes ] > select the derived class as you can now (after a Refresh Classes).
But since we don’t currently have this imagined system for using embeds
It’s up to programmers to write these classes by hand.
Which honestly isn’t that hard once you’ve done it once.
Now even if you’re already comfortable writing clarion classes, there are a few extra technical challenges to writing a class that can be used as a global class type in an APP
- you MUST have an ABCIncludeFile magic comment in the .INC
the comment MUST be at the top of the file ( before any compliable code )
and it MUST start in 1st column ( I don’t believe this is documented )
!ABCIncludeFile
!ABCIncludeFile(familyclass)
- note: the family class, names the * for
_*LinkMode_ and _*DLLMode_
when absent, it defaults to ABC
-
the .INC MUST appear in a ScanABC folder
while the extension of .INC is just
convention as far as the compiler is concerned
it’s a requirement for APPs -
you MUST refresh classes before you can select it
Here’s an example of an .INC file for a derived WindowManager
!ABCIncludeFile
INCLUDE('ABWindow.inc'),ONCE
MyWindowMangerType CLASS(WindowManager),TYPE,MODULE('MyWindowMangerType.clw'),LINK('MyWindowMangerType.clw',_ABCLinkMode_),DLL(_ABCDllMode_)
TakeAccepted PROCEDURE,DERIVED,BYTE,PROC
OnButtonAccepted PROCEDURE,VIRTUAL
END
and it’s matching .CLW
MEMBER()
INCLUDE('MyWindowMangerType.inc'),ONCE
MAP
END
MyWindowMangerType.TakeAccepted PROCEDURE() !,DERIVED,BYTE,PROC
CODE
IF ACCEPTED(){PROP:Type} = CREATE:Button
SELF.OnButtonAccepted()
END
RETURN Parent.TakeAccepted()
MyWindowMangerType.OnButtonAccepted() PROCEDURE!,VIRTUAL
CODE
! do something like play a sound