Advanced PowerBuilder

HomePrevious Lesson: Choosing Between Events and Functions
Next Lesson: Destroying an Instance

Creating an Instance

It requires only one line of code to create and display an instance of an object on the screen. The following script would create an instance of Window, Sheet and User Object respectively, with and without parameters:
/* Create an instance of a window in memory and 
display the created window on the screen */
// Open() Format 1,2
Open( WindowVariable {, ParentWindowVariable} )
Open( WindowVariable, WindowNameString {, &
ParentWindowVariable} )

The first format opens an instance of the specified window. If you want to open a child window, specify the parent window name in which you want to open the child window as the second parameter. The second format allows you to specify the window name as a string in the second parameter, and place the reference to the window instance after opening in the first parameter window variable.
// OpenWithParm() Format 1,2
OpenWithParm( WindowVariable, Parameter &
						{,ParentWindowVariable})
OpenWithParm( WinVar, Parm, WindowNameString &
						(,ParentWindowVariable})

This format works similar to the above formats, and also allow sending parameters to the opening window. The parameter is stored in the message object. In simple terms message object is nothing but a global structure variable, which is used for inter object communication. This is discussed in detail in "Inter Object Communication" topic.
/* Functions to open a window as a sheet */
OpenSheet( Windowvar {,WindowNameString}, MDIWindowName &
{, Position {, WindowArrangeStyle}} )
OpenSheetWithParm(Windowvar, Parameter {, &
WindowNameString},MDIWindowName {, Position{, &
WindowArrangeStyle}} )

These formats allow you to open a window as a sheet, in either MDI frame or MDI frame with MicroHelp window. The following example opens w_sheet in w_frame window and then cascades all windows.
OpenSheet( w_sheet, w_frame, 2, Cascaded! )
/* Functions to open a User Object. */
WindowName.OpenUserObject( User Object{, x, y} )
WindowName.OpenUserObject(User Object, &
ObjectType{, x, y })
Windowname.OpenUserObjectWithParm( User Object {, x, y })
WindowName.OpenUserObjectWithParm (User Object, &
ObjectType {, x, y })

These formats allow us to open user objects and place them in the specified window, at the specified x and y co-ordinates.

Any object you define through PowerBuilder painter, is declared as global. If you export w_variable_test window from the Library Painter and then have a look at the .SRW file, you'll see the following:
$PBExportHeader$w_variable_test.srw
forward
global type w_variable_test from Window
end type
type mle_help from multilineedit within w_variable_test
end type
type cb_3 from commandbutton within w_variable_test
end type
type cb_2 from commandbutton within w_variable_test
end type
type cb_1 from commandbutton within w_variable_test
end type
end forward

The parameter to this function may be, either the name of a window or a variable that refers to an instance of a specific window. Either of the following is correct:
/* Method 1: Specifying the window name directly */
Open(w_item_master)
/* Method 2: Using a variable */
w_item_master lWindow1
Open( lWindow1 )

The first method only allows you to define one instance of an object; this is because of how PowerBuilder allocates memory to the objects created. When you create an instance of an object, PowerBuilder allocates it some memory. If you try and call this function again, PowerBuilder simply returns this instance to you. This is because, the instance has a global scope; that means, a reference to the instance is recognized throughout the application and can't be duplicated.

The second method allows you to open more than one instance of the window, because it is basing the instance of an object on a variable that can be given a scope. Imagine that you are opening this window from a menu option. If you declare it as an instance variable, the variable is created when the menu is created and is destroyed when the menu is destroyed. This means that as long as the menu exists, the memory allocated for it is same, which allows you to open only one instance of the window, no matter how many times you try to open the window.

To open more than one instance of the window, you need to declare the window variable as local in the menu script. The local variable is created when the script starts executing and will be destroyed only when the execution of the script completes. That means that each time the script executes, a new variable is created and memory is allocated to it. This makes it possible to open more than one instance of the window.

Unfortunately, there is one problem associated with this; the external reference to other windows, except for the active window, is gone. Suppose you opened four instances of a window and with the third instance active, you may want to disable a CommandButton in the first instance. Using the above method, you don't have the ability to reference the first instance specifically, so, you can't disable the CommandButton. In interactive debugging too, you can't see other instances. In this situation, you may have to put some debug statements, something like MessageBox() for debugging.

The solution for this problem is to declare an array of instance window variables. For example:
// Declare these 2 variables as instance variables for
// the menu 
w_item_master i_item_master[]
Int InstanceNo = 1
// Script for the menu item 
OpenSheet(i_item_master[i], ParentWindow, 1, Cascaded!)
InstanceNo++

The above functions create an instance in the memory, and those instances are displayed on the screen. Sometimes, you may want to create an instance, but don't want to display on the screen. Well, for that, set the visible attribute after creating the instance. Otherwise, you can use CREATE statement. The CREATE statement is used to create an object only in memory. The syntax is as follows:
CREATE <Object Name>

At times, you may want to connect to two different databases at the same time. So, you need two transaction objects. One transaction object SQLCA is available to us by default, so, we need to create one more. The following code creates a new transaction object instance.
Transaction g_TranForSybase
g_TranForSybase = Create Transaction

Now, g_TranForSybase is available for use in the code. The following code sets proper values, by which we can use this for database connection.
g_TranForSybase.servername = &
                ProfileString( "sales.ini", "sybase", "server", "")
g_TranForSybase.logid = &
                ProfileString( "sales.ini", "sybase", "logid", "")
g_TranForSybase.logpass = &
                ProfileString( "sales.ini", "sybase", "logpass", "")
g_TranForSybase.database = &
                ProfileString( "sales.ini", "sybase", "database", "")
g_TranForSybase.dbparm = &
                ProfileString( "sales.ini", "sybase", "dbparm", "")

The following line connects to the database:
Connect using g_TranForSybase
// Error Handling...

Transaction object has no visual component, so, creating it in the memory is well enough. If you look at the exported version of the application, you can observe the CREATE statements that PowerBuilder uses to create global objects internally:
on oop_pb_impl.create
appname = "oop_pb_impl"
sqlca = create transaction
sqlda = create dynamicdescriptionarea
sqlsa = create dynamicstagingarea
error = create error
message = create message
end on

With version 5.0, we can create an instance of a class if we have the name of the class in a string. The following example lists all the menu names from a specified library and creates the selected menu in memory.
// Read All menu entries in the library and populate 
// the datawindow
dw_menus.ReSet()
dw_menus.ImportString ( Librarydirectory( &
        "userlib.pbl", DirMenu! ) )
// instance variables
menu i_Menu
String i_user_menu_name
// Get user selected menu into i_user_menu_name
i_user_menu_name = dw_menus.GetItemString( &
dw_menus.GetRow(), dw_menus.GetColumn() )
i_Menu = Create Using l_user_Menu_name
// Now you can find all menu items names, bitmap names,
// etc...

With version 5.0, you can automatically instantiate user object by setting AutoInstantiate attribute. If you set this option to true, the following line is equal to two lines following after that line.
nc_string_functions l_str_cls
// The above equals to two of the following lines, if
// "autoinstantiate" is not set
nc_string_functions l_str_cls
l_str_cls = create nc_string_functions

Till now we have seen how to create instances, now let's see how to destroy those created instances.
HomePrevious Lesson: Choosing Between Events and Functions
Next Lesson: Destroying an Instance