Tech Articles


The ClassDefinition Object (Part 1)


The ClassDefinition object was introduced in PowerBuilder 6.0 a long time ago. It allows you to retrieve information for an object at runtime. Most of us didn't pay too much attention to this object and it only attracts our attention when we see it in the debugger.

In this article I provide an overview of the ClassDefinition object and related objects and explain the most important properties of these objects. I also include a step-by-step guide on how to build a simple object browser. This browser has a limited functionality like the browser included in the PowerBuilder runtime environment and can't replace products like PBLPeeper by Terry Voth or PBBrowser by OOWidgets.

The ClassDefinition Object Hierarchy
The classdefinitionobject is a descendant of the pbtocppobject. It's the ancestor of all the other objects used to describe the PowerBuilder objects. Each object in PowerBuilder has one property named ClassDefinition that references the ClassDefinition of this object.

The objects serve the following purpose:

  • ArrayBounds: Information about the boundary of an array variable
  • EnumerationItemDefinition: Name and value of an enumerated value
  • ScriptDefinition: All information about a script
  • ClassDefinition: Information about a class
  • EnumerationDefinition: Information concerning an enumerated data type
  • SimpleTypeDefinition: Information about the type of a scalar variable
  • VariableCardinalityDefinition: Provides information to the cardinality of a variable
  • VariableDefinition: All information of a variable, property, or argument

At first glance, this looks quite complex as we didn't even touch the properties of the various classes. To get a good start we need to take a closer look at the ClassDefinition object.

First Steps
Create an application with a window. To access the ClassDefinition object of any object, without having to instantiate the object, use the function FindClassDefinition. The first argument of the function is the name of the class; the second argument is an optional array of strings defining a library list. If the second argument is omitted, the current library list is searched. Place the following code in the open event of the window. It gets the ClassDefinition object of the window using the name of the window class and displays the library name where your window object is stored.

This.Title = FindClassDefinition( ClassName() ).LibraryName

You can either run the window or open it in the application object. Running the application allows you to debug and inspect additional properties of the ClassDefinition object. I would categorize them into two groups. The first group contains properties describing the object. These are properties like Name, DataTypeOf, IsVisualType, etc. In the other group are properties that describe the data "within" the object such as NestedClassList, ScriptList, or VariableList and ParentClass for a NestedClass.

Add a treeview control to the window, check LinesAtRoot, and put the code from Listing 1(link at the bottom of the article) into the open event of the window. First, we retrieve the ClassDefinition object and use the property name to add the window name as a first entry in the treeview. Now we loop over every variable of the window (stored in VariableList) and add the name of the variable as a child to the window name entry. With these few lines we already see some information regarding the variables of this window.

In the script from Listing 1 we used the VariableList property (an array of VariableDefinitionObjects) that lists all the variables of a class. For a closer look at the nested classes of the window, use the NestedClassList property of the ClassDefinition object. The NestedClassList is an array of ClassDefinition objects describing the nested classes of an object (the treeview control in our example window). The code from Listing 2 shows the nested classes in the treeview. Play around by adding some more controls to the window. If you replace the NestedClassList in the script with the ScriptList property, which is an array of ScriptDefinition objects, the events and functions of the window are shown in the treeview.

Let's use the script from Listing 1 and add the initial value of the variable to the treeview label. Add the following code for the label in the InsertItemLast function and run the application.

+ ': ' + String( lcd_Window.VariableList[ll_Counter].InitialValue)

Behind each variable you'll see the initial value of the variable as long as the variable is a simple type and not an enumerated type, for example, toolbaralignment.

The Browser
After getting an idea on how the ClassDefinition object works, we start working on the browser (see Figure 2). The application is an MDI application that allows analyzing more than one PowerBuilder application at once.

First we create a MDI frame window (w_frame) with a menu (m_frame) and a sheet window (w_main). Choose either an application icon or a library-related icon for the windows. The sheet requires no menu on its own. The main menu should include an entry File/Open and File/Exit. You can either create this from scratch or use the Template Application Wizard in the PowerBuilder IDE.

Getting the Library List
Before we can analyze an application we have to choose one and determine its library list. The application target file (PBT) contains the information that's needed. First we create an event on the frame window called ue_opentarget. Place the code from Listing 3 in this event. The user can choose a target file in this event and the window w_main will be opened with the file name passed to it as an argument. Call the event ue_opentarget from the frame menu File/Open menu item. On the window w_main, declare an instance variable called il_LibList[] of type string array. Next, create a function of_ParseLibList to get the application name and library list from the target file. The PBT file is a text file that contains the definition of a target. The line begins with a keyword followed by a space and the data, whereas the data is enclosed in double quotes. The following lines show the PBT file for the object browser.

Save Format v3.0(19990112)
appname "myobjectbrowser";
applib "mob.pbl";
liblist "mob.pbl";
type "pb";

For our application we need the keyword appname to determine the name of the application and the keyword liblist for the library list. In Listing 4 we parse the PBT file by looping through each line and check for the key appname. As soon as we find it, we remove the double quotes and set the title of the window to the name of the application. We continue looping until the key liblist is found. Having found the key, we can leave the loop and start parsing the line found. Each PBL entry is separated by a semicolon. We split the line and store each library as an entry in the il_LibList array together with the directory where it's located. Using PFC would have made some tasks easier but I want to keep the application small.

Place a treeview control with LinesAtRoot checked on the left half of the window w_main and a multilineedit control on the right half of the window. You may add some code to resize them dynamically when the window size changes. We need quite a lot of treeview pictures in the application. Set the property PictureMaskColor to silver and define the pictures in the treeview and the picture constants in the instance variables section according to Table 1 (in the listings file). Since we used the last picture of the control as an overlay picture, place the following code in the constructor event of the treeview control:

This.SetOverlayPicture(1, PICT_OVERLAY)

In the open event of the window w_main call the function of_ParseLibList. We pass message.stringparm as an argument to this function as this is the target file passed to the window w_main on opening it. The code to call the function and fill the treeview can be found in Listing 5. The name of the library is shown without path information as the path information is stored in the data property of the treeviewitem. The children property is set to TRUE to show the plus sign in front of the library entry. This allows the coding the drill down in the itemexpanding event.

In the next article we'll continue to work on the browser. We'll read the objects from the PBL and drill down on them.

Download all the source from our website at: https://www.dropbox.com/s/odksu9rsgttqxzy/SourceClassDefinition.txt?dl=1

Comments (0)
There are no comments posted here yet

Find Articles by Tag

Source Control CI/CD Validation PostgreSQL ODBC driver PFC Script Event Debugger REST OAuth 2.0 Text Menu Automated Testing Jenkins SDK PostgreSQL Export Windows OS Web Service Proxy DataWindow Import Event Handler OLE BLOB MessageBox PBNI Design Android SQL Export JSON Deployment iOS OrcaScript RichTextEdit Control RibbonBar Builder Trial Sort Git SqlModelMapper Elevate Conference IDE OAuth Authorization Database Table Filter PBVM Linux OS Windows 10 Icons COM Interface PowerScript (PS) Icon Charts XML API JSONParser Variable Expression Syntax Platform Bug SQL Server Performance Database Object PowerBuilder Compiler Encoding DLL UI JSON UI Modernization UI Themes Oracle PBDOM InfoMaker TreeView RibbonBar Web API PDFlib .NET Assembly Database RESTClient ODBC SOAP PowerServer Web GhostScript Event Handling Azure CoderObject Data Stored Procedure 64-bit Open Source Database Profile CrypterObject .NET DataStore Authentication PDF Source Code Configuration JSONGenerator Window Branch & Merge Transaction HTTPClient Database Table Data TortoiseGit PowerBuilder (Appeon) Database Connection DevOps Resize Array Messagging DataType C# PowerBuilder Debug DataWindow JSON Import JSON Excel Application WebBrowser Class SnapDevelop .NET Std Framework Outlook TFS Testing SVN NativePDF WinAPI Migration 32-bit External Functions Graph PowerServer Mobile Debugging SqlExecutor Database Painter Database Table Schema File License DragDrop TLS/SSL Encryption Installation Model Visual Studio SnapObjects ActiveX Service Repository Error Mobile