Powerbuilder Tutorial – Anvil of Time https://anvil-of-time.com Nature Forges Everything on the Anvil of Time Thu, 06 May 2021 16:50:35 +0000 en-US hourly 1 100 Days of PowerBuilder – Tutorial – Day 9 – Window Methods https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-9-window-methods/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-9-window-methods/#comments Thu, 06 May 2021 16:50:35 +0000 https://anvil-of-time.com/?p=2311 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. Most steps/examples will be identical with any version going back to 9.

Before we go much further we need to think about common functionality within our application.  One advantage of Object Oriented Programming is the ability to reuse code which not only makes development faster but also aids in understanding and maintaining the application ‘down the road’.  So lets think about some common methods/processes for windows.

Previously we created the ‘we_postopen’ event which is posted by the window open event  To enhance our common window process flow we are expanding on this.

So now to modify the existing window.  Add the we_preopen, we_close, we_validate, we_savechange, we_save, we_cancelchanges, and we_cancel events to w_main.

Change the code in the Open event from this

THIS.PostEvent("we_postopen")

to this

THIS.EVENT TRIGGER we_preopen()

THIS.EVENT POST we_postopen()

I prefer the second syntax for triggering/posting events.

Now in the we_close event add the following

THIS.EVENT TRIGGER we_validate()

THIS.EVENT TRIGGER we_savechange()

THIS.EVENT TRIGGER we_cancel()

Close(THIS)

Hmm, something needs changing here.  We need to change the we_validate event to return a status so we can proceed to either the we_savechange or we_cancel methods.  So open the we_validate event and change the return value from (none) to “integer”

and add the following.

//validate
// do some sort of checking to see if values have changed and prompt the user
integer li_rc
li_rc = MessageBox('Save before closing','Save changes?',Question!, YesNoCancel!)
RETURN li_rc

Now go to the we_close event script and change it to:

// close 
integer li_rc
li_rc = THIS.EVENT TRIGGER we_validate()
CHOOSE CASE li_rc
	CASE 1 //yes
		THIS.EVENT TRIGGER we_savechange()
	CASE 2 // no 
                // reset things if needed
		THIS.EVENT TRIGGER we_cancelchanges()
	CASE 3 // cancel
		RETURN //prevents window from closing
END CHOOSE

Close(THIS)

So now we first trigger the we_validate event and return the Messagebox choice value. Based on that value we either save the changes, discard any changes, or cancel the action altogether.

Next remove the code from our earlier exercise from the Closequery event.  Now for demonstration purposes put MessageBox code in both the we_savechange and we_cancelchange events.  Something like this:

Messagebox('Cancel Change','we_cancelchanges')  //change wording for the we_savechange event

Now go to the ‘Exit’ button on the window and change the code to

PARENT.EVENT TRIGGER we_close()

Now when you run the program and click on the ‘Exit’ button you are prompted to save the changes. Run three times and choose each of the options (Yes, No, Cancel). You will see the two messageboxes for either Yes or No and the Messagebox close but the main window remain open for Cancel.

However, now we have to account for the user closing the window via the titlebar or ‘Alt-F4’. Go back to the Closequery event and insert following code:

// closequery
integer li_rc
li_rc = THIS.EVENT TRIGGER we_validate()
CHOOSE CASE li_rc
	CASE 1 //yes
		THIS.EVENT TRIGGER we_savechange()
	CASE 2 // no
		THIS.EVENT TRIGGER we_cancelchanges()
	CASE 3 // cancel
		RETURN 1 //prevents window from closing
END CHOOSE
RETURN 0

Notice this code isn’t much different from we_close.

Now change the code in we_save to the following;

// save the window then exit. 
// 
//insert save checking logic 

THIS.EVENT TRIGGER we_savechange()
CLOSE(THIS)

So you may wonder why don’t I use functions instead of events for some of this and my answer is that you could.  However, in the next session I will be going over some basic window inheritance and the flexibility of events will be demonstrated.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-9-window-methods/feed/ 1
100 Days of PowerBuilder – Tutorial – Day 8 – Adding a Menu https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-8-adding-a-menu/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-8-adding-a-menu/#comments Wed, 07 Apr 2021 17:46:38 +0000 https://anvil-of-time.com/?p=2285 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. Most steps/examples will be identical with any version going back to 9.

Let’s take a look at menus.  We will create a simple menu for our main application window created earlier.  Choose File – New – PB Object – Menu then click OK.

Now you have your newly created menu object called ‘untitled0’.  Notice the Menu Style on the Appearance tab of the Properties is ‘traditionalmenu!’; change this to contemporarymenu! to open up the various other options.

 

Now save the menu to the ‘firstapp’ pbl as m_main.

Right click on the ‘m_main’ menu item and choose Insert Submenu Item; give it the name ‘File’.

Then save the menu.  Now associate the menu with the main window of the application by opening the w_main object and clicking on the elipsis button next to the MenuName property.  

Now save the window and run the application.  You should see the menu:

Now granted the menu doesn’t do anything at all now but at least we know we have correctly associated it with the window.  Go back and open the menu painter.  Right click on the ‘File’ menu item and choose Insert Submenu Item.  Give it the name ‘Save’.   Once the control loses focus notice the visual example and the Name property are changed to reflect the menu item text.

Now associate a menu icon with this option by clicking on the elipsis button next to MenuImage.

Then choosing PB menu or toolbar icons

Search for ‘Save’ and then select the Save1! image, click OK, then save the menu. Open the w_main window again and add an event called ‘we_save’ and insert the following:

// save the window then exit.
//
//insert save checking logic
close(THIS)

Save the window and go back the the menu. In the clicked event of the Save menu option place the following:

parentwindow.triggerevent "we_save"

Now run the application.  From the main menu click on ‘File’ and then ‘Save’.  You should be prompted for closing the window (same functionality as from the earlier window example). Now reopen the w_main window, go to the event list and delete the ‘we_save’ event and then save the window.

Now run the application and choose Save from the File menu.  Nothing should happen now.  This shows how the triggerevent method on menus can be used to create generic functionality.  Non existing events can be triggered in PowerScript without the application crashing as would be the case of a function call.

Using Menu Methods

I consider it best practice to use menus primarily to trigger events on their parent windows.  Although menus can have their own methods to do whatever processing is desired,  I don’t believe there are any compelling reasons to architect an application this way  

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-8-adding-a-menu/feed/ 1
100 Days of PowerBuilder – Tutorial – Day 7 – Opening a Window https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-7-opening-a-window/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-7-opening-a-window/#comments Tue, 30 Mar 2021 21:13:00 +0000 https://anvil-of-time.com/?p=2250 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. Most steps/examples will be identical with any version going back to 9.

Although we have already opened the main window for our application earlier, there are some things to consider when opening windows. One of the chief concerns is the ‘responsiveness’ of the window. By this I mean what does the user see when the window opens. Does it sit there with a ‘busy’ type icon spinning away and then open? Let’s conduct an experiment.

Open the w_main form for our application and place a Multi-Line Edit control on it.

Expand it so you can see a fair amount of text and make sure the Horizontal Scrollbar property is checked. Now some code in the Open event of the window.

long ll_i, ll_et
string ls
time lt_1, lt_2< httpclient lnv_http
lnv_http = CREATE httpclient lt_1 = Now() // start time
// connect to the web service and send the request
ll_i = lnv_http.sendrequest('Get',"http://worldtimeapi.org/api/timezone/america/new_york")
IF ll_i <> 1 THEN
messagebox('http','request failed')
RETURN
END IF
// get the JSON response from the web service
lnv_http.getresponsebody(ls)
// end time
lt_2 = Now() ll_et = SecondsAfter(lt_1, lt_2)
mle_1.text = 'Start: ' + string(lt_1) + '~r~nEnd: ' + string(lt_2) + &
'~r~nElapsed: ' + String(ll_et) + '~r~n~r~nResponse: ' + ls IF IsValid(lnv_http) THEN DESTROY lnv_http

So what this code does is connect to a web service to get the current time in New York City and then puts the response JSON text into the MLE control.  Prior to connecting to the web service it gets the time and also gets the time after the call so we can see how long the ’round trip’ took.  This information is also put into the MLE text property.

Now when you run this you will get various response times based on your connection speed and latency of the web service (amongst other various things).  Regardless of the speed the window did not open until the code in the open event concluded which makes the application appear unresponsive.

To ‘improve’ the responsiveness of the application we are going to create a separate event on the window; this is known as a ‘user event’.  Click on the dropdown arrow next to the event name ‘Open’, scroll up and choose ‘(new event)’.

Now give it the name ‘ue_postopen’ (notice the top dropdown is updated when you tab off the name field.  In keeping with PB conventions the event name is prefaced with “ue_” to indicate it is a user event – you could also name it “we_” since it is a window event.  In any case none of the other parameters/etc. are changed.

Now cut the code from the ‘Open’ event and paste it here.

In the now empty ‘Open’ event place this line:

EVENT POST ue_postopen()

Or alternatively:

THIS.PostEvent("ue_postopen")

Now when you ‘post’ an event or function call it is placed onto the call stack and then executed once the current method is completed (or after other events and functions if they are already on the call stack since it is a ‘first in, first out’ type of arrangement).

When you run the application now you will see the window opens immediately and then some time passes before the MLE text is updated.  In my testing it took anywhere from 2 to 30 seconds (the default timeout).  Depending upon the situation you may have additional information messages show in the application screen so that the user understands that something is going on behind the scenes.

This type of post open functionality is normally part of most window ancestors and it used whenever any potentially long process is performed as part of the initialization of the object.  These include database calls (populating datawindows/datastores), retrieving network resources (files, images, etc.) or really anything which may take more than a second or so.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-7-opening-a-window/feed/ 1
100 Days of PowerBuilder – Tutorial – Day 6 – Adding Controls to a Form https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-6-adding-controls-to-a-form/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-6-adding-controls-to-a-form/#respond Wed, 24 Mar 2021 23:36:00 +0000 https://anvil-of-time.com/?p=2214 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. Most steps/examples will be identical with any version going back to 9.

Lets add some additional controls to our main form and check out some of the functionality of the PowerBuilder IDE. Once you have opened the main window object, choose Insert – Control from the menu.

Now I’m sure there is some sort of organizational structure behind how the entries here are listed but I haven’t taken the time to figure it out.  You can also click on the down arrow icon next to the control icon on the toolbar.

The icons within the red rectangle are the controls you can choose from.  Like many places in the IDE, the toolbar icon will take on the image from the last control chosen.  Each of the controls is assigned a default name when it is placed on the form.  The name consists of a defalt prefix and a sequence number.  You can control the prefix from within the Options dialog (menu option ‘Design – Options’).  When opening this dialog you are brought to the ‘General’ tab.

Here you can control the alignment grid (which appears on the window control) and whether controls default to a ‘3D’ appearance.

The prefixes are found on the next two tabs.

You can change these as you wish but each control must have a unique name when placed on a form within the IDE.

The Script tab defines some script editor behavior (auto indent, dashes) and controls what type of messages appear when the script is compiled (when saved or when you leave the particular script). The Event and Function List Order controls how these lists appear in the editor.

These tabs control the fonts within the script editor and when you choose to print out a script or control. Obviously some are more appropriate than others and are affected by the screen resolution of your monitor.

Coloring refers to how various statements, keywords, and etc. appear in the editor.

AutoScript is similar to Microsoft’s Intellisense where the IDE ‘guesses’ at what you are doing based on what you type in. You will need ot experiment with this to get the optimal settings for your style of programming.

So now select a SingleLineEdit (SLE) control to drop on your form.

Drop a couple more for a total of three.

The last control is ‘selected’ since it has four ‘handles’ in its corners. When an object is selected the Properties window shows information about it. Each type of object will have differing properties.

The Font tab is used to set typeface related properties of the control. Note that if you change the TextSize the size of the control does not change; you will have to adjust it yourself.

The Other tab in this case is primarily used for positional changes. Note that (nearly) all properties of controls can be manipulated from within the code of the application.

Here’s a trick to saving time when placing a like number of controls on a form. If you want to change the Font, Color, Height, etc. of a control from the defaults PB gives you when you drop it on the form, change a single copy first, select it, choose the same type of control from the menu, and then drop it on the form. The new control will have some of the same properties already assigned to the one you had selected prior to dropping it.

You can also achieve this by right clicking on a control and then choosing ‘duplicate’ from the options menu.

Manipulating Control Groups

You can select multiple controls and manipulate them as a group should you so desire. Simply hold the Control key and click each control. If you selected one too many simply Control click to unselect it. Once a group of controls is selected, the Properties window shows common elements amongst the group. If all items in a group are of the same type, all the properties are available. If multiple controls are selected (say, SingleLineEdit and CommandButton) then a smaller subset of properties are available.

Group Selected Properties (all Single Line Edit controls)

Group Selected Properties for SingleLineEdit and CommandButton

You can resize and position object groups by using the Positioning drop down toolbar

Remember that the first control selected in the group serves as the ‘master’; changing position and size will all be relative to the master control. In the case of spacing between objects the first two selected serve as the the ‘master’.

Now we have the fields sized and aligned. When designing a form it’s always important to designate the ‘focus flow’. By this I mean the order in which the controls gain focus as the user tabs through the form. This is set by the Tab Order property and can be displayed from the toolbar icon or menu option.

The tab order icon (or menu) acts as a ‘toggle’ into ‘tab setting mode’ which basically means you can’t do anything other than set the tab order until you toggle back out.

In the case of the form I’ve set up, my tab order is slightly off. The tab stops themselves are displayed in the upper left corner of the control (in red). The actual order on the form is hightlighted by the arrows which have been added to show the actual flow; not the most intuitive.

Clicking on the number of a specified tab order allows it to be changed. To ‘insert’ a control between others on a form, simply use a number between the tab numbers of the controls. Once you toggle out of tab order the tab numbers themselves are recalculated into multiples of ten.

Setting the tab order of the Exit button so it is last.

Now if you run the application, the window opens and focus is set on the first SLE field. Pressing the tab key moves the focus to the subsequent fields and then the Exit button before starting over again at the initial field.

Let’s put some functionality behind the SLE fields. Right Click on the first SLE and choose Script

This takes you into the Powerscript Editor for the Event methods of the control. Clicking on the down arrow as shown will list all of the events for this particular control. The script currently in ‘edit’ mode is highlighted.

In this case the ‘modified’ event is in edit mode. In this event script we will place code to change the background color of the field to indicate that it’s contents have been changed. The following will do this: Backcolor = RGB(255,255,0). RGB is a system function which calculates the long value of a color based on it’s red, green, and blue component values (integers from 0 to 255). In this case we are changing the value to yellow.

Now run the application, change the the contents of the first SLE, and then tab out of the field.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-6-adding-controls-to-a-form/feed/ 0
100 Days of PowerBuilder – Tutorial- Day 5 – Building up the Application Structure https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-5-building-up-the-application-structure/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-5-building-up-the-application-structure/#respond Wed, 24 Mar 2021 21:51:00 +0000 https://anvil-of-time.com/?p=2198 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. The same steps would be pretty close with any version going back to 9.

So lets get back to work on our sample application and enhance it’s functionality. Before we do this, lets get some organization to our project. The code created in PowerBuilder is stored in binary files called PowerBuilder Libraries which have the file extension of PBL. These are known as ‘pibbles’ (PBLs). All but the most elementary applications will have more than one of these files. In many instances you will use (or develop) one or more ancestor or framework level PBLs which make development easier, faster, more uniform in apperance and behavior, and (very important) to keep you from re-inventing the wheel over and over again.

In the halcyon days (PB 5 – 6.5) there were many strategies and best practices regarding the number of PBLs to have, how many objects they should contain, how to dynamically switch libraries to improve performance, and etc. Today many of the performance issues are no longer relevant due to OS and hardware improvements made since that time. Establishing a uniform structure to the contents of your PBLs which applies across the applications you develop is much more important in terms of lessening the learning curve for new developers and improving maintenance activities.

Most applications which are at least ten years old have a hodge-podge of PBLs loosely organized at best. Many may have had better structure but over time entropy took control, especially when the initial developers moved on to something else, and there was no longer anything other than individual discipline keeping things organized. The two types of sturctures I advocate are Object Centric and Module Centric.

The Object Centric model organizes libraries by object types. This gives a structure as follows

application.pbl
window.pbl
dataobject.pbl
service.pbl
business.pbl
ancestors

The Application PBL is generally very thin. By this I mean it has only a few objects. These include the Application object, a ‘Splash’ window, the MDI Frame (if its an MDI app), and maybe a specialized ‘About’ window. If the application is PFC based, the global ‘app manager’ object resides here too.

The Window PBL contains all the application specific windows.

The Dataobject PBL contains all the datawindow/datastore objects.

The Service PBL contains application specific functions, non visual objects, and application controls which do not provide business rule interaction. For example, say your application needs to know the date of the first business day after any given date and this type of calculation is needed in several places. You create a non visual object which contains all the code to do this (and any other date related stuff) and it would reside in this PBL. If you have a need to calculate Gross Margin based on various inputs you would place this in the Business PBL.

The Business PBL contains business rule objects. Processes like scrap calculations for materials processing, claims adjudication, inventory transaction processing, etc. go here.

Ancestor/Common object PBL(s) would go last and in whatever order is dictated by the framework.

Depending upon the circumstance, it may be benefitial to create separate PBL files for report dataobjects (if the application has a large number of them). Structures and Functions may be useful as well depending upon how may of these are used.

The point of this is to provide a simple ‘rule of thumb’ for any subsequent developers who have to maintain the application. It’s also easy to find common code across applications with this approach since you would generally be looking at the Service and Business PBLs.

The Module Centric model organizes libraries by application ‘sub units’. This gives a structure which might resemble this.

application.pbl
module1.pbl
module2.pbl
setups.pbl
common.pbl
ancestors

The Application PBL is also pretty thin. It contains the application object, the main window, the ‘About’ window, maybe a global transaction or app manager object.

The Module PBLs are determined by major functionality groups within the application. Examples would be ‘order entry’, ‘scheduling’, ‘payables’, etc. Within each PBL are all, or most, of the objects needed for that functionality group.

The Setups PBL is really a specialized module which groups all the ‘Maintenance’ type activities required for the other modules. These would include code or definition creation/maintenance, rules engine setup, data imports, etc.

The Common PBL contains items needed across multiple modules or applications. These objects could include a base code search window, financial calculations, a dashboard ancestor, etc.

The Ancestor PBL(s) again go last.

This type of structure captures common functionality within the PBL allowing for easier sharing amongst applications. If even a small subset of windows is needed somewhere else, you would only have to include a single PBL in the other application library list. This structure has a more ‘organic’ feel to it and can become very confusing if growth is not managed.

Common Considerations

The PBL files themselves should be named so there are no duplicates amongst all the applications. Generally an application designator is used, e.g., abc_app.pbl, abc_window.pbl, or abc_setups.pbl.

Each PBL should reside in its own folder. This is very important for source control reasons. Name the folder the same as the name of the pbl, i.e., ‘abc_app’ contains the ‘abc_app.pbl’.

Often you will not really know how large a set of objects you will have when you start building an application. This makes setting a limit to the number of objects a PBL contains difficult. If you start to exceed 100 or so objects you might want to create a second library.

What You Don’t Want

MB_MODS9_17.PBL
MB_MODS9_30.PBL
MB_MODS.PBL
WIN95NT.PBL
MAIN.PBL
CEMAIN.PBL
ULSUPPORT.PBL
ULDW.PBL
ULDW2.PBL
MIKE.PBL
PFC.PBL
PURCHASE.PBL
ULDW_2.PBL
OBSOLETE.PBL
ANCMAIN.PBL…

Have fun with this one…

Creating and Adding a Library

Go to File – New – Select the Library Tab, then OK

Click on the Elipsis to open the File Dialog window

Navigate to the appropriate location to hold the new file, create the folder,  name the file, then Save

The new library appears in the Library Treeview.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-5-building-up-the-application-structure/feed/ 0
100 Days of PowerBuilder – Tutorial – Day 4: A Look at the IDE https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-4-a-look-at-the-ide/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-4-a-look-at-the-ide/#comments Wed, 17 Mar 2021 01:54:00 +0000 https://anvil-of-time.com/?p=2139 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. The same steps would be pretty close with any version going back to 9.

Mastering the PowerBuilder Integrated Development Environment (IDE) is the key to becoming a successful PB developer. As is normally the case with an IDE, there are many ways to accomplish the same task and each developer will create their own processes to do so. In this discussion we will go over some common configuration changes which should enhance productivity within the PB IDE.

Here again is the standard screen normally presented after PowerBuilder is installed and run for the first few items. Now it’s time to banish this since we no longer need it. Select the ‘Reload last workspace…’ option and unselect the ‘Show this dialog…’ and then close the window.

Now from here we have selected our ‘100day’ target and opened the ‘w_main’ object in the IDE. The system treeview on the left is a nice navigational tool but it is always on top. Sure we can resize it or move it to another place but we still have the issue that it reduces the working area within the IDE. Close this frame altogether.

While we are at it, lets set up some system options to make things a bit more friendly. Open the System Options dialogue.

Unselect the ‘Automatically Clear Output…’ option. This is especially important when searching through the code within the IDE. If you leave this option checked, previous search results are cleared; if you have a photographic memory then leave it checked. Select the ‘Disable database connection when compiling…’ option. This prevents the IDE from attempting to connect to the default database when performing a build (normally this is not important).

On the Workspaces tab you should have the ‘Reopen workspace…’ option checked.

Remember to click OK to save these changes.

Getting back to the IDE we see that the working area is fairly large now and encompasses almost all of the space within the IDE. To view our workspace and the associated object we need to bring up the Library Painter. Choose the Library Icon from the toolbar.

Notice the default location is My Computer which is of limited use. The library painter is very similar to the Explorer window in Windows. The left treeview is for navigation and the right is the detail. Right click on the treeview on the right.

Choose the Set Root option and then ‘Current Workspace’

Now when you open the Library Painter you see the Workspace treeview to the left and the current object pane on the left.

While in the Library Painter we can set some options, first on the General Tab

and then in the Include Tab.

I normally don’t make any changes here to the defaults.

Now when we click on an object to open it we see that the script painter opens much larger and is on top of the library painter.

So if we take a closer look at the Script Painter for our window we have created we have the basic layout as shown.

Along the bottom of the ‘working area’ are a series of tabs.

These show the visual layout of the object, the current script (in our case the closequery event script), the list of Events, the list of Functions, and the Declare Instance Variables script.

On the right side of the working area is the Properties pane.

Along the top are a series of tabs showing various properties. These tabs (and properties) change based on the object selected in the Layout tab of the window or from the Control list (shown below).

Along the bottom of the Properties pane are tabs for the Properties, the Control List, and the Non-Visual Object List

If you right click within the General properties area on the Properties tab you can change the layout of the tabs. The default is Labels on Top.

Here is the appearance when Labels On Left is chosen.

In this mode the information is shown in less space.

The Control List tab for our sample application looks like this.

You can select another control by clicking on it from the list. In this case we have two controls, the main window and the exit button.

You can control the various panes shown in the script painter from the View menu option. Here we are choosing to have the Event List in its own pane.

Since our system option is to have Horizontal Windows dominate the event list shows on the bottom. Not too helpful in my book.

Move the pointer over the separation bar of the Event List and the title bar appears. From this point you can ‘pin’ the titlebar by clicking on the pushpin icon.

Drag on the titlebar with the pointer to change the location of this pane. Move it to the tab area below the Properties pane (or some other location). You will see a shadow box appear indicating the location will receive the dropped pane.

Now the Properties pane is ‘split’ into two with the newly dragged Event List on the bottom.

Do the same with the Function List so now you have both lists (as tabs) underneath the Properties pane. You can now experiment with changing the Properties pane width to give your script pane the most area possible.

If you really screw things up or just want to start over, go to the View menu, choose Layouts and then (Default). You can also save layouts here once you come up with one or more you really like.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-4-a-look-at-the-ide/feed/ 1
100 Days of PowerBuilder – Tutorial – Day 3: Window Properties https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-3-window-properties/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-3-window-properties/#respond Wed, 17 Mar 2021 01:51:00 +0000 https://anvil-of-time.com/?p=2128 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. The same steps would be pretty close with any version going back to 9.

Continuing with the window we created on Day 2 (w_main), lets look at some of the various properties associated with it. Locate the window on the system tree and double click on it. This should ‘open’ it in what is called a ‘painter’. I call this type an ‘Edit Painter’ but it is also referred to as a ‘Window Painter’ since the object we are working on is a window.

Painters have a ‘view’ menu that can be used for opening various views. Each painter has a default layout of views which can be rearranged or hidden to suit your needs. You are able to save your personal layout of views using the ‘View – Layouts – Manage’ menu option. Remember ‘View – Layouts – (Default)’ option as this can save you a bunch of frustration when you jumble things up and close stuff you really want to see.

Anyway, we are looking for the Properties View of our window. In the default layout it is on the right side of the IDE and should look something like this:

Title – the title of the window; normally displayed in the window’s TitleBar
set in code: w_main.title = ‘100 Days of PowerBuilder’

Tag – this is often used to set the ‘microhelp’ area of a MDI frame. It can also be used to provide custom functionality based on it’s content. To set in code: w_main.tag = ‘Main application window’

MenuName – the name of the menu object associated with the window

Visible – can the window be seen?

Enabled – controls whether the window can have focus. boolean value (TRUE/FALSE) If this is FALSE (not checked) and is the main starting window of your application, when you run the app nothing will happen.

TitleBar – always TRUE for Main widow types.

ControlMenu – controls whether the Control Menu box displays in the TitleBar

MaxBox – controls whether the Maximize box displays in the TitleBar

MinBox – controls whether the Minimize box displays in the TitleBar

ClientEdge – Does the client area of the window appear sunken within it’s frame

PaletteWindow – used for Popup windows.

ContextHelp – used for Response windows.

RightToLeft – if the operating system supports right to left display, specifies how the characters should be displayed.

Center – causes the window to be centered when created

Resizable – is the window able to be resized?

Border – does the window have a border (TRUE if window type Main).

WindowType – This is set at design time and cannot be changed during runtime.

WindowState – specifies the window state when opened (Max, Min, or as designed)

BackColor – the background color

MDIClient Color – only for MDI frames

Icon – the icon displayed in the titlebar.

Transparency (%) – 0 – 100 value with 0 being totally opaque

OpenAnimation – how the window opens

CloseAnimation – how the window closes

AnimationTime(ms) – animation time in miliseconds – related to Open/Close animations

WindowDockState – relates to MDI applications and how the window appears

The Scroll tab contains settings used if the windows display area is smaller than the layout of the controls within it. The HScrollBar and VScrollBar settings allow the user to move around to see all of the window contents if needed.

The Toolbar tab is used to control the Toolbar in MDI frame windows.

These settings control the windows dimensions, initial position on the screen, pointer image, and user accessibility.

Position

X – The horizontal coordinate of the window where the upper right corner of the display is zero (0).

Y – The vertical coordinate of the window where the upper right corner of the display is zero (0).

Width – The width of the window. This dimension starts from the X position.

Height – The height of the window. This dimension starts from the Y position.

Pointer

Pointer – The image displayed when the pointer is over the window.

Accessibility

These properties are used when designing applications in compliance with various standards regarding use by individuals with disabilities. More information can be found in the Appeon PowerBuilder Help Guide.

As of PowerBuilder 2019 R2 Docking is obsolete.

Notes on the above properties

The various properties which have check boxes next to them are all boolean values (TRUE/FALSE).

Many of the drop down lists show Enumerated Values which are specific to PowerBuilder.

All window measurements are in PowerBuilder units (PBUs). A PBU is defined in terms of logical inches. The size of a logical inch is defined by the operating system (OS) as a specific number of pixels. The number is dependent on the display device. Windows typically uses 96 pixels per logical inch for small fonts and 120 pixels per logical inch for large fonts.

The window coordinates system can take a bit of getting used to since the Y position is opposite of what is taught when you learn about Cartesian coordinates. Also remember that quite often you will need to convert positions into Pixels when interacting with the OS; naturally there are methods to convert PBUs to Pixels and vice versa.

For image file designations in general you can choose items from folders available to your PC during design time. When you do this, PowerBuilder will insert the full path into the specified setting (icon, pointer, etc.). You should always remove the file path from the entry, leaving only the file name. Any graphic resources should be placed in a common folder which is contained within the PATH on your PC. If you do not do this and someone else runs your application who has a different folder structure (or the file is no longer in the location specified), these images will be missing (some will display as a red X or just be blank).

These properties can easily be experimented with by changing them in the painter, saving, then running the application. You can even set the window to be invisible or disabled – just be prepared to bring up the task manager and kill the app since you won’t be able to get to the window.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-3-window-properties/feed/ 0
100 Days of PowerBuilder – Tutorial – Day 2: Creating a Main Application Window https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-2-creating-a-main-application-window/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-2-creating-a-main-application-window/#respond Fri, 12 Mar 2021 22:48:00 +0000 https://anvil-of-time.com/?p=2092 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. The same steps would be pretty close with any version going back to 9.

For the purposes of this exercise I will be creating a Windows based application with a Single Document Interface (SDI). Later installments of the project will cover the other main interface type, MDI (Multiple Document Interface).

If you re-start PowerBuilder from the conclusion of our last session you will again be greeted with the ‘Welcome’ page.

At this point you may wish to check the last checkbox, ‘Reload last workspace…’. This will have PB automatically begin each session with the previous session’s workspace open within the IDE. As time goes on you will probably uncheck the ‘Show this dialog box…’ option to dispense with the Welcome window altogether.

To add a ‘main’ window to the application choose ‘File – New’ which presents you with the following dialog window.

Select ‘Window’ and click ‘OK’. We will go over the other items in later sessions. By default the script window is opened for the new window (called ‘Untitled’ since it has just been created) in the ‘Open’ event. Lets set some of the window’s propreties right off the bat. Click on the Properties tab on the control list (lower left of screen).

This window shows the entire PB IDE so lets take a quick overview. The top portion contains all the various menu bars, the left frame contains the system tree, the bottom frame contains the output (you can toggle these visible/invisible via the Window menu option), and the right frame is the current object editor (which includes the scripts and layout tabs) as well as the object properties frame.

The toolbars change depending upon which area of the IDE you are working in. To maximize the ‘working area’ (the area containing the scripts and layout) drag the toolbar sections from the third row up to the first two rows. See the start and end examples:

Okay, back to the window properties. Give the window a Title as shown below. All of the other defaults are fine for now

Now lets drop an object on the window to provide some basic functionality. In this case a button to close the window. Click on the Layout tab at the bottom of the IDE to display the window form. From the toolbar click on the small down arrow next to the Add Control icon.

This brings up a subtoolbar with various controls you can place on the window. Choose (click) the command button option as shown then click on the toolbar icon to tell the IDE you are going to place a command button on some other control.

(Note about the add control icon, the icon on the IDE toolbar changes to the last control chosen so it will not always appear as a button.)

Click on the window form to place the command button. Once place the control is ‘selected’ allowing for resizing and repositioning as needed. Move the button to the lower right corner of the window frame.

Note the properties section of IDE changes to those of the button just added. Change the Text from ‘none’ to ‘Exit’ since that is the function of the button. Right click on the button control and choose ‘Script’ from the menu. This takes you to the script portion of the control and, in the case of a command button, to the ‘clicked’ event. If you click on the down arrow in the Event list of the control, you see all of the system defined events for this type of control.

Remain in the clicked event script by clicking outside the dropdown. In the event script insert the following code:

close()

Okay, so what is this doing? Well, the button is used to trigger a method on the main window, in this case the Close function.

Now Save the window. This brings up the Save Window dialog.

In this dialog we give the window a name (w_main), some comments, and select which library in our target we wish to save it in. Since we have only one library (PBL file) our choices are limited. Note the section below the window name. This area lists other objects in the currently selected library of the same type (in our case a window). Since this is the first window we are saving, the list is empty.

Now click the OK button.

Okay, something’s not correct.

The section below the event script has a message indicating an error. If there were multiple lines in the script above, you could click on the error messages and you would be taken to the incorrect line. In our case we are missing an argument to the function. To correct the error change the script to:

Close(Parent)

In this case the close method requires the name of the window it’s going to close. The pronoun ‘Parent’ is used to refer to the button’s containing control which is in this case a window. A window is the Parent of all of the controls which are directly placed upon it.

Now save the window. You will have to put in information in the window save dialog again in order to save it.

Now code the ‘Closequery’ event on the window. The button click will call the close function on the window. This function will first call the ‘closequery’ event and the ‘close’ event on the window. This allows for any preprocessing which may need to occur prior to the close of the window. Right click on the window, choose script, and then choose closequery from the dropdown. Insert the following code:

IF Messagebox(‘Hello World’,’Close the window?’, Question!, YesNo!) = 2 THEN
RETURN 1
END IF

This causes a messagebox window prompting a response from the user. The first string of the function is the messagebox title, the second is the message, the third is the icon, and the fourth is the choices the user has. Each choice returns a numerical value, in this case a 2 indicates the user pressed ‘No’. The closequery event can be used to prevent the close of the window by returning a value of 1.

The values “Question!” and “YesNo!” are enumerated datatypes specific to PowerScript and always end with an exclamation point.

Save the window again and then click on the Run icon.

Now another message indicating something else is missing.

Click ok and add the following:

Open(w_main)

This tells the application to open the window object ‘w_main’ when the application launches.

Now save and run the application.

Click Exit.

Click Yes to exit the app.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-2-creating-a-main-application-window/feed/ 0
100 Days of PowerBuilder – Tutorial – Day 1: Creating a Workspace https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-1-creating-a-workspace/ https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-1-creating-a-workspace/#comments Fri, 12 Mar 2021 21:59:00 +0000 https://anvil-of-time.com/?p=2079 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder 2019 R3. The same steps would be pretty close with any version going back to 9.

When you first install PowerBuilder and the tool is launched, you are presented with a ‘Welcome to PowerBuilder’ dialog window asking you to tell the application what you want to do.

Initially the infomation presented won’t mean much to a beginning PB user but what PowerBuilder calls a ‘workspace’ roughly corresponds to a ‘Project’ in the Visual Studio / .Net world. Within a workspace is a target which you can think of as an application or object / component collection. You may have many targets inside a workspace but generally there is a one to one relationship between them.

For this exercise lets just start things off fresh and pick the Create new workspace and target selection.

Here is a standard Windows File create type dialog allowing you to choose where the workspace file will be created. As you can see the file is created with the extension ‘.PBW’. I have gotten into the habit of creating a folder under my user name called ‘MyCode’ which then has subfolders (PB, SQL, VisualStudio, etc.) for the types of code I create. Within the PB folder I create a new folder for each workspace/project.

Once you create this the target creation response window appears.

For our purposes we are creating a new application so highlight the appropriate icon and click ‘OK’. You now are presented with a window to create the Application, Library file, and Target file. Notice my initial choice for an Application Name – ‘first’ – and the error message on the lower left. Apparently you cannot create an app called ‘first’ so I changed it to ‘firstapp’.

The default is to create the target and application files in the same location but this can be changed is desired. I recommend using the same location for the target and application files to keep things simple and easy to keep track of.

After this process is complete you have the shell of the application completed. There are now three main files created by PB – the workspace (.PBW), the target (.PBT), and the application library (.PBL). The first two are text files and can be viewed by any editor. The PBL or ‘pibble’ file is binary and makes up the core of your PB application. PBL (PowerBuilder Library) files contain all of the objects and code making up an application while in the PB Integrated Development Envionment. They cannot be directly modified outside of the PB IDE.

After creating the application you can view the newly created files and objects in the System Tree (Window – System Tree menu option). At the base is the workspace with all associated targets underneath (we only have one). Opening the firstapp target displays all the libraries (pibbles) – at this time we only have the initial one created by the wizard. Opening the firstapp.pbl on the treeview shows the objects contained within it – initially there is only the application object (firstapp in our example).

At this time you can set some of the initial defaults used when coding the application. If you doubleclick on the application object you bring up the Object Painter, click on the Additional Properties button.

Within the Application Properties dialog you can set the default font to be used as you create and code objects within the application. These are set on the Text, Column, Header, and Label Font tabs. The Icon tab is where you set the icon to be used when the application runs (in the upper left corner of windows). The Variable Types are used to set user defined global variables which will be discussed at a later time. RichTextEdit is for designating what RTE control is used. Themes allow you to use and set a theme. PDF Export is for designating exporting to PDF.

]]>
https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-tutorial-day-1-creating-a-workspace/feed/ 2
100 Days of PowerBuilder – Day 6 – Adding Controls to a Form https://anvil-of-time.com/powerbuilder/100-days-of-powerbuilder-day-6-adding-controls-to-a-form/ Mon, 30 Apr 2012 22:06:43 +0000 http://anvil-of-time.com/wordpress/?p=1279 This is part of my project ‘100 Days of PowerBuilder’ which is a series of discussions focused on basic PowerBuilder development.

Note: This article is written with examples created in PowerBuilder version 12.5. Most steps/examples will be identical with any version going back to 9.

Lets add some additional controls to our main form and check out some of the functionality of the PowerBuilder IDE. Once you have opened the main window object, choose Insert – Control from the menu.

Now I’m sure there is some sort of organizational structure behind how the entries here are listed but I haven’t taken the time to figure it out.  You can also click on the down arrow icon next to the control icon on the toolbar.

The icons within the red rectangle are the controls you can choose from.  Like many places in the IDE, the toolbar icon will take on the image from the last control chosen.  Each of the controls is assigned a default name when it is placed on the form.  The name consists of a defalt prefix and a sequence number.  You can control the prefix from within the Options dialog (menu option ‘Design – Options’).  When opening this dialog you are brought to the ‘General’ tab.

Here you can control the alignment grid (which appears on the window control) and whether controls default to a ‘3D’ appearance.

The prefixes are found on the next two tabs.

 

You can change these as you wish but each control must have a unique name when placed on a form within the IDE.

The Script tab defines some script editor behavior (auto indent, dashes) and controls what type of messages appear when the script is compiled (when saved or when you leave the particular script). The Event and Function List Order contols how these lists appear in the editor.

These tabs control the fonts within the script editor and when you choose to print out a script or control. Obviously some are more appropriate than others and are affected by the screen resolution of your monitor. If you change the font here you will need to exit and restart PB to apply the changes.

Coloring refers to how various statements, keywords, and ect. appear in the editor.

AutoScript is similar to Microsoft’s Intellisense where the IDE ‘guesses’ at what you are doing based on what you type in. You will need ot experiment with this to get the optimal settings for your style of programming.

So now select a SingleLineEdit (SLE) control to drop on your form.

Drop a couple more for a total of three.

The last control is ‘selected’ since it has four ‘handles’ in its corners. When an object is selected the Properties window shows information about it. Each type of object will have differing properties.

The Font tab is used to set typeface related properties of the control. Note that if you change the TextSize the size of the control does not change; you will have to adjust it yourself.

The Other tab in this case is primarily used for positional changes. Note that (nearly) all properties of controls can be manipulated from within the code of the application.

Here’s a trick to saving time when placing a like number of controls on a form. If you want to change the Font, Color, Height, etc. of a control from the defaults PB gives you when you drop it on the form, change a single copy first, select it, choose the same type of control from the menu, and then drop it on the form. The new control will have some of the same properties already assigned to the one you had selected prior to dropping it.

You can also achieve this by right clicking on a control and then choosing ‘duplicate’ from the options menu.

Manipulating Control Groups

You can select multiple controls and manipulate them as a group should you so desire. Simply hold the Control key and click each control. If you selected one too many simply Control click to unselect it. Once a group of controls is selected, the Properties window shows common elements amongst the group. If all items in a group are of the same type, all the properties are available. If multiple controls are selected (say, SingleLineEdit and CommandButton) then a smaller subset of properties are available.

Group Selected Properties


Group Selected Properties for SingleLineEdit and CommandButton

You can resize and position object groups by using the Positioning drop down toolbar


Remember that the first control selected in the group serves as the ‘master’; changing position and size will all be relative to the master control. In the case of spacing between objects the first two selected serve as the the ‘master’.

Now we have the fields sized and aligned. When designing a form it’s always important to designate the ‘focus flow’. By this I mean the order in which the controls gain focus as the user tabs through the form. This is set by the Tab Order property and can be displayed from the toolbar icon or menu option.

The tab order icon (or menu) acts as a ‘toggle’ into ‘tab setting mode’ which basically means you can’t do anything other than set the tab order until you toggle back out.

In the case of the form I’ve set up, my tab order is slightly off. The tab stops themselves are displayed in the upper left corner of the control (in red). The actual order on the form is hightlighted by the arrows which have been added to show the actual flow; not the most intuitive.

Clicking on the number of a specified tab order allows it to be changed. To ‘insert’ a control between others on a form, simply use a number between the tab numbers of the controls. Once you toggle out of tab order the tab numbers themselves are recalculated into multiples of ten.

Setting the tab order of the Exit button so it is last.

Now if you run the application, the window opens and focus is set on the first SLE field. Pressing the tab key moves the focus to the subsequent fields and then the Exit button before starting over again at the initial field.

Let’s put some functionality behind the SLE fields. Right Click on the first SLE and choose Script

This takes you into the Powerscript Editor for the Event methods of the control. Clicking on the down arrow as shown will list all of the events for this particular control. The script currently in ‘edit’ mode is highlighted.

In this case the ‘modified’ event is in edit mode. In this event script we will place code to change the background color of the field to indicate that it’s contents have been changed. The following will do this: Backcolor = RGB(255,255,0). RGB is a system function which calculates the long value of a color based on it’s red, green, and blue component values (integers from 0 to 255). In this case we are changing the value to yellow.

Now run the application, change the the contents of the first SLE, and then tab out of the field.

]]>