0% found this document useful (0 votes)
41 views308 pages

PB Book Part 1

PowerBuilder is an object-oriented development tool used to create client/server applications. It allows developers to create applications that can be deployed as clients, middle-tier applications, or both. PowerBuilder provides strong database connectivity, supports multiple platforms, and allows applications to be deployed on the web. It includes features like data windows, embedded SQL, remote procedure calls, OLE 2.0 support, and more.

Uploaded by

YOGENDRA SINGH
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views308 pages

PB Book Part 1

PowerBuilder is an object-oriented development tool used to create client/server applications. It allows developers to create applications that can be deployed as clients, middle-tier applications, or both. PowerBuilder provides strong database connectivity, supports multiple platforms, and allows applications to be deployed on the web. It includes features like data windows, embedded SQL, remote procedure calls, OLE 2.0 support, and more.

Uploaded by

YOGENDRA SINGH
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 308

Introduction to PowerBuilder

PowerBuilder is a 4GL client / server enterprise development tool. Its strongest strength is database
connectivity and object-orientation implementation. In its initial releases, PowerBuilder was just used
as a client --talking to the database server directly. However from version 5.0 onwards PowerBuilder
applications can be deployed as client, as a middle tier application or both. With version 6.0, it
supports transaction servers such as Jaguar CTS and Microsoft Transaction Server.

After this session you will get an understanding of:

PowerBuilder features
Powersoft family of products
Various PowerBuilder editions and features available in each edition

Estimated session time: 30+ minutes

Prerequisites:

Some knowledge about client/server applications would be helpful but not


mandatory.

PowerBuilder Features

The following is an overview of PowerBuilder features.

Object-Orientation Implementation: Supports inheritance, encapsulation and polymorphism,


with the ability to overload methods at the same object without using inheritance for the same. You
need to create all the classes using GUI painters, and PowerBuilder does all the dog work, behind
the scenes.

SQL Support: PowerBuilder supports SQL and Stored Procedures using DataWindow and
embedded/dynamic SQL and remote procedure calls.

DataWindow: DataWindow control is the heart of PowerBuilder and is used to display data in a
wide variety of presentation styles --Freeform, Tabular, Grid, Labels, Group, N-up, RichText edit,
Graph, Crosstab, OLE 2.0 and Composite -- by executing SELECT statements or Stored Procedures in
the database. They can also be populated programmatically. DataWindow automatically updates
the datasource just by writing a few lines of PowerScript code.

Embedded/Dynamic SQL: PowerBuilder supports both embedded and dynamic SQL, including
scrollable cursors and Stored Procedure execution.

Remote Procedure Calls: It also supports calling Stored Procedures and procedures using
function-calling notation (programmers in the industry call this 'remote procedure calls' even
though the actual meaning of 'remote procedure call' is differs from this).
Database Connectivity: Database connectivity is its strong point.

ODBC Drivers: Supports all popular databases --Sybase/Microsoft SQL Server, Informix, Oracle,
and DB2-- using ODBC 3.0 drivers.

Native Database Drivers: Provides native database drivers for Oracle 8.0, Informix 6.2, Sybase
SQL Server 11.1 and Sybase Adaptive Server Enterprise 11.5.

Dynamic Data Exchange: PowerBuilder supports DDE at window object level. PowerBuilder
application can act as a DDE client or DDE server or both.

OLE 2.0 Support: PowerBuilder supports OLE 2.0 including OLE 2.0 automation from version 4.0
onwards.

OLE 2.0 Window Control: Acts as an OLE 2.0 container and OCX Controls can also be
inserted.

OLE 2.0 - DataWindow:

DataWindow Presentation Style: Data can be displayed in any of the OLE 2.0 server's
format.

OCX Control: OCX control can be inserted in DataWindow like any other object.

OLE 2.0 Automation: This feature was introduced in version 4.0. PowerBuilder can act
as an OLE 2.0 client, server or both. V6.0 supports DCOM --Distributed Component Object
Model-- also.

MAPI Support: PowerBuilder supports MS-Windows messaging standard MAPI --Messaging API.

Web Support: DataWindow can be saved as HTML table and form with only one line of code.
PowerBuilder applications can be deployed on the web in different ways:

DataWindow Plug-in: Used basically to display DataWindow reports on the web.

Window Plug-in: Used to deploy PowerBuilder applications on the web. Using 'Context'
object --gives access to the browser's exposed services-- you can make use of browser's
services -- an example would be displaying an URL from other site. Supports secure mode also.

Window ActiveX Control: Functionality similar to Window Plug-in --Plug-in is Netscape's


way of running other applications in its browser, and 'ActiveX' is Microsoft's way. Supports
secure mode also.

Web.PB Class Library: Used to generate HTML dynamically at the web server level.

Distributed Objects: From version 5.0, PowerBuilder applications can be deployed as client app
or application server or both. Client app and Server applications talk using TCP/IP and other popular
protocols. Supports 'Asynchronous' --Fire-and-Forget communication and server push also.

Unicode Support: V6.0 supports unicode. In case you do not know what unicode is, each ASCII
character takes 8 bits which limits the usage of Asian languages such as Japaneese, Hindi, etc.. in
computer applications since characters in those language can't fit in 8 bits. Using unicode in which
each character takes 16 bits, you can develop applications for non-English languages also. Unicode
is supported by MS-Windows 95/NT.

Built-in Support for Arabic, Hebrew Languages: These languages use right-to-left writing
style.

Translation Assistant: This tool helps you in deploying PowerBuilder application in multiple
languages with minimum efforts.

Support for Pen Computing: Class library for Pen Computing can be used on pen based
Windows systems, to implement pen computing interface in PowerBuilder applications.

Lotus Notes Support: Powersoft ships a class library for Lotus Notes, using which you can display
information from Lotus Notes in PowerBuilder and also update changes back into Lotus Notes.

Support for Operating Functions: You can use operating system functions, by declaring them
as external functions, with an exception of callback functions.

NetWare Support: A class library is available to call Novel NetWare functions.

Third-Party Vendor Applications: Third party controls can be used in PowerBuilder, either as
OCX controls or as external user object.

Multi Platform support: Available for MS Windows 95, NT, 3.x (deployment only from v6.0
onwards), Macintosh, Sun Solaris, IBM AIX, HP-UX.

Support for Transaction Servers: Supports Sybase Jaguar CTS and Microsoft Transaction
Server (basic support only as of this writing).

Application Profiler and Tracing: APIs are available to log all tracing information and analysis.

PowerBuilder Foundation Class Library: Available since version 5.0. (Learn about this in
detail in the PFC session).

Synchronizer: Allows you to make sure that the user always uses the latest files. Synchronization
can be done on the web also.

ORCA: Allows you to access PowerBuilder library --a file that stores PowerBuilder objects--
functions such as copy, rename, delete, move, export, import, compile, check-in/out PowerBuilder
objects, create executables, look into inheritance hierarchy and so on, from outside programs,
typically a C program.
C++ Class Builder: Allows creating C++ classes from within PowerBuilder and uses those classes
in PowerBuilder.

Version Control Interfaces: Supports popular version control products including Object Cycle --a
RDBMS based version control software from PowerSoft and Microsoft Common Source Code
Control Interface Specification.

Features of Various PowerBuilder Editions

Till PowerBuilder version 3.0, there was only one PowerBuilder edition. However, after version 4.0,
Powersoft introduced different PowerBuilder editions, targeting different segments such as students &
single-user application developers, enterprise users, etc. The following tables list various features that
are available in different editions.

Multitier deployment
Feature DesktopProfessionalEnterprise

Multithreaded Server 

Server push 

Shared objects support 

Asynchronous communication support 

Data Synchronization feature for DataWindows 

Build-in-four-user developer edition of Jaguar CTS 

Basic support for Microsoft Transaction Server 

Component assembly and transition from two-to-three-tier 


development with built-in learning edition of HOW from Riverton
Software

Wired for Web


Feature DesktopProfessionalEnterprise
Support for HTML and Java client connectivity 

Web.PB DLLs and Web.PB class library 

Window ActiveX and Window Plug-in which run both in standard   


and secure modes

PowerBuilder DataWindow Plug-in   

O'Reilly WebSite Web Server software 

PowerBuilder VM for simplified application deployment   

File synchronization tool   

Context object --gives ActiveX and Plug-in components access to   


information and services by exposing browser services

HTML enhancements including the ability to generate HTML form   


syntax

Open Technology
Feature DesktopProfessionalEnterprise

Ability to create localized runtimes 

Foreign language translation tools 

Unicode version for multinational language support 

Arabic, Hebrew and double-byte character set versions 

ODBC 3.0 support   

Native DBMS drivers for Oracle 8, Informix 7.2, Sybase Adaptive 


Server Enterprise 11.5, Sybase SQL Server 11.1 and Sybase Open
Client 11.1

Source control interface which compiles with the Microsoft  


Common Source Code Control Interface Specifications

IntelliMouse device support –enhances DataWindow scrolling and   


navigation through any windows control
Developer Productivity
Feature DesktopProfessionalEnterprise

Application profiling and tracing for advanced program execution 


analysis

Redesigned debugger   

PowerBuilder Foundation Class (PFC) Library 

InstallShield Free Edition --the de facto standard for application   


deployment

Migration Assistant --scans specified PowerBuilder libraries for  


obsolete PowerScript functions and event syntax --A good tool used
before migrating applications to the latest versions.

PFC Extender -Allows creation of new layers in PFC library  


hierarchy with the click of few buttons --saves time.

PowerBuilder Cross Reference Tool - it examines the  


relationship among objects that make a PowerBuilder application.
Using this tool, you can analyze the relationships among objects,
sorting, saving to a database, or printing, as necessary.

DataWindow Extended Attributes Synchronizer  


(DWEAS) is an interactive tool for updating many attributes of the
existing DataWindow object, with the current extended attributes
from the Powersoft repository. This tool is useful if you change any
extended attribute after creating the DataWindow.

DataWindow SQL Verifier: checks the validity of the SQL  


statements, used by the DataWindow objects in the specified
libraries. This is useful when migrating PowerBuilder applications
from one database to another.

Stored Procedure Updates for DataWindows: which  


generates PowerScript statements to override the default
DataWindow behavior and update the database through stored
procedures.
PowerBuilder extended attributes reporter (PEAR): reports  
on the extended attributes contained in the PowerBuilder
repository.

PowerBuilder object searcher: allows you to search for an  


object or text string, in the PBLs included in a single application.

Misc...
Feature DesktopProfessionalEnterprise

Check-out & Check-in support 

Stored Procedure support in DataWindows 

Version Control support 

C++ User Objects development support 

PowerBuilder Library for Lotus Notes 

PowerBuilder Family of Products

The following are some important products from Powersoft which you will be using directly or
indirectly as a PowerBuilder programmer.

InfoMaker

InfoMaker is a subset of PowerBuilder, used by end users for generating reports. You can't use this
product for development. All DataWindows generated in InfoMaker are by default read-only.

PowerDesigner

PowerDesigner a new name for 'S-Designer', a product of Red-Pepper. After merging of Red-Pepper
with Powersoft, this product became a product of Powersoft. This product supports multi-user
database designing, including logic, physical modeling and process modeling. Using the 'AppModeller'
module of this product, you can generate code for popular front-ends, such as VisualBasic,
PowerBuilder, etc.

SQL Anywhere

SQL Anywhere (also called 'Watcom SQL') was a product of 'Watcom' , which later merged with
Powersoft at the time of PowerBuilder 4.0 development. SQL Anywhere is a full-featured transaction
processing SQL database management system, which performance excellently even with its fewer
resource requirements (memory space, disk space, and CPU speed) than other database management
systems.

SQL Anywhere is a fast and efficient database for many environments, from notebook computers to
servers supporting large numbers of concurrent users. It is a flexible and scalable solution for today's
diverse needs. One great feature that you don’t find in any other database is that the database files
are compatible between versions and across all operating systems.

SQL Anywhere is available for Windows NT, Windows 95, Windows 3.x, OS/2, NetWare, Solaris, HP-
UX, AIX, DOS, and QNX operating systems. SQL Anywhere can be used as a standalone database
management system or (on non-UNIX operating systems) as a network database server, in a
client/server environment.

SQL Anywhere is an ideal database for a variety of application developers --such as C, PowerBuilder,
etc. for developing single-user and/or client/server applications for workgroups and mobile usage.
Currently SQL Anywhere supports ODBC 2.1 level II, as well as other interfaces.

From version 5.0 onwards, this database completely supports Transact SQL (Transact SQL is an
enhanced version of ANSI SQL, used in Sybase SQL Server as well as Microsoft SQL Server), and also,
SQL Anywhere supports replication in different ways, which ideally is used in mobile applications.

PowerBuilder Library for Lotus Notes

From version 4.0, Powersoft started shipping a 'PowerBuilder library for Lotus Notes', as part of the
enterprise edition. This library comes with many user objects that fall into two categories.

User objects that encapsulate Lotus Notes APIs

User objects that are meant for inheritance (you can create PowerBuilder objects by inheriting from
them and build applications quickly)

Using this library, you can build PowerBuilder applications, which act as front-end to the Lotus Notes
databases, i.e., you can create reports and also modify data in the Lotus Notes databases. We have a
separate session on this topic.

PowerBuilder Library for Pen Computing Interface

You may be aware that on a computer that has regular MS-Windows installed, you can’t use a pen
(i.e., a special pen used to write on the computer screens) to write on the screen instead of using the
keyboard and mouse. For that, you need to install MS-Windows for Pen Computing. What if you need
to build a PowerBuilder application, for that type of computers? PowerBuilder does not support pen
interface. You need to purchase a PowerBuilder library for pen computing, (This library is not part of
any PowerBuilder edition, you need to purchase it separately.) and you can use user objects and APIs
available in that library. There are few applications written using this library for doctors, sales reps,
courier deliverymen, etc.. We have a separate session on this topic.

Translation Assistant

As company grows, competition increases. For companies which span various countries need to write
the same application for multiple languages and cultures. For example, take any multinational
company that has its branches in various countries. If it has branches in USA and France, the same
application should have two interfaces one in English and one in French. Sometimes, multiple
language might exist in the same country --such as India. Using the Translation Assistant, you can
write the PowerBuilder application once in the base language and then deploy it in multiple languages.
We are covering this topic in a separate session.

Funcky Library

This library contains many functions that are not available in PowerBuilder. However, these functions
are made available in PFC as services. Funcky library is discontinued from version 6.0.

PowerBuilder Library for Netware

This PowerBuilder library is not part of any PowerBuilder edition. You need to purchase it separately.
This library comes with user objects, that encapsulate various Novell NetWare APIs and reduces the
complexity of calling them as external function. We are not covering this library.

ObjectCycle

ObjectCycle is a relation database based version control system, sold by Powersoft. This product also
supports Microsoft source control APIs and is tightly integrated with PowerBuilder. From within the
Library painter, you can directly check-out PowerBuilder objects, and the versioning is taken care by
this product automatically. ObjectCycle client comes with PowerBuilder enterprise edition, however,
you need to purchase ObjectCycle Server separately. You don't have to stick to this product for
versioning PowerBuilder objects. You can choose any third party vendor products as well --such as
PVCS, LBMS, CCC, Endevor, SourceServer, etc.. We have a separate session covering this product in
depth.

In this session you have learned about various PowerBuilder features and also got an overview of
various tools that you use in conjunction with PowerBuilder in your real world projects. In the next
session, you will learn about PowerBuilder development environment.

PowerBuilder Environment
In this session you will learn about PowerBuilder environment -- such as
toolbars, toolbar customization, opening painters, etc..

After this session you will be able to:

Create an icon for PowerBuilder under Windows NT/95.


Start and stop PowerBuilder.
Dock toolbars.
Customize toolbars.
Invoke a painter automatically when you start PowerBuilder.
Use PowerBuilder help system.

Estimated session time: 30+ minutes

Prerequisites:
You should have PowerBuilder (Desktop/ Professional/ Enterprise version)
installed on your computer.

Starting PowerBuilder
If you have PowerBuilder installed on Windows 3.x/ Window NT version prior
to 4.0, the PowerBuilder program group looks like the following picture. The
number of icons in the group may vary depending on:

the options you choose while installing PowerBuilder.


the type of PowerBuilder package you installed, i.e. PowerBuilder Desktop/
Professional/ Enterprise.

PowerBuilder Group under Windows 3.x/NT 3.51

To start PowerBuilder, you need to either double-click on the 'PowerBuilder


x.x for Intel 32' icon ( where x is the PowerBuilder version no. ) or tab onto
that icon and press Enter key when the icon is highlighted.

As you may recall, Windows 95/NT 4.0 user interface is different from
Windows 3.x/NT 3.51. If you have installed PowerBuilder on Windows
95/NT4.0, PowerBuilder icons are added to the 'Start' button menu. Here to
start PowerBuilder, you need to click on the 'Start' button ( placed on the 
windows task bar ) and select 'Programs/ PowerBuilder x.x/ PowerBuilder x.x
for Intel 32' options. After starting PowerBuilder, it looks as shown below:
PowerBuilder Startup Window

When you start PowerBuilder, it opens the last application you worked on as
the current application and displays the application name as the window
title. PowerBuilder comes with an example application named "example50".
By default PowerBuilder starts this application. You cannot work on
PowerBuilder without an application. If there are no applications installed,
PowerBuilder prompts you to select an application or create a new
application. More details on creating the application in a moment.

Creating Shortcuts
Under Windows 95/NT 4.0, the icon you create are called "Shortcut Icon". A
shortcut icon for PowerBuilder allows you to start it by double-clicking on the
icon rather than using menu options. You may want to create a shortcut icon
and start using it. Under Windows 95/NT 4.0, menu options are similar to
the picture shown below.
'Start' Menu options under Windows 95/NT4.0

To create a shortcut, invoke the operating system's popup menu by clicking


with the right mouse-button on the screen ( on an empty space, not on icons
) and select 'New/Shortcut' from the menu.
Windows 95/NT4.0 right mouse-button menu

Dialog box to Create Shortcut

A dialog box as shown above appears. The name of the PowerBuilder


executable is "pb050.exe". This file is located under "c:\xx\pb5i32\". The
directory "xx" indicates the directory you have chosen while installing
PowerBuilder. Click on 'Next' button after providing the file name and
provide the shortcut name in the next dialog box and click
on 'Finish'button. You can go ahead by double-clicking on the icon to start
PowerBuilder.
There are other ways to create a shortcut , knowing one would be good
enough. Once you start working in PowerBuilder, the operating system
becomes transparent.

PowerPanel
While developing you create/test objects using painters. Each painter has an
icon associated with it. You can see all the painter icons right below the
menu options laid horizontally. To see the descriptive text and shortcut for
each icon, display PowerPanel by selecting 'File/PowerPanel'from the menu.

PowerPanel

The dialog box shown above is called 'PowerPanel'. To invoke a painter from


the PowerPanel, you need to click the icon/text and select 'OK' button ( don't
do it now ). PowerPanel is available from initial versions of PowerBuilder. We
don't see any real need for PowerPanel in real life. Then do you wonder how
to invoke painters without the menu options and PowerPanel. If so, you will
come to know of it in the next section.

Before we go any further, lets have an overview of each painter. Close


PowerPanel by clicking on the 'Cancel' button.

Application object is the entry point to any PowerBuilder application.  For those from
'C' background it is like 'main()'. In the application object you can specify what
PowerBuilder should do when:
Application
Painter you start the application

the application is idle for a pre-determined time


an error occurs at run-time

you close the application

In any application, screen is the main interface between a user and an application. It
allows you to do data entry, see reports and so on. In PowerBuilder, screens are called
as 'Windows'. Don't confuse the term 'Windows' with Microsoft Windows operating
Window
system; it is referred to as 'MS-Windows'. A Window Painter, as the name suggests
Painter allows you to paint and save window objects. On a window you can paint various
controls such as CommandButtons, ListBoxes, etc.

A menu is a list of options or commands. An example of a menu would be your


browser's menu. In character based systems, typically one menu occupies the whole
screen. When the user selects a menu option, another screen will be displayed with a
Menu
new menu. In some systems like AS/400 or Mainframes, you can see all the available
Painter options at the bottom of the screen, it is nothing but a menu.

Under MS-Windows, menu interface is user-friendly than


character based screens. In PowerBuilder, you can create menu
objects in the menu painter and assign it to the screens
(windows) you have painted in the window painter. You can
also paint popup menus (context sensitive menus) in the menu
painter.
DataWindow object allows you to retrieve data from a database or other source, for
display. A DataWindow object definition consists of:

DataWindow data source definition (about the data to bring, i.e., database, table, column
Painter names, etc.)

presentation definition (about how you would like to display the retrieved data,
i.e., a table format, labels, graph and so on).

You can also do data entry through a DataWindow. After


painting the DataWindow object, you can't use that object
alone. You need to associate a DataWindow object with a
DataWindow control and place that DataWindow control on the
screen (window). Finally users interact with the DataWindow
object through the screen (window).
The Data Pipeline object allows you to copy tables and their data from one database
to another with few lines of code, even if the tables are located on different DBMSs.
For example, you may want to develop an application using Watcom (SQL AnyWhere)
Data Pipeline
database on your desktop, but you need some SQL Server data which resides on the
Painter network.
In the traditional way, you need to export the data from SQL
Server and fiddle with the data to make sure that the data
format is compatible for importing into Watcom database and
then import it. In this approach, if you want to refresh the
existing data, you need to write a big program.

Things are very simple if use PowerBuilder. Here you can just
paint a data pipeline object in couple of minutes and execute
the pipeline. You can then reuse the data pipeline object every
time you want to copy/refresh data from the source.
An User Object allows you to reuse the code. It is nothing but a collection of one or
more PowerBuilder/ non-PowerBuilder objects. Non-PowerBuilder objects includes
objects from VB, DLLs, OCX and so on.
User Object
Painter
A Query Painter allows you to build SQL SELECT statements which can be saved as
query objects in the PowerBuilder library. If you intend to use the same SQL
statement many times in your application as embedded SQL or as DataWindow
Query Painter
source, you need to define reusable query objects.

The function painter allows you to build function objects that define a series of
frequently executed commands. In PowerBuilder, a function is a collection
ofPowerScript commands and/or embedded/dynamic SQL statements. You can also
Function
refer to these functions in your PowerScript and DataWindow painter.
Painter
The Structure Painter allows you to create structure objects. A structure is nothing but
a set of related variables (which may have different data types) grouped under a
single name. It makes management of related variables easy. You can refer to the
Structure
structures in your PowerScript.
Painter
Objects you create in PowerBuilder painters (application, windows, menus, functions,
queries, structures, user objects and DataWindow objects) are stored in an operating
system file with ".pbl" extension (pronounced as pible); In PowerBuilder terminology,
Library
this file is called a "Library". A Library Painter allows you to create and maintain
Painter PowerBuilder libraries and objects in those libraries.

Database Painter allows you to create database objects--such as table, view, index,
stored procedure, trigger, etc. without knowing the actual DDL syntax. All the
database objects that you create in this painter are stored in the connected database
Database and not in the PowerBuilder library. Objects that you create in other painters--such as
Painter window, menu are stored in PowerBuilder library. You can also do database
administration from this painter.

Project Painter allows you to create PowerBuilder Dynamic Linked Libraries (PBDs),
executables. You need to define what libraries need to be included in the project for
Project the first time. Once you define this, you can create executable files with few clicks. It
Painter also allows you to do incremental rebuild if you are using a version control system.

You guessed it right. A Run icon allows you to execute the application you are
 Run currently working on.

A Debug painter allows you to view the execution of the current application step-by-
step and simplifies the discovery of bugs. It is very powerful and comes with all the
Debug debugging facilities you will ever need.

Toolbars
What is a toolbar? A toolbar is nothing but a collection of icons associated
with actions. Clicking on a toolbar icon triggers some action. All the icons
that you see across the PowerBuilder window, i.e., below the menu (as
shown in the picture), are part of the toolbar called  Powerbar.

Typically, each toolbar icon represents one of the menu options, except
in Powerbar (the one you see on the screen) and Stylebar. Say you want to
represent File/Open with one icon, File/Save with one icon and so on. Toolbar
allows you to be more productive, since you will be directly clicking on the
toolbar icon, instead of selecting nested menu options. For example, to
select File/Open, first you need to select File option and thenOpen option.
If File/Open has a toolbar icon, you can simply click on the icon. You can also
create toolbars as part of your PowerBuilder application and make the
application more user friendly.

PowerBuilder comes with three toolbars:

Powerbar

Painterbar

Stylebar

The one you see on the screen is called Powerbar. Typically, a toolbar is


associated with a menu and options in the menu. That means, for each
menu option toolbar contains one icon. It is not necessary to have a toolbar
icon for each menu option. For example, some times you come across some
menu options which are difficult to be expressed in terms of picture, So, you
can't provide a picture for them. Similarly, in PowerBuilder, there are few
icons which don't have corresponding menu options. For example, icons in
the Stylebar has no associated menu options.

Unless you hide Powerbar, it is visible through out the PowerBuilder session.
Painterbar and Stylebar are available only when at least one painter is open.
In some painters like Project painter, database painter, Library painter,
Stylebar is not available. In some painters like Structure painter neither the
Painterbar nor the Stylebar are available. The options in the Powerbar and
Stylebar are static, i.e., you see the same icons irrespective of the painter in
use. Painterbar is dynamic in nature and the icons change depending on the
painter in use. Now let us examine what you can do with each of those
toolbars.

Powerbar

Powerbar is similar to PowerPanel in terms of functionality and contains all


options available in PowerPanel.

Powerbar
When you move the mouse pointer over toolbar icons, description for the
specific toolbar icon is shown at the bottom of the PowerBuilder window.
That area is called Statusbar.

When the Show PowerTips option (explained in a moment) is turned on, you


will also see the name of the icon just below the mouse pointer in a yellow
colored rectangle. This short description which moves along with the mouse
pointer is called PowerTip.

To see how PowerTip works, switch to PowerBuilder from this web page


and keep moving the mouse pointer over the toolbar icons slowly. If you
don't see PowerTips, don't worry. We will give the solution in a moment.

The basic purpose of Powerbar is to allow you to invoke any painter. To


invoke a painter, you need to single click on the appropriate icon.
Advantage of Powerbar over PowerPanel is that you can place Powerbar
anywhere you like within PowerBuilder window. To move Powerbar, click
anywhere in-between toolbar icons and drag it to the place intended.

Video demonstration of 'Moving the toolbar' (moving-toolbar.zip, 2313


K).

DropDown Toolbar

Toolbar icons that contain down-side arrow on right-side are drop-down


toolbar. For example, the first icon from the left hand side (application icon)
is a drop-down toolbar.The purpose is to reduce the space needed for a
toolbar. The placement of the toolbar can be selected from the popup menu
by clicking the right mouse button on the Powerbar.

Popup/Right Mouse-Click Menu for the Toolbar

Another advantage of Powerbar over PowerPanel is that, unlike PowerPanel


Powerbar can be customized . Simple customization includes:

showing/hiding the text below the toolbar icons

the text font & size, showing/hiding PowerTips

placement of the Powerbar

Toolbar Style Customization Dialog box.

All of the above mentioned can be done by selecting proper options in the
popup menu. Un-checking the Powerbar option hides it. Once you hide all
toolbars, you cannot show toolbars by selecting from the popup menu; the
reason being that you invoke the toolbar popup menu by right clicking on
the toolbar itself. Since the toolbar itself is not visible, you cannot invoke the
popup menu. Well, we have gotten ourselves into trouble here. There should
be some way of making the toolbar visible.  We could try selecting
File/Toolbars from the menu.

In the dialog box shown above, along with the regular options, font related
options are also available.

To invoke a toolbar when one of the toolbars is visible, double-click in the space between icons
on the toolbar.

Painterbar
As explained in the previous sections, painters --such as Window painter,
Menu painter, DataWindow painter can be invoked from the Powerbar. Once
you invoke a painter, you will see another toolbar called "Painterbar" along
with the "Powerbar". Unlike Powerbar where the toolbar icons are static,
Painterbar toolbar icons are dynamic.For each painter you invoke different
toolbar icons are available .

Painterbar for Window Painter

If you invoke window painter, you will see icons required to paint a window -
such as an icon to paint a line, rectangle, CommandButton, etc.

Painterbar for Script Painter

If you invoke "script editor" from the window painter, Painterbar displays
icons required to write script - such as script comment icon, script
uncomment icon, etc.

Invoke window painter by clicking on the window icon


(the one in Blue color) from the Powerbar. Have a look at
the toolbar icons displayed in the Painterbar (don't worry,
you may not know what each icon stands for; you will be learning them in
the window painter).

Now, invoke the script editor by clicking on the script icon. You will notice
that PainterBar has different icons compared to the window painter toolbar
icons.

Close the script painter by clicking on   icon. Now, you are back in the
window painter.

Stylebar
Stylebar allows you to change the text style - such as text's font, font size,
justification, etc.

Stylebar is present only in some painters like "Window" and "User Object".
You can see the Stylebar now since you are in the window painter.

The left most value is the selected control's  text property value (you will be
using this in the window painter session). By default the value is "none" and
you have to change it to the value you want.

The next value 'System' is the font type. You can select the font by clicking
on the down arrow. The fonts available in this DropDownListBox depend on
the fonts installed on your system. The last three right icons represent
justification of the text. They are "right", "Center", "Left" from right side. In
versions prior to 5.0, a toolbar named "Colorbar" was prevalent. It allowed
you to change the background & foreground colors for a selected control.
With version 5.0, it was merged with the Painterbar.

Select Controls/StaticText from the menu.Click on the location you


want to place that control. You will see some colored area labeled as
none. On the Stylebar (see the above picture) click on 'none' and
type What is your name?. You will see the changed text value being applied on the selected
control in the window. Now click on the font DropDownListBox arrow and select a font. Change
the font size by clicking on the number next to the font. Click on justification buttons one at a
time and see how PowerBuilder justifies the text. Close the window by
selecting File/Close from the menu. Choose No for the prompt.

If you have any problem in doing the above, click on the projector icon
and download the zipped Lotus ScreenCam file (stylebar-demo.zip) and
watch it.

Customizing Toolbar
The power of a PowerBuilder toolbar is in its flexibility. If you want to get rid
of some of the icons in the toolbar, you can do so. If you want to add some
more icons to the toolbar, you can also do it. Let us see how to customize
toolbars.

Adding an icon to the Toolbar

Toolbar Customize Dialogbox


Invoke the popup menu on the Powerbar and select "Customize" option. The
buttons under the "Current toolbar" are the presently available icons in the
current toolbar. To add an icon to the current toolbar, click on an icon from
the "Selected Palette" and drag and drop onto the "Current toolbar" area.
That's it, you are all set. In this case, the button you added has the standard
functionality defined by PowerBuilder.

Sometimes you may want to do add custom functionality to the toolbar icon.
In that case, you need to select "Custom" Radiobutton from the "Select
Palette"; you will be presented a collection of new icons. Add one of them to
the current toolbar in the same way you added previously.

Dialogbox to specify Toolbar Icon Properties

PowerBuilder prompts you for the command definition of the toolbar icon.
You need to provide the command for the Command line prompt. For
example, providing "c:\Program Files\Accessories\wordpad.exe" allows you to
invoke Wordpad by clicking on the newly added toolbar icon. The value you
provide for "Item Text" option will be displayed as PowerTip. Value of "Item
MircroHelp" will be displayed as MircroHelp on the Statusbar. Click on "OK"
CommandButton and test how the new toolbar icon works. Similarly you can
also assign a pre-defined query or a report to the toolbar button.

If you can add a button to the Painterbar when the DataWindow painter is
invoked, you can also assign a function or format to the toolbar button.
Painterbar has one exception in this matter. Once you add a toolbar icon to
Powerbar, the added toolbar icon is available whenever Powerbar is
displayed. As you know, Painterbar is displayed only when a painter is open.
The toolbar icon you add to the Painterbar would be displayed only when
that painter is open. For example, if you have added an icon to the
Painterbar when Window painter is open, it would be displayed only when
the Window painter is open. If you open say, Menu painter, you cannot see
the icon.

If you have any problem doing the above, click on the projector icon
and download the zipped Lotus Screencam file (add-toolbar-icon.zip)
and watch it.

Deleting a Toolbar icon

To delete a toolbar icon, you need to invoke " Customize" dialog box by
selecting "Customize" from the popup menu and drag the icon you want to
delete from the "Current Toolbar" and drop on the "Selected Pallete" area.

If you have any problem doing the above, click on the projector icon
and download the zipped Lotus Screencam file (delete-toolbar-
icon.zip) and watch it.

Custom Toolbars
With version 5.0, PowerBuilder allows you to create your own toolbar. You
can create three more Powerbars. Similarly, you can have seven custom
toolbars for each painter. That means, you can add seven Painterbars when
the window painter is open. As soon as you close the window painter, all
Painterbars are closed. If you invoke say, User Object painter, you see only
one Painterbar which is the standard Painterbar. Here again seven more
Painterbars can be added.

Creating New Custom Toolbar

To create a new Powerbar, invoke popup menu by clicking with the right
mouse-button on the toolbar and select New. Add icons as explained
inAdding a Toolbar Icon and select OK button. The new toolbar is placed
just below the "Powerbar". Similarly a new Painterbar can be created by
invoking popup menu on the Painterbar and selecting the New option.

If you have any problem doing the above, click on the projector icon
and download the zipped Lotus Screencam file (adding-custom-
toolbar.zip) and watch it .

Deleting a Custom Toolbar

To delete a custom toolbar, invoke the popup menu and select " Customize"
option. Select "Reset" button from the dialog box.
Till now you have learned about toolbars. There is one more area which you
need to be familiar with before programming. That is the 'Script editor'.

Customizable Web links on PowerBuilder Menu


In version 6.0, you can display up to four web links on the PowerBuilder menu under the 'Help' menu
bar item. When you install PowerBuilder, you see the following links.

To customize these links, you need to edit pb.ini file that is located in the PowerBuilder installation
directory. The .INI file is a file that stores initialization values of an application such as defaults, last
used values and preferences. A .INI file is divided into sections and each section name is surrounded
by square brackets. A partial listing of section 'PB' looks like:

[PB]
CompilerWarnings=1
DashesInIdentifiers=1
DatabaseWarnings=1
Maximized=1

Each variable in the section is placed on the left and the value on the right seperated by an equal sign.
Take the example of 'CompilerWarnings'. It is placed on the left and its value 1 on the right of the '='
sign. The keywords of web links are WebLink1, WebLink2, WebLink3, WebLink4 which can be found
under 'PB' section.

To edit these web links, you need to supply the name you want to see on the menu and the actual
web site address separated by a comma. For example, open pb.ini file and replace the code for those
four variables with the code shown below and save the file.

WebLink1=&PowerSoft,http://www.powersoft.com
WebLink2=&Sybase,http://www.sybase.com
WebLink3=PowerBuilder &Online Courses,http://www.applied-software.com
WebLink4=&Yahoo,http://www.yahoo.com

In the above code, you find '&' (ampersand) characters. An ampersand creates an accelerator key for
the menu item. An accelerator key is a letter that you press in   combination with an 'Alt' key to
access the menu item quickly without using a mouse. For example, you can press 'Alt + F' and 'O'
keys to access 'File/Open' from the menu.
If you restart PowerBuilder, the changed options under the 'Help' menu bar item will be as shown in
the picture.

Script Editor
Script editor allows you to write scripts for object events, functions and so
on. To start  script editor for an object, invoke the right mouse popup menu
by clicking the right mouse button on an object and select Script . You can
also invoke script editor by clicking on the Script   icon. For demonstration
purpose, invoke application painter by clicking on the application icon from
the Powerbar. Click on one of the Script icon   or  . Clicking on either of
them invokes the script editor. You can see only one at any time. The first
icon (left) means that there is no script for any event for the selected object.
The second icon (right) means that at least one event for the selected object
has the script.
Script Editor - Script Editor Popup Menu

Script editor has five DropDownListboxes by default, and you can customize


them. Note that script editor also supports right mouse button's popup
menu. So for things like cut & paste, you can simply use the popup menu.

The first DropDownListBox from the left is called an Events DDLB. This DDLB


lists all the events available for the selected object level. The name of the
event for which you are currently writing the script is shown as the heading
of the script editor window. To write script for an another event, all you need
to do is select the event from the Events DDLB. Selecting an option from any
DDLB other than Events DDLB, would paste the selected option at the current
mouse pointer position in the script editor.

The second DropDownListBox (DDLB) Paste Arguments lists all the arguments


for the selected event. The third DDLB Paste Object lists all the controls and
variables at that level. The Paste Global DDLB lists all the global variables
and the right most DDLB Paste Instance lists all the instant variables.

 icon Comments all the selected text with // comment format.   icon


Uncomments all the selected text with // comment format. If there are any
with /*...*/ format, they will not be uncommented.

The last icon on the Painterbar represents the object for which you are
writing the script. That is, if the script is for a window or a control in the
window, it would be a  Window and if it is for a menu object, it would be a
menu object. To close the script editor, select File/Return or click the last
icon on the Painterbar; this action compiles the script and exits to the
current object. You can also close the script editor  from the script editor
window control box. Closing the script editor from the control panel or
clicking on window close button (icon next to the window maximize icon) will
prompt you for the confirmation to close the script editor. All these options
do the same thing, except for the later option where you have to answer the
prompt.

PowerBuilder automatically compiles the code that was open in the script
editor when you close it. However, the script can be manually compiled by
selecting Design/Compile Script from the menu or by clicking on the Compile
 toolbar button.

You can customize the script editor to suit to your tastes & needs. To
customize, when in script painter select Design/Options from the menu .

Script Editor Customization Dialog box

You can choose the font for the script display in script editor from
the Fonttab. Script editor has the ability to maintain color codes i.e.,
comments in one, reserved words in another and so on. You can choose the
colors from the Coloring tab. You can also specify if PowerBuilder should
automatically indent the codes like If, For, While, 'Do While' and so on as you
type in. This is available in the General tab.

You have learned how to start and stop PowerBuilder and customize
PowerBuilder environment. In the next session, let us develop a simple
application in PowerBuilder

PowerBuilder Environment - Summary


In this session, you have learned about PowerPanel and toolbars --such as Powerbar, Painterbar and
Stylebar. You have also learned about customizing toolbars and PowerBuilder menu customization for
web site links. To read a full summary of the session, click on pb-env.ppt which is a PowerPoint
presentation. You may not have PowerPoint viewer installed on your machine if it doesn't
automatically start from your browser, when the presentation is clicked. Please visit 'Software Setup'
page at the beginning of the course and download PowerPoint viewer free-of-cost.

What's a PowerTip?

PowerTip is a short description of the toolbar icon that is displayed just below the mouse
pointer when the mouse is moved over it, in a  rectangle area with yellow background.
List the toolbars available in PowerBuilder.

 Powerbar
 Painterbar
 Stylebar

What is the difference between PowerPanel and Powerbar?

 PowerPanel is not configurable, where as a Powerbar is fully configurable.


 PowerPanel is always invisible unless you select File/PowerPanel from the menu to
make it visible. On the other hand, Powerbar is always visible, unless you choose to
hide it.
 PowerPanel works like a model window, Powerbar doesn't

List two differences between Powerbar and Painterbar.

 Toolbar icons in Powerbar do not have associated menu items.


 Toolbar icons in Powerbar are constant throughout the PowerBuilder session, where
as Painterbar icons are dynamic, i.e., they differ from painter to painter.

What is the difference between PowerTip and MicroHelp?

 PowerTip is a short description for the toolbar icon and is displayed right below the
toolbar icon.
 MicroHelp is a detailed description for the toolbar icon and is displayed on the
Statusbar at the bottom of the PowerBuilder window.

When you close Script Painter, PowerBuilder compiles the code and converts it into
machine code. True/False.
False. PowerBuilder compiles the code when changes are made to the script and the script
painter is closed. However, at this point of time, it doesn't create machine code for the
compiled script.
What icons can be added to the PowerPanel?

You can't add toolbar icons to the PowerPanel. It can be done only to Powerbar or
Painterbar.
How many additional toolbars can be added to your PowerBuilder development
environment?
You can add:

 three additional Powerbars.


 seven Painterbars for each painter.

PowerBuilder Environment - Exercises


Make Powerbar to float.
Display the toolbar text.
Hide the Powerbar and then show it.
Add a button to the Powerbar to invoke Paintbrush program.
Create a new Powerbar with one button and then delete the created Powerbar

Your First PowerBuilder Application


Previous session familiarized you with the PowerBuilder environment. This
session onwards, you will be learning about various painters ( to create
objects ), PowerScript ( to manipulate them ) and finally build a complete
project. What we do here is, define a project and then start learning. Here
while learning each painter, you create few objects which would be needed
for the defined project. This way, you will complete the project while you
learn? Isn't that exiting?

After this session you will be able to:

Create a PowerBuilder Library.


Create a PowerBuilder Application Object.
Defining the specifications of 'Product Management System', which you would be
developing in the 'PowerBuilder Online Courses'.

Estimated session time: 20+ minutes

Prerequisites:

You should have PowerBuilder (Desktop/ Professional/ Enterprise version)


installed on your computer.

Introduction
You might know that when you write a program, you need to store it in a
file. For example, a 'C' program, would be stored in a file with '.c' extension.
Similarly, a COBOL file with '.cbl' extension and a FoxPro program with '.prg'
extension. All PowerBuilder objects and scripts are to be stored in a file with
'.pbl' extension. 'pbl' stands for PowerBuilder Library. Unlike 'C', 'FoxPro' or
'COBOL, you need to create PowerBuilder library before you start creating
any PowerBuilder objects and scripts.

As part of PowerBuilder online courses, you will be developing "Product


Management System" application . For this application we need a
PowerBuilder library called "product.pbl" ( actually, you can name it
anything, however, we recommend you to use 'product.pbl' since we used it
in all the examples ).

There is one more distinction between other languages like 'C', 'FoxPro',
'COBOL' and PowerBuilder. In them you need to create a separate file for
each program you write. Where as in PowerBuilder, you create one library
and all objects & scripts you create will be stored in that library. You seethe
difference when you search for it from the operating system (through 'dir'
command, File Manager or MS-Windows Explorer). Here you will find only
one file, i.e., 'product.pbl'; but when you open the same file in PowerBuilder,
you will find all the objects you stored in the 'product.pbl' library.

In this session, we don't go into details about Library painter and Application
painter. We will revisit them as and when required in the coming sessions .

Introduction to 'Product Management System'


Wouldn't it
be nice to know what project you will be doing as part of the
course? The  outlines of the project are as follows .
Till 'PowerScript Basics' session, you will be painting various objects that are
necessary for this project. Once familiar with PowerScript, you write scripts
to allow the user to login to SQL Anywhere database 'product.db' from your
application. Later on you allow the user to
retrieve/change/add/delete/print/print preview/sort/filter various products
from the database. Then you will be introduced to DataWindow internals.

By this time you will be comfortable with PowerScript, event driven


programming and DataWindow programming. At this point introduction to
MDI (Multiple Document Interface) will be made and you will be converting
the previous code to MDI programming model. We know that you will be
redoing few things, still we would prefer to do it this way. That is because,
we want to introduce this new technology slowly and since there are so
many things to learn in PowerBuilder.

After this, you will be introduced to object-oriented programming, handing


multiple-table updates in DataWindow and handing multiple DataWindows
especially those that have parent-child relationship. Then you will be
introduced to MS-Windows SDK, where you will be reading information from
the operating system and displaying it to the user. In later sessions, you will
be implementing dynamic query manager using embedded/dynamic SQL.

After that, you will be implementing DDE for sending e-mails to different
users and reading e-mails from them based on certain events. Then, you will
make use of OLE to give OLE interface and to make it interact with other
applications. Later, you will convert this application to use PFC and then
convert to allow the user to use pen computing (using pen computing
interface) for your application. After that you will change the application for
international multiple language deployment.

At this advanced stage, you will be introduced to state-of-the-art technologies --such as 'Distributed
Objects', web deployment, etc. and you will be converting your application to use 'Distributed
PowerBuilder Objects' and then for web deployment.

This would be a great time for you to start real world projects and jump into preparing for technical
interviews and finally for the CPD exam.

Creating a Library
To create a library or to manage objects within the library, you need to
invoke the library painter by clicking on   icon. By default, the library
whichever has the Application object is displayed in the expanded mode, i.e.,
all the objects within the library are listed. It is similar to the 'File Manager' ,
where to start with you see directories. Once you double click on the
directory, it would expand and display all the files within the directory. All
other directories are listed, but not expanded. Same is the case with
PowerBuilder. Library in which the application object resides is expanded and
other PowerBuilder libraries are just displayed.

Libraries that are not being displayed in the expanded mode have  library
icon. Libraries in the expanded mode have   library icon ( It is like a open
library door ).

To create a library, select Library/Create from the menu or click on   icon.

In Create Library dialogbox, select the appropriate directory (we advise you to


have a directory named "workdir" and use that directory throughout the
course) and provide product ( PowerBuilder automatically adds '.pbl'
extension if you don't provide any ) for the File name prompt and click on
the Save button. PowerBuilder prompts you for the comments. ProvideLibrary
for 'Product Management System' application and click on OKbutton. Now
you can see the new library in the library painter. Close the Library Painter.

Creating an Application Object


Application object is the entry point of an application. For each application
you create, you have to have an application object. Similarly for "Product
Management System" we need to have an application object. Let us create
it with the same name.
You need to invoke an application object painter by clicking on the   icon.
At this time, the application that is opened is "example 5.0"/"example 6.0",
that comes with PowerBuilder software, depending on the version, .

To create a new application object you need to click on   icon (Please note
that, at anytime you see a star on an icon, it means that clicking on that
icon allows you to create a new object ) or select File/New from the menu. As
explained in the previous page, for every object you create in PowerBuilder,
you need to store it in a PowerBuilder library. Same is the case with an
Application object. You need to select a library name in which you want to
store the new application object. Select product.pbl which you created
previously. Now, PowerBuilder prompts you for an application object's name.
Provide product_management_system and click OK or Savebutton depending
on the operating system you are using.

PowerBuilder makes the application development faster, by creating the


skeleton application, if you choose so. Do NOT select "Yes" for the prompt,
instead select No. You might ask, what happens if I select "Yes". Good
question. As explained earlier, it creates the minimum required components
for an application. Actually, it creates an application that uses MDI (Multiple
Document Interface) style, which is too advanced for you at this stage.
Before you develop a MDI application, you should know a lot of other basics.

Now you see the new application named product_management_system on


the window titlebar, indicating it as the active application.

Writing "Hello, World!" Application


Select Entry/Script from the menu. You can now see the script editor for the
application object. Type the following code:

MessageBox( "My First Application", "Hello, World!" )

Come out of the script painter by selecting File/Return from the menu. To run


the application, click on the Run   icon from the Powerbar. Say Yes for the
prompt asking you whether to save the changes or not.

That's all. Isn't it simple to write an application; even though this might not
be a great one. Do you know what you did? You wrote the above script in
the application's Open event. When you run the application, application
object's Open event is the first one to be fired. So it executed 'MessageBox()'
function you wrote over there.

Summary
You have learned how to create a library and an application object. You also
wrote a single line of PowerScript code and executed the application. To read
the full summary of the session, click on first-app.ppt which is a PowerPoint presentation. If your
browser didn't open PowerPoint viewer automatically upon clicking on the presentation, then you may
not have it installed on your machine. Please visit 'Software Setup' page which is at the beginning of
the course and download the PowerPoint viewer free-of-cost.

Window Painter
After this session you will be able to:

Understand what a window is.


Understand about Window Controls and how they work together.
Paint windows.
Preview/Run/Print the window.
Understand different types of windows.

What we won't teach you in this session:

Events
Scripting

At the end of each topic, you are needed to complete exercises in which you
paint few windows. As you proceed to other topics, you will be using these
windows, So, please don't skip exercises. Upon completion, you can
download windows that we painted for you and compare them with yours.
This can rectify any mistakes that you might have committed. If you still
have any questions, you can always send an e-mail to prasad@applied-
software.com.

Estimated lesson time: 300+ minutes

Prerequisites:

You should have PowerBuilder (Desktop/ Professional/ Enterprise version)


installed on your computer.

Introduction to Window Painter


No matter what kind of application you have used, it is the user interface
that has been your best friend. Without that you would have been powerless
to interact with the software, whether it be to format a document, calculate
your tax return or interrogate the information in your local database.

To address to these basic requirements, PowerBuilder provides you with an


object that operates in the same customary manner to display information or
accept it from the user and in combination with others of its own type, to be
used as a guide for the user through the task that the user wishes to
complete.
The object that PowerBuilder provides is called a "Window Object". The basic
building blocks of the user interface are designed, maintained and
customized using the Window Painter.

What is a Window? Is it Microsoft Windows Operating System? The answer is


No. A Window in PowerBuilder world is a screen. It is the main interface
between the user and the application you develop. Do not confuse it with
MS-Windows. Whenever we refer to Microsoft Windows, we always refer as
"MS-Windows".

Window is the place where the end-user does the query and sees the report,
does the data entry and so on. A window itself doesn't do all these things,
instead a Window acts as a placeholder for some controls. There are few
controls that the window allows you to place on it. For example, a control to
allow you to enter your name, a control that allows you to close the window
and so on.

Creating a Window
Invoke the Window painter by clicking on the Window icon   (the one that
is filled with blue color) from the Powerbar and select the New button in the
'Select Window' dialog box. ( You will see another Window icon also which is
filled with gray color;don't click on that, you will be learning about that later
in this session ).
Image of Select Window dialog box

Once the Window painter is open, it will look like:

Image of Window Painter Working Environment

The rectangular area that you see in the "Window - (Untitled)" window is the
window work area. The work area is the area where you can paint the
window. If you want to have a large work area, you can do so; Move the
mouse over the border of the work area (you know the window border when
the mouse pointer changes to   or   or  ), click on the border, drag till you
get the area you need.

In the previous section, we described in simple terms that  a window is like a


screen. Now, if you were from xBase background, what you would do to
display "Enter your name:" on the screen. You probably would have
coded @05,01 SAY "Enter your name:".

Later when the user wants it at a different position, you would have opened
your program and changed the x and y co-ordinates. In PowerBuilder, you
don't have to code the x, y co-ordinates; instead you place a control that is
capable of displaying the given text and use the mouse to drag it to the
correct position. The control that is used to display the text in PowerBuilder
is called "StaticText" control. To place a 'StaticText' control in the Window
workspace, you can follow either of the following procedures:

Select Controls/StaticText from the menu and click in the


workspace wherever you want to place the StaticText control. (OR)
From the Painterbar, Click on the arrow that has OK and click on the
StaticText control (Whichever displays "A") and click in the window
workplace wherever you want to place it.

As the name suggests, the purpose of the "StaticText" control is to display


text that won't be changed by the user. Of course, you can change the text
programmatically at run-time using PowerScript.

Window Controls
In addition to the StaticText control, the following controls are also
available:

SingleLineEdit PictureListBox RichTextEdit


MultiLineEdit DropDownPictureListBox Picture
DataWindow
EditMask ListView
Control
CommandButton TreeView UserObject
PictureButton CheckBox OLE Control
Vertical
ListBox RadioButton
Scrollbar
Horizontal
DropDownListBox GroupBox
Scrollbar
Tab Control Line Rectangle
RoundRectangle Oval Graph

Each control has certain properties, such as border, foreground color, name,
etc. Once you place a control in the Window Workspace, you can change the
control properties either:

By clicking with the right mouse-button on the control and selecting


"Properties" option from the popup menu. (OR)
By selecting the control (To select the control, click on the control), then,
select "Edit/Properties" from the menu.
By double-clicking on the control.

The following picture is the "Properties tab object" for the StaticText control.

StaticText Control Properties Dialog Box.

The value you specify for "Text" attribute is the text that it displays on the
"StaticText" control; that is what the user sees. The default value for this is
"none'. For this example, change this to: "Enter Name:", without quotes.
Each control has a name. The 'Name' property allows you to refer to that
control in the script. (We will explain naming conventions in a moment).
Change the name to "st_name", without quotes. Users don't see the name,
it is meant for the programmer to refer in the script.

Visible: By default this property is checked-off, Otherwise, users can't see


this control even though it is on the window.

Enabled: This property is not checked by default. If this property is not set,


nothing will happen when the user clicks on this control. Users can't tab onto
this control when this property is not checked.

Focus Rectangle: Bydefault this option is not checked-off. If you do so,


PowerBuilder displays a rectangle around the control. The control gets focus
when the user either tabs onto the control or clicks on it with the mouse
button.

You can choose from four borders, 3D raised, 3D lowered, Box and Shadow
box. The Align option aligns the text you provided for the Text property.

You can select the text font properties by clicking Font tab and choosing the
appropriate option. You can choose where you want to display the control,
but we won't recommend choosing the x, y co-ordinates from this dialog
box; instead click on the control and drag it to the correct position and resize
it.

Pointer: By default, when you move the mouse pointer over the StaticText
control, you will see the standard icon. The standard mouse pointer might be
different on your computer; it depends on the pointer you select in the
Windows setup. Typically, the pointer is an arrow. If you would like to
display a different mouse pointer whenever user moves the mouse pointer
over the control you just painted, you can do so by clicking on
the Pointertab. We will explain how to preview the window you are painting
in a moment; you can test this property at that time.

We will explain about drag-and-drop in the coming sessions.

Accelerator Keys: When there are lot of controls in the window and when the
user wants to jump from one control to another, he can either keep pressing
tab till he reaches the control he wants to reach OR he can click with the
mouse-button directly on the control. Remember, there is a large community
out there who are from DOS world and still use keyboard most of the time.
If they want to reach the last control in the window while the focus is at the
top, pressing tab keys would be pretty tiresome.
We can provide hot keys, by which they can jump to the controls directly by
pressing them, no matter where the cursor is. In PowerBuilder, these hot
keys are called as Accelerator Keys. User presses them in combination with
the "Alt" key. To specify an accelerator key, you need to prefix the key with
an ampersand (&). If you want "n" as an accelerator key for "Enter your
name:", you need to type "Enter your &name:". The case of the accelerator key
doesn't matter.

Please note that StaticTexts have no accelerator keys since we won't expect
the user to do anything on the StaticText control itself. Other controls have
accelerator keys but, there is a problem of displaying the accelerator keys to
the user. You will learn more about them in the "SingleLineEdit" control.

SingleLineEdit Control
With the use of a "StaticText" control, you have asked the user to enter his
name. But, there is no provision to input the data. For that you can make
use of SingleLineEdit control. This control allows the user to input data.

Hide Selection: By default, "Hide Selection" property is selected. When you


highlight some text in the control and then move the focus to a different part
of the window, the highlighted text will remain highlighted if you deselect
this option. This allows you to begin editing the text, move elsewhere to
check on something, return and still be able to continue where you left off,
without re-selecting the text.
Case:The Case property allows you to control the case of the text the user
can enter. The user can enter text in either case, but if you specify upper or
lower, the text would be converted automatically to the relevant case. For
example, if you set Case property to "upper", even if the user is typing in the
lower case, it will automatically convert into upper case.

Auto HScroll: The "Auto HScroll" property should be checked if there is lot of
text to be entered. With this option selected, the text will automatically scroll
as the user types the text. You don't have to use up lot of screen space with
large SingleLineEdit boxes when you want the user to enter a large text.
When designing windows and sizing controls, you should also keep in mind
the various sizes and fonts that may be used.

Limit:If you don't provide any value for this property, user can type 32,787
characters. If you would like to restrict him as to how many characters he
can type, you can do so by filling up the Limit property.
If you turn-on "Display Only" property, then the SingleLineEdit control will be
used to display data only; it will not accept input from the user.

The Accelerator property as described in the "StaticText" control, allows you


to associate a hot-key with the SingleLineEdit control, which causes the
focus to jump to it when the accelerator is pressed at any time, except while
entering text into another control. For this control, user won't be able to see
the accelerator key. However, you can display the accelerator key on the
StaticText control and assign the actual accelerator key to the SingleLineEdit
control. To display the accelerator key, prefix the character with an
ampersand "&". To display "n" as the accelerator key on the StaticText
control, change the 'Name' as "Enter &Name:".

Any text that you type into this field will appear, by default, in the
SingleLineEdit control, when the window is first opened.

Typical uses of "SingleLineEdit" control are: to accept limited data (either


string or number) from the user in a single line, accepting passwords, etc.
To accept dates and times, you can use "EditMask" control.

Password: Sometimes, you might want to accept a  password from the user.
If you use SingleLineEdit control to accept a password, it will be displayed as
the user types. In this situation, you need to turn on Password property.
Turning on this property will display stars as the user types the password.

Previewing the Window


You may want to see how the window looks like at run-time. You can do so
by selecting "Design/Preview" option from the menu. In the preview mode,
scripts do not execute. If you want to run the scripts, you need to run the
window; this is explained in a moment. To come back to design mode, you
need to select "Design/Preview" again.

Window in the Preview Mode

Naming Controls
When you place controls on a window, PowerBuilder automatically names
them using standard prefixes and a number to uniquely identify them. The
full list of controls and naming prefixes are as follows:

Control Type Prefix


CommandButton cb_
PictureButton pb_
StaticText st_
SingleLineEdit sle_
EditMask em_
MultiLineEdit mle_
ListBox lb_
TreeView tv_
CheckBox cbx_
RadioButton rb_
DataWindow dw_
DropDownListBox ddlb_
DropDownPictureListBo ddplb
x _
Picture p_
Groupbox gb_
Graph gr_
OLE 2.0 ole_
Vertical scrollbar vsb_
Horizontal scrollbar hsb_
RoundRectangle rr_
Rectangle r_
Oval oval_
Line ln_
ListView lv_

The above list has the default prefixes. If you want to have different
prefixes, you can change the defaults by selecting "Design/Options" and
changing values in "Prefixes 1" and in "Prefixes 2". You can rename any of
the controls, but it's a good idea to keep the standard prefixes so that it is
easy to identify the type of object by looking at the control name in the
script. Remember the control names within a window should be unique. That
means, you can't have more than one control with the same name in a
window. You can have a control with the same name in different windows.
The names are case insensitive. While naming, you should follow
PowerBuilder naming rules:

Must start with a letter


Can have up to 40 characters, but no spaces
Are case insensitive (PART, Part, and part are identical)
Can include any combination of letters, numbers, and  all these special
characters:
Dash
Underscore
$ Dollar sign
# Number sign
% Percent sign

CommandButton
A CommandButton is used to allow the user to trigger an action. You'll
probably be familiar with the OK and Cancel buttons used in standard
Windows dialog boxes, allowing the user to take control of whether or not a
task is to be completed.

A Window with a CommandButton

PowerBuilder allows you to pass on this functionality to your users by


providing CommandButtons that can be customized, while allowing you to
modify the code behind each button to perform the options that you have to
offer.
CommandButton Properties Dialog Box

Typically, we write code for the clicked event ( We will explain about events
after couple of sessions ) of CommandButton, i.e., we specify the action to
be taken whenever the user clicks on this CommandButton. Some users are
from the DOS background, they have the habit of using keyboard than the
mouse, might even press Enter key. Whenever user hits the Enterkey, the
Clicked event script should be executed. To achieve this functionality, you
need to turn on the Default property. Border of a CommandButton which
has Default property turned on, would appear black and thicker.

Similarly there is one more property, Cancel. Selecting this property will


execute the CommandButton's Clicked event, whenever user
press Escbutton. Default and Cancel properties are not exclusive. If you need
to run the same code for Enter as well as Esc keys, you can turn on these
properties.
One limitation of the CommandButton is that, you can't change the
background color and the border.

PictureButton

A PictureButton works exactly like a CommandButton and in addition to


displaying text on the face of the button, it allows you to display a bitmap, a
Run Length Encoded file or Windows metafile picture on the button.
PowerBuilder allows you to display different pictures when the PictureButton
is enabled and disabled. When you disable the PictureButton with some
script, PowerBuilder automatically displays the picture you specified for the
"Disabled File Name".

PictureButtons have one more advantage over CommandButtons - the ability


to display multiple lines of text on the button and to format them around the
button. You can set the alignment of the text by using the
"Horizontal Alignment" and "Vertical properties".

Checking the "Original Size" property changes the picture to its original
dimensions, i.e. to the dimension the picture was given when it was first
created. Even if you check this option, you can still resize the control and the
picture will stretch to fit the size of the button. If you do this and look at the
properties of the button again, you'll see that PowerBuilder has unchecked
the "Original Size" property.
EditMask
The EditMask control allows you to take formatted input from the user. For
example, you might want to accept zip code from the user in the format
#####-####. If the user tries to input information into this control that
doesn't conform to the mask, PowerBuilder refuses to accept the keystrokes.

If you can go to properties, you can see, there are different data types
available under the "Options/Type" DropDownListBox. For each of these data
types, there are some pre-defined masks available. For example, if you
select the String data type, you can format the data in upper case (!), lower
case (^), number (#) and alphanumeric (a) characters. Most of the times,
these masks are enough for your needs. If you need a special mask, you can
as well create them by typing into the "Mask" option.
Note that the formatting of data is for display purpose only. PowerBuilder
doesn't store the data in the way it is displayed, in particular "date" type.
Dates are usually stored as a number representing the number of days from
a fixed date. This allows PowerBuilder to easily swap between formats by
simply applying the rules for the given format to this base number, rather
than performing two conversions and remembering what format the date is
currently stored in. For example, if the fixed date is 1st January 1994, then
3rd January 1994 would be stored as 2 and the 25th December 1993 would
be stored as -7. The point is that it doesn't matter to us how PowerBuilder
stores the date as long as we see it in a format that we understand and
require.

In versions prior to v5.0, there was an option in the dialog box to test the
mask you defined. However, it is no longer available in v5.0. You need to
either preview or run the window to test the defined mask.

One note from our experience is that, make sure you paint enough space
(may be a little extra than required) for the content to display in the
EditMask. For example, if you paint the height a little shorter for the
SingleLineEdit control, user can still type in data even though he can't read
the data comfortably. If you do the same to the EditMask control, it displays
no data at run-time.

AutoSkip isone of the interesting properties. If you turn on this property for


an EditMask control, focus will automatically jump to the next control in the
Tab List (We will explain in a moment) when the user has completely filled
the mask with the input. User doesn't need to either press tab or click with
the mouse-button to jump to the next control.

The Spin Control property is most often used with numeric data to allow the
user to increase or decrease the value in the EditMask control by clicking on
the arrows that appear at the corner of the control. You can see this
property in the print dialog box while specifying the number of copies to
print, in any application under MS-Windows.

You can enter the relevant information in the appropriate fields to specify
the minimum and maximum values for the control and the size of the
increment ( which must be a whole number).

You can also use the spin control option for the "date" data type fields. In
this case, only one part of the date will increment or decrement depending
on the cursor position. For example, if the cursor is on the month part of the
date, clicking on the upper arrow will increment the month by one.

While previewing the window, you won't be able to click on the spin control
arrows because you are previewing the window.

If you type in a value which is outside the allowable range, as soon as you
try to increment or decrement it using the spin control, the value will change
to the minimum or maximum value and won't allow you to move outside this
range.

Code Tables

If you want to use spin controls with string-type data, you can make use of
Code Tables. Code Tables work like look-up tables. That means, it allows you
to display the detail value, for the corresponding abbreviation. For example,
you may want to display "New York" on the screen, and store "NY" in the
database whenever user selects "New York". All you need to do is provide
"New York" for the "Display Value" property and "NY" for the "Data Value"
property. You can provide as many entries as you want in this "Code
Tables".
If you use "Spin Control" and "Code Tables" for the String data type values,
PowerBuilder displays values from the code tables that is specified in the
"display value", as the user keep clicking on the arrows in the "Spin
Control".

Tab Order
Tab Order defines the order in which the focus changes from one control to
another as the user keeps pressing tab key. Each control in a Window has a
tab order, which is measured in numbers. Controls with tab order 0 (zero)
can't be tabbed on. It is vitally important to provide a smooth and well
disciplined tab order, so that the user can easily follow the motion of the
focus around the window. Your applications will quickly be condemned as
unfriendly if you don't provide a sensible tab order.

To see the current tab order, select "Design/Tab Order" from the menu. In this
mode, you can't do anything (including saving the window) except changing
the tab order. You can see the tab order at the top of each control in red
color. To change the tab order of a control, you need to click on the tab
order number and type a new number.

PowerBuilder automatically creates a tab order which matches the order in


which you placed controls on the window, spaced out with increments of 10.

If you have ever programmed in BASIC, back in the good old days before
PCs, you might remember numbering your program lines with increments of
10 so that you could add extra lines later without having to re-number all
your lines. The same principle applies with the tab order set by
PowerBuilder.

The following controls are not included in the tab order or in other words,
have been assigned a value of zero:

StaticText
Graph
Picture
You can't tab into drawing objects or StaticText controls, so PowerBuilder
allocates zero tab value by default to these controls; which means that they
are not included in the tab order. This also applies to any RadioButtons or
any other mutual exclusive controls that you place on a Window.

These defaults are generated for two main reasons:

If you tab to StaticText or drawing object, you can't change anything, so why
would you want to tab to it?
If you change a set of mutually exclusive controls to have an 'active', non-
zero tab order, as each control receives the focus, it is also selected. As you
might guess, this can cause some consternation among your users.

When you place a custom User Object (We didn't explain what a User Object
is. For the moment, just remember that an User Object is a collection of one
or more objects) which contains more than one object on a window and tab
onto it, you can press Tab key until every control within it has been visited.
After that, continued tabbing will take you to the next control on the
window.

Once you change the tab order, choose "Design/Tab Order" again to come
back to normal mode.

MultiLineEdit

A MultiLineEdit control is similar to the SingleLineEdit control, but it lets you


enter or display multiple lines of text. Remember, the maximum number of
characters that you can enter in either a SingleLineEdit or a MultiLineEdit is
same, i.e. 32,787 characters.
Looking at the properties for the control you can see that you can select
horizontal and vertical auto-scrolling, scrollbars, limit the number of
characters and so on.

One important property is the Ignore Default Button property. If this is


selected, it will allow the user to hit the Enter key to start a new line of text
without triggering any CommandButtons whose "Default" options have been
set.

Do not confuse the "Tab Order" with the "Tab Stop" property. The Tab Stop
property allows you to display text in a table format and will be covered in
greater detail in the PowerScript session.

To get full understanding of scrollbar properties for MultiLineEdit control, place a control as shown in
the picture (at the beginning of the page) and turn on and off different scrollbar properties and
preview the window with a few lines of text. You will get an idea about how the text scrolls with
different scrollbar options.
ListBox
A ListBox control is used to display a list of options from which the user can
select one or more. Our example shows a list of countries with a vertical
scrollbar to scroll through the list. You select from the list by clicking on one
of the countries. By looking at the properties of the control, you can see that
we've typed in the options that we want to be displayed in the Items box:

The list of options is in the order in which we typed them, but when you
previewed the window, you may have noticed that the list was in
alphabetical order, because we've checked the Sorted property.

The "Disabled Scroll" property will automatically turn off the vertical
scrollbar, if there is enough room in the control to display all options.
There are two ways to allow a user to select more than one choice from a
list. Checking the Multiple Selections property allows any number of options
from the list to be selected by clicking on them. Clicking on a selected option
will then deselect it.

In MS-Windows environment, you can select a range of files using Shift and
left mouse button together. Similarly you can select random files using Ctrl
key and left mouse-button together. You can give the same functionality to
the user by enabling the "Extended Select" property.

The "Tabs" property specifies the position to stop within the ListBox, in terms
of characters, whenever user press "Tab" within the control. You can specify
up to 16 tab stop positions. We neither saw it working nor found it is useful
in any application.
Typical usage of ListBox

Typical a ListBox is used when you want to display more than two and less
than five multiple choices. If it is only two choices, you can use
Radiobuttons, but if it were more than two, using them would occupy most
of the screen.In those cases it would be better to use a ListBox. Using
DropDownListBox would be better choice if the options are more than five
and multiple selections are not required.

DropDownListBox (DDLB)
A DropDownListBox is used to display a list of available options when you
click on the down arrow at the right side of the box. This can be used to
save space on the window, as it takes up the same amount of space as a
SingleLineEdit controland more over allows you to select from a fixed range
of options. In the above example you can select one country from the
DropDownListBox. The advantages of DDLB over ListBox is that, DDLB takes
less space, but DDLB has one limitation. You can't allow the user to select
more than one option from the DDLB.
You can select the country by clicking on the one you want, or you can type
and the list will scroll down to the first entry that starts with the letters you
typed in. This is an important feature as it allows you to put a great number
of entries in a DropDownListBox, but still allows the user to quickly find the
one they want.

Again, you can choose to have the list Sorted and can enable or disable both
the horizontal and vertical scrollbars. If you don't have a vertical scrollbar,
you can still select from a long list using the cursor keys.
The Allow Editing property allows the user to type a new entry into the
control. If Allow Editing is enabled and you supply some Text, then that is
displayed in the control and becomes one of the selectable options.
However, it is not permanently added to the list, which means that if you
select another option from the list and then decide to change it back, you
will have to type it in manually.

If you allow editing of a DropDownListBox, it will be displayed slightly


different with the down arrow detached from the actual box. The 'Always
Show List' property means that the list of options will always be displayed,
so the control effectively becomes a standard ListBox.

CheckBox
A CheckBox is used to select or deselect a given option. For example, you
may want to find whether the user is employed or not? You can achieve this
with the help of a Checkbox.

If required, a CheckBox can have a third state, which means either


undecided or a mixed state. This option is activated by checking the control's
"Three State" property.
A better example of the "Third State" property would be a part time job. This
position is neither full time employment nor an un-employment.

"Checked/Third State": The default value of a CheckBox is Unchecked, but


you can change this by selecting either Checked or "Third State" properties.

Selecting the "Three State" property allows the Checkbox to have three
states and selecting the "Third State" property makes the "Third State" the
default state.

"Left Text": The "Left Text" property displays the text to the left of the
CheckBox. By default, the text display is on the right side and the Checkbox
on the left side. Deselecting it reverses the order, placing the CheckBox on
the left of the text.
"Automatic": By default, "Automatic" property is turned on. When this option is turned on, at run-
time, the Checkbox automatically changes the state (checked/ un-checked/ third state) as the user
clicks on the Checkbox control. If the option is not turned on, you need to change the state
programmatically.

RadioButton
A RadioButton is similar to a Checkbox, with one difference. When you place
more than one Checkbox on the window, you can check any/all/one
Checkboxes on/off. Every Checkbox is independent. Similarly, if you have
more than one RadioButton placed on a window, you can always turn on
only one RadioButton, no matter how many Radiobuttons are there on the
window. This behavior makes sense in the example given below, because
you can't be single and married at the same time!

If you select one RadioButton when another RadioButton is already selected,


the first RadioButton will be deselected before the second RadioButton
becomes activate. Other properties for the RadioButton are similar to those
of Checkboxes.

Sometimes, you might have multiple logical groups. For example, from the
above picture, Radiobuttons related to "Sex" is one logical group, while other
Radiobutton belong to another logical group "Martial Status". That means
user should be able to choose one option from each question, similar to the
picture. By default, it is not possible, since as soon as the user selects
another Radiobutton, previously selected RadioButton becomes de-selected.

For practice, paint the window as shown in the above picture and try to
select options from each logical group and see, whether you are able to or
not.

The solution for this problem is using a Groupbox. We will explain this in
"Groupbox"

Groupbox
The GroupBox control is used to group related objects together, but it is
generally used to group sets of related Radiobuttons together. When there is
no group box in the window, the window behaves as a group box. That's
why, you can select only one RadioButton, no matter how many
Radiobuttons are there on the window.

For example, you have two questions, one is "Martial Status" and another is
"Sex". In this situation, you need one answer for each question. If atleast
one question is not in a GroupBox, user can't answer both questions, since
he would be able to select only one option for both questions together. The
solution for this problem would be, either put each set of answers in a group
box separately or put at least one set of answers in a GroupBox. If you put
one set in a GroupBox, window behaves like a GroupBox for another set of
Radiobuttons.

Picture
A Picture control is used to display a bitmap, Run Length Encoded file or
Windows metafile on your window. Turning on "Invert image" property,
inverts color of the image. After placing the picture control in the window,
you might have resized few times and might want to see it in its original
size, then just  turn on "Original Size" property.
OLE 2.0 Control
Since, OLE is a huge topic in itself and can't be explained here, we will about
it explain briefly; we won't go into much details at this point because it
would be too advanced at this stage.

An OLE control allows you to place a non-PowerBuilder object in the


PowerBuilder window (You can create an OLE object from PowerBuilder and
place that one also. Details in the coming sessions). For example, you want
to present a Microsoft PowerPoint presentation from within PowerBuilder
application, or you may want to allow the user to edit a document in MS-
Word invoked directly from PowerBuilder. In the above two cases user  won't
even know that another package is being invoked. He feels to be in
PowerBuilder but actually no.

At this initial stage we think it would be enough, rather than to introduce too
many new technologies.
Graph Control
PowerBuilder allows you to add a Graph to your window with the help of this
control, in any of the common graphical formats to present the numerical
data.

There are numerous options for the properties of this control relating to
titles, legends and axes, as well as the type of graph.

We won't go into details about it here.  In comparison with "Graph


DataWindow", usage of a graph control in a Window is rare.  So it is better
to learn about Graph control once you complete DataWindow session.

PowerBuilder Graph Terminology

Category: Categories are the major divisions of data. For example, we can divide all transactions
into three major divisions (types) like 'Receipts', 'Issues', 'Returns'. In the above graph, there are
three categories.
Series: Suppose, say you are comparing transactions for two products then, you will find receipts
for each product, issues for each product and so on. In this example, each product is a series. Series
are a set of data points. Let's take another example, say you are comparing transactions of a product
for each month. Here you have 12 series, which means that you are comparing receipts for each
month, issues for each month as well as returns for each month.

Values: This is the value of each series or category ( if no series are present ). The total number of
receipts, total number of issues and total number of returns are values. Display of 'value' varies
between graph types.

Title: The title of the graph. By default it appears at the top of the graph.

Category Axis: Category axis is the axis where the categories (major divisions of data) are
plotted. Typically it is on the x-axis.

Series Axis: Series axis is the axis where the series (set of data points in a category) are plotted.
In two-dimensional graphs this is on the same axis as the category axis. In three dimensional graphs
it is different from the category axis. You can see this in the graph above.

Value Axis: Value axis is the axis where the values are plotted. Typically it is on the Y axis and
varies in different graph types.

Legend: Legend displays how the series are represented. For example, you may have different
colors for receipts, issues and returns. You can see the legend at the bottom of the above graphs. You
can display legend at different places on the graph such as bottom, top, left, right, etc..

Ticks: Ticks displays the starting of another value on the value axis and represents categories on
the category axis. You can display these ticks inside, outside or straddle (half on inside and half on
outside) the axis. You can display ticks for major divisions as well as minor divisions. For example, the
major division is 500 and if you want to display 4 minor divisions then PowerBuilder will display a
minor division tick 4 times (after every 125) between each major division. The ticks for minor division
can't be a straddle. Similarly, you can display label for each major division, but not for minor division.

Graph Types:

Column Graph:

In this graph the values are plotted along


the Y axis and categories are plotted along
the X axis. This type of graph is good for
noncontiguous data.

Bar Graph:

It is similar to column graph except for the


graph orientation. In this graph, values are plotted along the X axis and categories are plotted along
the Y axis.

Line Graph: This graph is good for displaying continuous data, for example time and
temperature. The data points are connected by lines. Graph properties such as overlap %, spacing %
do not apply for this type of graph since the datapoints are connected by a continuous line.

Area Graph: It is similar to line graph except that the area under the lines are filled with color.
When this graph has a series, each series is filled with a different color.

Stacked Graphs:

In stacked bar/column graphs, each category


is displayed as one bar or column instead of a
separate bar/column for each series in the
category. You can choose between stacked,
solid stacked, 3D stacked bar/column graphs.

Pie Chart Graph:

This graph displays the data as percentage of all the


data. PowerBuilder automatically calculates the
percentage. If you choose to have series in this
graph, they are displayed as concentric circles.

Scatter Graph: This graph is different from all the graphs explained earlier. This graph does not
use categories, instead it plots data values on both X and Y axis. This graph is used to display the
relation between two data points. For example, speed & mileage, speed & production, project team
size & time taken to complete the project, etc..
Three Dimensional Graphs:

All the above mentioned graphs have 3D graph


versions except for scatter graph. The picture on the
side is a three dimensional pie chart.

Graph Control Properties

You can specify the sorting order for the series as well as categories in the 'Series Sort' and
'Categories Sort' options. Using the 'Legend Location' you can specify the location of the legend, it can
be bottom, top, left or right.

The 'Spacing (% of Width)' specifies the space between each category. Unless you have too many
categories, you don't need to adjust this property. The 'Overlap (% of width)' specifies the percentage
that each item in the category that should overlap. This property is more useful when you use bar or
line graphs. The 'Depth (% of width)' property specifies the depth of each item in the category and
can be set only for the 3D graphs such as 3D piechart, 3D column, 3D bar, etc..
In the 'Text' tab you can specify properties for text such as title, value axis, category axis and so on.
Select the text object for which you want to set properties from the 'Text Object' ListBox and set
properties for that text object. Other than the regular font properties, you can rotate the text either
left or right in 450 or 900. This option is not available for title and legend.

Infact, the 'AutoResize' feature is the best option that you may always want to turn on. Turning on
this property will adjust the text size automatically when the graph control is resized. This can be the
case when you may want to resize the graph control in the window everytime the window is resized at
run-time. You can't specify the font size when this option is turned on, which makes sense.

You can make the background color transparent in the graph control; this option is not available in
most of the other window controls. For each text object, you can specify the display expression. For
example if you want to display the date in the title,

title + "as of " + today()

In the above expression, title is the property of the graph control.


This value, i.e. title can be specified in the 'Title' property on the
'Graph' tab page. Such as, if you are creating this graph to display
inventory then you may want to set the title as 'Stock'. At run time
the title for Jan 1st 1997 would be:

Stock as of 01-01-1997

If you don't specify any expression, PowerBuilder takes the value of


the category/value and uses it.
On the value axis you can specify the minimum and the maximum values to use or you can choose
'AutoScale'. In the later option, PowerBuilder takes the maximum value in the data and adjusts the
value points automatically for you. Depending on the Data value you can specify 'Round to Maximum'
property. For example, if the value axis data type is numeric, then specifying 1 will round the fraction
to the next integer value. If the value axis is of date data type then the value is rounded to the next
highest year.

On the value axis you can divide the axis into some major divisions. For example, to display 5 data
points each incremented by 100 you specify 5 for the 'Number' under the major divisions. If left to the
default zero, PowerBuilder takes care of creating major divisions. PowerBuilder displays one tick at
each major division. You can choose the tick type as 'inside', 'outside' or straddle. Similarly, you can
choose to display grid line for major division.

You can divide each major division into few


minor divisions and ask PowerBuilder to
display ticks and grid lines for each minor
division. However, you can't display labels
for minor divisions.

If you are creating a Graph presentation


style DataWindow, you find one more tab
named 'Data'. In this tab you can specify
the column that can be taken as value,
category and series axis. However, in the
graph control, you need to add data to the
graph control at run-time through scripting.

Unlike the RTE control ( where it can share


data with a DataWindow/ DataStore ),
graph control can't share data with a
DataWindow control/ DataStore object.

In case
of
three dimensional graphs you can specify rotation,
elevation and perspe

DataWindow Control
A DataWindow control is a container for a DataWindow object. The definition
of a DataWindow object contains the data source (SQL Statement/ Stored
Procedure) and the format of the results. You paint the DataWindow Object
in a DataWindow painter. DataWindow Object it self can't do anything. You
need to place a DataWindow Object in a DataWindow control. All the script
you write is for the DataWindow control.

In version 6.0, this control supports 'Right to


Left' property.

To use a DataWindow control, you must:

Create a DataWindow object which contains data from the source.


Add a DataWindow control to your window.
Associate the control with the object.

We don't have anything for practice at this time. Only it would be after
completing "DataWindow" session

User Object
User Object is an object that is defined for reusability purpose. An example
would be to display microhelp whenever mouse pointer moves over any
CommandButton. What is the best way to do it? Method one would be
( which is not the best one ), to write script for each and every
CommandButton in the application. It works fine; but the drawback of this
method is that you duplicate code at each CommandButton. If a need to
change some functionality occurs, you need to change code in all
CommandButtons. It is time-consuming and the probability of missing some
places is more.

An other way of accomplishing the same is to define an User Object of type


CommandButton and write code there. Start using this new User Object
instead of the Standard CommandButton. Here, you are not duplicating the
code, instead you are reusing it. When you want to change a functionality,
apply the same in the User Object and you are done.

We won't go into details here, because, explaining User Objects takes a


session by itself. Here we just wanted you to know what an User Object is.

At this point, we don't have anything for practice. It


would be waiting for you after completion of "User
Object" session.

Horizontal and Vertical Scrollbars


Typically use of Scrollbars is to display percentage. Some examples:  to
display the amount of work completed, or the percentage selected. You
might be seeing the scrollbars at the bottom of a window (say MS-Word) or
at the right hand side of the window.

However there is a difference between scrollbars under Windows 3.11/NT


3.51 and  Windows 95/NT 4.0. The H/Vscrollbar controls available in
PowerBuilder belong to the first category, even if you use PowerBuilder
under Windows 95/NT 4.0.

The indicator in the Scrollbar in the first category, represents the cursor


position in terms of the percentage of the whole content.

The indicator in the Scrollbar in the second category not only indicates the
current cursor position in terms of the percentage of the whole content, but
it also indicates the percentage of the content that is being displayed on the
screen.

In real life projects usage of Scrollbars is less than one percent, since most
of it is accomplished by a DataWindow control.

PictureListBox
PictureListBox is similar to ListBox control, only with an added advantage of
picture display capability for every option in the ListBox. In the normal
ListBox, this can't be done.

Picture names to be displayed in the ListBox can be filled in the Picturestab.


While filling the item names in the Items tab, you can specify the picture to
be displayed for each item. If you choose, you can display the same picture
for multiple items.

We think it would be better for us to allow PowerBuilder to specify items and


pictures in the tab page, so as to avoid switching between tabs
DropDownPictureListBox
This control is similar to DropDownListBox but, with an additional capability
of displaying pictures along with the items

ListView
ListView and TreeView are Windows 95 controls. In simple terms, a ListView
control has functionality similar to that of a PictureListBox. However, a
ListView is more flexible and allows you to develop more user-friendly
applications.

Recall that in a PictureListBox you can assign pictures to each item, where
as in a ListView, each item can be associated with three pictures. One Large
picture, one Small picture and one picture to indicate the state of the item.
You can display a ListView in different presentation styles:

Large icon view


Small icon view
List view
Report View

If you select "Fixed Location" property, users can't move the items in the
ListView control at run-time. Otherwise, users can drag and arrange the
icons, to suit there needs.

You can allow the user to edit labels at run-time, by turning on " EditLabels"
property. You can also allow the user to delete items, by turning on " Delete
Items"property. The label may overlap other labels if it is very large. It
would be always better to check "Label Wrap" property.

It is a good idea to preview the window each time you enable/disable


property for the ListView control. This way, you understand it better. When
selected, you may not be able to see the affects of "Report View" style. You
need to do some programming  to view, how a ListView control looks like in
"Report View" style. So let us skip this part until we teach you about
PowerScript.

TreeView
TreeView is similar to a ListView and it is more powerful. As the name
suggests, it allows you to display items as a branch.

Tab Control
Tab control allows you to paint "organizer" like user interface. Did you
observe that  you have been using tab control? The properties dialogbox of
any control uses tab control. Tab control is new to version 5.0, till then
programmers were simulating tab control with the help of User Objects. We
can skip the tedious programming techniques.

Place a tab control on the window. By default it has one page. To insert
more pages, click with the right mouse-button and select "Insert Page"
option. Invoking popup menu by clicking in the free area next to page name
( Area 1 in the picture) allows you to select properties for the tab control. If
you invoke popup menu by clicking in the area below the page name (Area
2), it allows you to specify properties for the page.  , First let us see the
properties.
"PowerTips": By turning on the "PowerTips" property,  you can display
PowerTips for the page names, similar to the PowerTips for the toolbar icons.

"Fixed Width": By default, the tab size automatically adjusts to the width of
the tab page name. That means, the area that displays the tab page name
may be longer and sometimes shorter, depending on the length of the tab
page name. To make all tag page's tab to have the same width turn on
"Fixed Width" property. In this case, the tab page's tab width is decided by
the longest tab page text.

"FocusOnButtonDown": This property is similar to "FocusRectangle" property of


other controls. Turning on this option would display a dotted rectangle line
around the tab page name whenever user clicks on the tab page and brings
the tab page to the front.

"ShowText", "ShowPicture" Properties: In a given situation if you don't want to


display the tab page text (We don't see any need), just turn off "ShowText"
property. While this property is off, tab page text will not displayed even if
the tab page has some text. Similar to the menu object, you can assign a
picture to each tab page. Similar to the "ShowText" property, you can turn
on/off "ShowPicture" property.

"PerpendicularText": By default, a tab page name is displayed horizontally. If


a need arises, the name can be displayed vertically . This can be done by
turning on the "PerpendicularText" property. Similarly you can display text in
multiple lines by turning on "MultipleLines" property".

"RaggedRight": Turning on the "RaggedRight" property stretches the right most


page's name display area till the edge. To test this, insert two more tab
pages by selecting "InsertPage" from the popup menu. Turn this property on
and off and see how it works. "BoldSelectedText" property, as the name
suggests makes the selected tab page's text bold.

In cases where there are more tab pages than the number of tab pages that
can fit in the display area, PowerBuilder automatically displays scrollbar
icons. The position of the icon depends on the "TabPosition" property.
"TabPosition" property gives a wide choice of area to display the tab page
text.
Once the tab control is painted, you may want to rearrange the tab pages.
This can be done by dragging and rearranging in the "PageOrder" tab in the
dialog box.

Wondering where to define picture name, text for PowerTip, etc.; double-
click on the page itself (area-2). You can define name for each tab page,
text and picture for the tab page in this dialogbox.

RichTextEdit Control
RTE control gives you the power of WYSIWYG text editing in PowerBuilder application. Using this
control you can provide word-processor like interface. You can see the real power of a RTE control
only when you share data from a DataWindow.

General Properties: Create a new window and place RTE control on it. Similar to any other
window control, this control has 'visible', 'enabled', 'DragDropIcon', 'DragAuto' and 'Pointer' properties.

RTE Control showing invisible characters

Invisible Characters: You can control the type of characters that are to be displayed in this
control. For example, if you wish to display tab characters, you need to turn on 'Tabs Visible' property.
So are 'Returns Visible', 'Spaces Visible', 'Fields Visible' properties. 'Fields Visible'
property is useful when you share a DataWindow /DataStore with a RTE control and use DataWindow /
DataStore fields in the RTE control; otherwise, this property has no effect on the control display
behavior.

Popup menu: If you have used MS-Word, you might have used popup menu in the word-
processor for context sensitive operations such as Cut, Paste, Copy, etc.. Similarly, you can make
PowerBuilder to display the popup menu for the RTE control by enabling the ' Popup Menu' property.
Except for a single mouse click you don't need to write code to display the popup menu in the RTE
control.
Paragraph properties dialog box at run-time

RTE Control Toolbars: You can display a toolbar in the RTE control by turning on the
'Toolbar' property. Don't mix-up RTE specific toolbar with the general toolbars such as Powerbar,
Painterbar and custom built toolbar for your application. RTE has one more toolbar called a 'Tabbar',
that allows the user to set tab positions for different lines in the RTE control text. Similarly you can
make the ruler bar visible.
Properties dialog box at run-time.

Word Wrap: By turning on 'Word Wrap' property, you can control whether the text should wrap
around if it reaches the right margin of the RTE control.

Margins: Margins can be set using 'Left Margin', 'Right Margin', 'Top Margin' and 'Bottom
Margin' properties.

Undo Depth: Maximum number of undo levels can be set using 'Undo Depth' property. The
default value for this property is zero, that means nothing can be undone.

Pictures as Frames: When there are more pictures in a document or when you want to display
the RTE control faster, turn on 'Pictures As Frame' option. By default, PowerBuilder displays the
picture as it is. However, you can choose not to and instead display a frame area that is equivalent to
the picture dimensions.

Print Document Name: When a document is printed from the RTE control the name specified
in this property is used to be displayed in the print queue .
 Drawing Objects
You can make use of drawing objects to improve the appearance of the
window you paint. You can notice (from the picture below) that Drag-and-
Drop properties are missing for controls that fall under the Drawing
category. Make a note that Drawing controls don't have any events and
moreover you can't define user-defined events (details in future sessions).

The only drawing control that has interesting properties is the


RoundRectangle. The "Corner Height" and "Corner Width" properties allow you
to specify the degree of roundness that should be applied to the corners. The
"Corner Height" property defines how far from the corner on the vertical
edges should the curve begin, while the "Corner Width" property affects the
same, except that it affects the horizontal edges.
Given the starting points, two for each corner, PowerBuilder calculates the
smoothest possible curve between the two points closest to each corner, to
produce a rounded rectangle.

Selecting Multiple Controls


There are two ways in selecting more than one control. The first method
involves holding down the Ctrl key while clicking on the controls you require
or secondly you can click on the window and drag a box ( as shown in the
picture below ) to surround all the controls you want to select.

The above screen-shot is an example for selecting multiple controls. Note


that for a control to be selected, it needn't be completely enclosed by the
box.

When you select a control, the corners turn black to indicate that it is
selected and you can then affect any changes against it. This holds true for
multiple control selections, but the actions you can perform against such
selections are less.

Some of the actions you can perform against a multiple control selection
include:

Moving them.
Aligning them, based on axis.
Resizing them, based on the size of one control.
Spacing them, based on the current spacing between the controls.
If you have any problem in selecting multiple controls, click on the projector icon, for a demo
(movie.gif).

Moving Controls
This is the easiest action to be performed in a multiple control selection. To
move all controls so that they retain their relative positions, select the
controls that you wish to move and click on one of the controls and move it
to its new position.

PowerBuilder will indicate where the controls will end up by an image of the
controls moving around the window until the left mouse button is released.

Aligning Controls

You might have experienced that you can't align controls in a window. To
align a group of controls, select controls using one of the methods outlined
above, and then select "Edit/Align" and choose one of the following methods
of aligning the controls:

If you use the Ctrl method to select controls, PowerBuilder will use the first
control selected as the reference point. The reference point control doesn't
move and all other controls conform to it. If you use the box swipe method
of highlighting multiple controls, the reference control is the last one that is
selected.

Spacing Controls
To make spaces between your controls equal, you can select "Edit/Space
Controls" and select either horizontal or vertical spacing.
PowerBuilder takes the first two controls that you select and uses the space
between them as the default space to space all other controls.

Note that you should use the Ctrl key method of selecting controls,


otherwise PowerBuilder won't be able to determine the first two controls and
when it spaces them you will not get what you want!

Sizing Controls
If you want several controls to have the same size you can select the
required controls and select "Edit/Size Controls".

The note that was made for aligning controls also applies here. Use
theCtrl method of selecting the reference control for the sizing to base upon.

The Grid
Using these tools to manipulate your controls can take a while to get used to
and when they do become second nature, they can still be a little unwieldy.
To help you out with this problem and to speed up the process, you can use
the Window Painter's grid as a basis for your controls positioning.

The Window Painter's grid is turned on by default when you first  create a
window.

To look at the properties that PowerBuilder associated with the grid, select
"Design/Options" and click on the "General" tab.

You can change the horizontal and vertical spacing of the grid by changing
the X and Y values and, if you check the "Snap to Grid" option the size
controls will snap to the nearest grid point when you move them. This
enables you to size, space and align controls very quickly.

Duplicating Controls
If you want to add several similar controls to a window, you can use the
duplicate tool. Select the control you want to duplicate and press Ctrl + Tor
right-click on the control and select "Duplicate".

Another control of the same type is created and placed below the original
control. The new control gets all the appearance properties such as text,
colors, font, font size, borders and so on, and is named with the next
available control name. Unfortunately, any scripts or user events that were
created for the original control aren't copied to the new control.

Copying and Pasting Controls


Another way of duplicating a control is to use the Copy and Paste options
from the Edit menu or use the Ctrl+C and Ctrl+V shortcut keys. When you
use this method of copying controls, all the properties of the original control
will be copied including scripts if any and the name of the control. For
example, if you copy one of the CommandButton, you'll get the following
warning:

You can't have two controls with the same name on the same window, so
you have to type in a new name before PowerBuilder creates the new
control. The control is copied directly on top of the original control, so you'll
have to move it to verify that its presence

You can also use Copy and Paste method to copy controls between windows.
PowerBuilder does allow you to have two controls with the same name in
different windows, so you won't get a naming conflict warning when you
attempt to copy a control onto the other window.

Listing Controls
As we have just seen, when you copy and paste a control, it appears directly
on top of the original. Back in the section on CommandButton, we saw that
when you deselected the visible property, the control disappeared from both
the run-time and the design view.

Both of these situations can cause you to 'lose' some controls visually to get
around this problem PowerBuilder allows you to see a list of all the controls
that you have placed on a window. This catalog of controls is called the
Control List and you can call it up by selecting "Edit/Control List..."
You can select all of the controls on your window from here, and  affect
changes against any of the properties of it by selecting the Properties button
to take you to the relevant properties dialog.

Sometimes, you may place a control on the window, but don't want to
display it to the user. So set "Visible" property to false. When you do this,
you can't see the control at painting time as well as at run-time. If you want
to see all the controls including hidden controls at painting time, select
"Design/Options" and select "Show Invisibles" option in the "General" tab. This
displays the hidden controls at painting time only.

Defining Tag Values


You can store the description about the control in the " Tag" property. Do not
confuse it with the "Text" property. The text property displays text on the
control, where as value of the tag property does not get displayed on the
screen. It is for programming purpose only. Typical use of tag property is to
display its value as microhelp (help that is displayed on the status bar). If
you are using Version 4.0, you can define tag values for all controls on the
window, from a single place, by selecting "Edit/Tag List". If you are using
version 5.0, you can define the same in the "Properties" dialog box. You can
also make use of tag property for displaying help for the system you
develop, in the standard windows help format.

Window Properties
We've looked at all the controls available in a window and properties for
each control and seen how to manipulate these controls on a window.
However, the window itself has certain properties. To see the properties of
the window, click with the right mouse-button in the windows workspace
(the space that is not occupied by any control in the workspace) and select
"Properties" option.

You might have observed that till now, when you do the window preview,
"Untitled" is being shown in the window title. You can change the window
title in the "Title" prompt.

Each window can have a menu associated with it. For example, while
painting a window, you are in the Window painter; you see a menu at the
top and a toolbar (Painterbar) associated with the menu. The term
"associated" means that the options in the menu have a corresponding
toolbar icon in the Painterbar. Similarly, you can paint a menu (We will
explain in the next session) and associate that menu to any window you
want. A menu can be associated with any number of Windows, where as a
Window can have only one menu associated with it. (You can't associate a
menu at this moment, since we didn't paint a menu yet.) Whenever you
open the window at run-time, the menu will be automatically displayed.

Standard window (Under MS-Windows) properties such as "Maximize Box",


"Minimize Box", "Resizable property" can be turned on/off. All the above
properties are independent of each other. When you want to turn on/off
depends on the application requirement. Depending on the window type (we
are going to explain types of windows in a moment), some of the window
properties are not editable.

The following table lists Window types and properties. If nothing is


mentioned in the table it means that you can turn the property to either
True or False.

Property/Window Main Child Popup Response MDI Frame MDI Frame with
Type Microhelp

Border Always Always On Always On Always On


On

Titlebar Always Always On Always On


On

Maximize box

Resizable Can't
have

Minimize box

Control Menu Can't


have

Menu Name You must provide at You must provide at


design time design time

Window Color

You can specify a color for the window itself. By default, the color of the
window is "Window Background". We know that the sentence is a bit
confusing. To get out of the confusion, we need to explain some MS-windows
color theory.

All system windows and applications that follow MS-Window's standards use
MS-Window's system colors. You can view/change system colors from the
"colors" option in the Control Panel.
Here you can specify what window's background color should, what color the
window title should have, what colors enabled/disabled menu options should
have and so on.

Coming back to "Window Background", if you select any color other than
this, the end user will always see the color you specify. Please note that
some users may not like the colors you defined or some users may be color
blind. That is one of the reasons why users start disliking the system.

If you select the window color as "Window Background", the color of the
window you painted would be the color they specify in the Control panel.
That means every user can have the color they want.

For example, the "Window background" is defined as "Gray" on your system.


You develop and deploy the application. The window color won't be
guaranteed to be "gray". The window color on the user machine would be
the color he defines as "Window Background" color in the control panel on
his machine.

Window Size and Position

The X and Y values specify the position of the top left-hand corner of the


window. Changing them would be useful for child and popup windows but
you also need to change them at run-time. So, just leave them to the
defaults and change them at run-time only.
The size and height of the window can be changed from this dialog box.
However, we don't see any need for changing this property from this dialog
box; you can as well grab the edge of the window and drag it to the required
size and position.

You can choose how to open the window: maximized, minimized or normal
size. The initial position of the window when it is open would be in the
position you specify.

The scrolling options allow you to specify how the standard Windows
scrollbars should work. The defaults are as follows:

Scrollbar Default Value

Horizontal Units Per Scroll Columns 0 - 1/100th of the width of the window

Scroll Columns Per Page 0 - 10 columns

Vertical Units Per Scroll Line 0 - 1/100th of the height of the window

Scroll Lines Per Page 0 - 10 lines

Types of Windows
There are six types of windows available in PowerBuilder. They are all
created in the same way, but each has a specific task for which it is used.
You don't have to specify the window type before you create the window.
The default window type is: "Main".

Main Window

A Main Window is a stand-alone window, which acts independent of all


others. This type of window can be minimized, maximized and resized; they
can also overlap and be overlapped by other windows. They are usually
used:

in single window applications,

As sheets in MDI (Multiple Document Interface) applications. (We will explain about MDI concepts
& programming in the comming sessions.
If you open say, 3 windows of type "Main", each window behaves
independently. For the user, it looks as if they are 3 different applications.
Closing of one window doesn't exit the application unless it is the last open
window on the screen. Minimizing a window will display the minimized icon
in the "Program Manager"; Under Windows 95, it would not be displayed
anywhere.

Popup Window

A Popup Window is typically opened from another window, which is then


said to be the popup window's parent window.

The popup window is dependent on its parent window, but it can also be
displayed without opening it from the parent window.If you do not open the
popup window from another window, it will behave like a main window.

Parent window will not overlap a popup window, but if a parent is minimized
popup window will be hidden.

Response Window

A Response Window is the PowerBuilders equivalent of a Windows dialog


box; it is used to accept response from the user, to display warnings and so
on. A response window demands action from the user and once active
remains active until the user answers.

If a window behaves in this manner it is said to be modal.

When a response window is opened, you neither can move to another


window within the same application nor can you resize, minimize or
maximize the opened response window. You can switch to any other
application that you have opened under Windows, but when you return to
the current application, the response window will still be active.

A typical example of where you might encounter this type of window is when
you want to save a new document using your favorite word-processor. When
you click on the save option, the word-processor can't save the file as the
document is as still untitled and therefore displays a 'Save As' window,
asking for the required information.

Until you answer this question, the word processor will not allow you to
continue , unless you click on the Cancel button and throw away the whole
idea of saving the document.
Child Window

As in "popup window", a Child Window can only be opened from another


window, its parent. Even though you specify the window type as "child", it
will behave like a main window, when opened directly, i.e. not opened from
another window. "Directly" means from an application object, from a menu
option and so on.

A child window can't be moved outside the parent window boundaries. If you
try to move a child window outside its parent window limits, all the window
area that you expect to see outside of parent window would disappear. To
see the full window area again you need to move back the child window into
the parent window.

On the other hand, if you move the parent window, the child window will
maintain its relative position within the parent.

A child window can't have a menu associated with, but a child window can
still have a title bar. When you minimize a child window, the minimized icon
is displayed at the bottom of the parent window and when it is maximized, it
occupies the entire parent window. A child window is never considered as an
active window. It doesn't mean that you can't do anything in the child
window. The interpretation of "never considered as an active window" is
from programming and not from the end-user perspective. When you close a
parent window, any children that are inside it are closed automatically.

MDI Frame Window

A MDI Frame Window allows you to open multiple windows as sheets


inside it. We will explain PowerScript in the coming sessions. For better
understanding: Open() is the function that you need to call to open a window
programmatically. As explained in  "Main Window", when you
useOpen() function, the window behaves independently once open. If you
open ten windows, it will look like they are ten different running applications.
You feel as if all windows are independent and you can see Program
Manager also.

You can use another function OpenSheet() which gives you the functionality of


"developmental environment" of "PowerBuilder". When you first invoke
PowerBuilder, you see a window, i.e. a PowerBuilder window. Within that
you are opening all these painters. You can see that all these painters are
open within the PowerBuilder window. You can't move a window outside the
PowerBuilder window . When you close PowerBuilder window, all those
painters that are open will close. In PowerBuilder terminology, all the
windows that are open within the MDI window (in this example,
PowerBuilder window it self), are called as "Sheets". Well, as a developer,
we call them as painters. MS-Word is the good example for this.

When a window (sheet) inside the MDI Frame window minimizes, the
minimized sheet icon is displayed at the bottom of the MDI Frame window.

MDI Frame with Microhelp

This window is exactly like an MDI Frame, except that it has an additional
feature of a status bar at the bottom of the window. This status bar is used
to display context-sensitive help like current time, etc..

PowerBuilder opening window is a good example of this type of window.


When you move the mouse over the toolbar icons, microhelp is displayed on
the status bar giving you an idea of what the icon stands for.

By resizing this window's workspace, not only are you defining your design
area, but you are also defining the size of the window when the application
is run. Clearly, if you have enabled the Maximize, Minimize and Resizable
properties of the window, you will be able to alter this sizing at run-time, but
when the window is initially opened, it will be displayed within these
proportions.

Testing a Window
We've already explained how to preview a window after you paint it. In the
preview mode view how the window looks like. If there are scripts they won't
execute in the preview mode. There are two ways of running the window.
One method is, write script in the application object's script and run the
application. This method is good when you want to test the whole
application, or when this window is dependent on the application object
events. Sometimes, you may want to test the window alone. In this case,
you can run the window without running the whole application, by selecting
the window toolbar icon (The icon which is filled with gray color, NOT Blue
color) from the Powerbar.
If you haven't saved the changes, PowerBuilder prompts for saving the
changes. After that, you will be prompted for the window to run. Remember,
when you selected "Design/Preview" to preview the window, you can only
preview the currently open window. However, irrespective of the window
that is open currently, you can run any window. Note that, while running the
window, appropriate scripts will execute.

Assume that you have two windows with the same name, but in different
libraries and these two libraries are in the application "Library list".
PowerBuilder displays the first window that it finds in the library list
( PowerBuilder searches objects in the library list in the same order you list
them ) in the "Run Window" dialog box. It does not display the second window.
That means, you can't test the other window. If you really need to test the
second window, one way would be to open and save that window with a
different name and test it. Once testing is done, save it back to the original
name.

Sometimes, you might have a window with NO "Titlebar" and want to test
the window alone. You can do it, no problem. The only problem would be
closing the window with no CommandButton with script in it to close the
window. In this situation you can't come back to the development
environment. What you could do is switch to "PowerBuilder development
environment (keep pressing Alt Tab key combination till you see
"PowerBuilder - Your application Name" task). PowerBuilder prompts you as
shown below. Say, yes. It will stop running the window.

Summary
In this session, you have learned about creating a window, various window controls & objects, window
properties and various window types, previewing and running a window. To read a full summary of the
session, click on window.ppt which is a PowerPoint presentation. If your browser do not open
PowerPoint viewer automatically upon clicking on that link, you may not have PowerPoint viewer
installed on your machine. Please visit 'Software Setup' page which is at the beginning of the course
and download PowerPoint viewer at free-of-cost.

Window Painter - Questions & Answers


Which control has Password property and what does it mean?

SingleLineEdit control has the Password property. When this property is set to true, at run-
time the value entered into this control is displayed as stars ( ***) instead of the actual
data. The actual value is available through program. This is useful when you don't want
other people to watch the data you type into the control.
Which control allows you to input multiple lines of text with different attributes such as
bold, subscript, tabs, superscript, colors and so on?
RitchTextEdit control

What does Extended Select property mean and which control has that property?

ListBox control has Extended Select property. This property allows you in selecting:
multiple sequential items in a ListBox using Shift key.
multiple non-sequentially placed items using a Control key.
In which of the following attributes of a CommandButton changes are allowed?
Text
Border
Background color
Name
size
Font color
You can change Text, Name, Size of a CommandButton. You can't change Border,
Background color, Font color of the CommandButton.
What advantage a PictureButton has over a CommandButton?

PictureButton allows you to display a picture along with the text on the button. You can
also display text in multiple lines which is not possible in a CommandButton.
If there are ten Checkboxs placed on a window, how many of them can you check off at
any given time?
You can check off any number of Checkboxes.

If there are ten RadioButtons placed on a window, how many of them can you check off at
any given time?
You can check off only one RadioButton at any time, unless you place some RadioButtons
in a GroupBox control.
What is an accelerator key?

Accelerator key allows you to select a control using the keyboard instead of a mouse.

What is tab order?

Tab order specifies the order in which the focus moves from one control to another when
the user presses the tab key.
Explain the Default, Cancel properties that are available for a CommandButton.

Clicked event triggers when the user presses Enter key, if the Default property is set.
Clicked event triggers when the user press Esc key, if the Cancel property is set.
In a situation given below, how do you prevent the triggering of CommandButton's clicked
event, when the user presses the Enter key.

A window has a CommandButton with Default property checked off. This


window also has a MultiLineEdit control and it has the focus.
You need to set Ignore Default Button property for that MultiLineEdit control.

Explain the behavior of a "Response" window.

A "Response" window doesn't allow you to do anything within the application except in
the "Response" window.
What is a code table? Which controls have this property?

Code tables allow you to do translation. It allows you to display long names on the control
while allowing you to save short names. Only EditMask control allows you defining "Code
Tables" property.
There are few controls in a window whose visible property is  turned off because you don't
want to display it at run-time. How do you make the hidden controls visible while you
paint the window.
You need to turn on Show Invisibles property by choosing Design/Options option from the
menu.
Howis Drawing objects such as circles, rectangles different from other controls such as
CommandButton, StaticText, etc.?
Drawing objects do not have Drag and Drop related events. You can't write scritps for
Drawing objects.
Which of the following controls allow multiple item selections?
ListBox
PictureListBox
DropDownListBox
PictureDropDownListBox
All of of the above
ListBox, PictureListBox

Visually how do you recognise a CommandButton that has its Default property set.

CommandButtons that have Default property set have thick border.

How a Child window is different from a Popup Window?

A child window can't move outside its parent window where as a popup window can.

What is the behavioral difference when you open the Child window
1. Directly
2. From another Window
When a child window is opened from another window, it behaves like a child window and
the window that opened the child window becomes its parent window.
A Child window when opened directly behaves like a main window.
What is the technique you use to display the accelerator key for a SingleLineEdit control?

You can't`display the accelerator key for a SingleLineEdit control, even though you define
one. To display the accelerator key, display the accelerator key to the StaticText control
that is used for labelling the SingleLineEdit Control.
Which of the following statements is correct?
You can specify two menus for a window of type "Main"
A window of type "Response" can't have a menu.
A window of type "MDI" can't have a menu.
Only option 2 is correct.

Window Painter - Exercises


All the windows that you paint as part of this exercise will be used in
applications you develop in future sessions. So, we recommend you NOT to
skip this exercise. You need to paint windows as shown in the picture. The
details of each element in the picture are described below it.

Note: Use the downloaded files for verification only. We strongly suggest you to do all the exercises.

After completion of these exercises, if you have any problem or want to


make sure that your home work is correct, you can download objects by
clicking on the appropriate "Download Code" icon. Please note that, all these
window names are suffixed with "_asi". To open these objects, you need to
import them into your PowerBuilder library. To import the file, invoke the
library painter, select "Entry/Import" from the menu and select the
downloaded file name. Now, the object is ready in your library.

Exported version of
Window Name
Window

Login Window w_login_asi.srw

Error Information Display Window w_error_asi.srw

A Full-featured window(for data-entry,queries, w_product_master_asi.srw


etc)

A window to display your application information w_about_asi.srw

Login Window (w_login)

Picture of w_login window


Window Properties for w_login window:

Property Value

Title: Login Information

Window Color: Window Background

Window Type: Response

Window Name: w_login

Controls left side Top-to-Bottom for w_login window:

Control Type Name Properties

StaticText st_name Text: "Enter your Login &Name:"

StaticText st_password Text: "&Password:"

StaticText st_dbms Text: "Database &Vendor:"

StaticText st_server Text: "&Server Name:"

StaticText st_database Text: "&Database Name:"

CommandButton cb_ok Text: "OK"


Turn on "Default" property
Tab Order: 60
Tag: "Either hit Enter key or click this button to validate
your login."

Controls right side Top-to-Bottom in w_login window:


Control Type Name Properties

SingleLineEdit sle_name Turn-on AutoHScroll


Accelerator: "N"
Limit: 32
Case: Any
Border: Box
Tab Order: 10
Tag: "Enter Login name. Login name is case sensitive.
Check your CapsLock."

SingleLineEdit sle_password Turn-on AutoHScroll


Accelerator: "P"
Limit: 32
Case: Any
Border: Box
Turn-on Password property
Tab Order: 20
Tag: "Enter Password. Password is case sensitive. Check
your CapsLock."

SingleLineEdit sle_dbms Turn-on AutoHScroll


Accelerator: "V"
Case: Any
Border: Box
Tab Order: 30
Tag: "Enter Database vendor name. Enter "ODBC", if you
want to use ODBC driver."

SingleLineEdit sle_server Turn-on AutoHScroll


Accelerator: "S"
Case: Any
Border: Box
Tab Order: 40
Tag: "Enter Server name."

SingleLineEdit sle_database Turn-on AutoHScroll


Accelerator: "D"
Case: Any
Border: Box
Tab Order: 50
Tag: "Enter Database name."

Text: "&Cancel"
Turn on "Cancel" property
CommandButton cb_cancel Tab Order: 70
Tag: "Click or Press Esc key, to cancel Login and to exit the
application."
The bottom most control is a StaticText control. Name it as "st_help". Value
of text is: "Ready". For all StaticText controls, select background color as
"Window Background" color (Marked as "W" on the toolbar icon).

Error Information Display Window  (w_error)

Picture of w_error window

Window Properties
Property Value

Title Error Information

Window Color Window Background

Type Response

The top control is a "DataWindow" control. Name it as "dw_error". Turn on


horizontal and vertical scrollbars.

The bottom four controls are CommandButtons. From left to right,  cb_print,
cb_save_to_log, cb_continue and cb_abort. The text for the
CommandButtons are "&Print", "&Save", "&Continue", "&Abort" in the same
order. Save this window as "w_error".

A Full-featured window (w_product_master)
Picture of w_product_master Window

Window Properties for w_product_master window


Property Value

Title Product Master Maintenance

Window Color Window Background

Type Main

Left most control is a DataWindow control. Name it as "dw_product". Just


below that, there is one more control, which is hidden. That is also a
DataWindow control, just like "dw_product". Name it as "dw_query". All
controls that are on the right side are CommandButtons. The names of these
CommandButtons from top are: cb_query, cb_retrieve, cb_add, cb_delete,
cb_save, cb_export, cb_sort, cb_filter, cb_print_preview, cb_printer_setup,
cb_print and cb_close. The text values are on the picture. Save this window
as "w_product_master".

A window to display your application information  (w_about)


Picture of w_about window

Window Properties for w_about window


Property Value

Title: (Disable Titlebar)

Window Color: Window Background

Window Type: Response

Left Top control is a "Picture". Assign your company logo's bitmap. Name it
as "p_logo". The next two controls are StaticText controls. Provide your
company name over there.

The bottom four controls are CommandButtons, cb_copyright_info,


cb_system_info, cb_credits and cb_done. Turn on both "Default" and
"Cancel" properties for cb_done CommandButton. Save this window as
"w_about".

Menu Painter
PowerBuilder offers the ability to add your custom menus to the application.
In this session you will learn about creating menus, while retaining control
over what the user can and can't do. You will be learning various techniques
to create menus, which you will be using in the 'Product Management
System'  and you will also be looking at some of the other options available
in the Menu Painter.

In this session, you will learn:

The various types of menu.


Creating menus.
Specifying accelerator and shortcut keys.
Menu preferences.
Menu design guidelines.

Prerequisites:

PowerBuilder (Desktop edition will do)

Types of menus
You can create three different types of menus in PowerBuilder:

DropDown menus

Cascading menus

Popup menus

DropDown Menus

DropDown menus are displayed when you select an option from a menu bar
which is on the top side of a window. The available options are grouped into
logical collections and the group names are displayed horizontally on the
menu bar. The following picture illustrates a typical DropDown menu.

Selecting a menu option which has … (ellipses) would bring up a response


window for getting more information. For example, selecting the "Printer
Setup" menu option would display Printer Setup dialog box which is a
response window (You cannot do anything in the application unless you close
the response window).

Some of the menu options work in toggle mode, i.e. clicking on a menu
option would turn it and selecting it again would turn it off. An example of it
would be the Print Preview option. When you select it for the first time, the
report is displayed in the preview mode and by selecting it again the report
is displayed in the normal mode. The current state of the toggle menu
options are displayed by a check mark just before the menu option (see in
the picture).
Cascading Menus

A Cascading menu can display more menu options than a DropDown menu.
In simple terms, if a menu option has a sub menu, it is called a  Cascading
Menu. As you must have noticed, in the window painter all aligning options
are available under the Align menu option which is under the Edit option.
You can identify a cascading menu when you see a right arrow icon next to
the menu option. Clearly, Cascading menus are usually used in conjunction
with the DropDown type menus.

Popup Menus

A Popup menu is displayed in response to a specific event. Unlike DropDown


menus a Popup menu is not displayed at a fixed place, but it pops up at the
current mouse position. Clicking with the right mouse button invokes
the popup menu. Programmatically, you can activate a popup menu for any
event, but the usual way of activating popup menus is with the right mouse
button.
Similar to the DropDown and Cascading menus, Popup menus use the
ellipses, right arrow head and check mark conventions. However, Popup
menus are more versatile than other menus, since they don't have to be
associated with any particular window and can offer different options
depending on the object and the position of the right mouse button.

Creation of a popup menu is no different from other menus, except that you
need to write few lines of extra code to invoke it.

Creating a Menu

Invoke the menu painter from the Painterbar and select New from the Select
Menu dialog box.
Items that are displayed horizontally, such as File, Edit, Window, Help are
calledMenu bar items. Items that belong to menu bar items are
called Menu Items. For example, you may want to display Print, Exit for the
File menu bar item and Cut, Paste for the Edit menu bar item and so on.

You need to type Menu bar items in the Edit


Control that is placed above 'Menu For'
heading. After typing each item, you need to
scroll the scrollbar that is placed after 'Menu
Bar Items' heading, by clicking on the right
arrow. To create a menu with two menu bar
items 'File' and 'Help', first type 'File' and
click the right arrow on the scrollbar and
type 'Help' in the Edit Control.

Now, you might want to display 'File', 'Exit'


under the 'File' menu bar item. To do this,
make the 'File' menu bar item visible with the help of the scrollbar and type
one item per line under the 'Menu For' heading. You see two edit controls
per line under the 'Menu For' heading. Leave the right side edit control
empty ( PowerBuilder doesn't allow you to type there anyway ).
Menu Properties
In this section you will learn about the menu properties that are used while
painting menu.

Menu Item Name Property

As explained in the Window painter, the name of any control is for


programming and not for display purpose. As you type the text for the menu
bar /menu items, PowerBuilder automatically assigns the name. It assigns a
prefix "m_" for each menu bar/menu item name. PowerBuilder automatically
strips out any spaces that you have included in the text and limits the length
of the NAME to 40 characters. There is a 64 characters limitation on the
menu item TEXT.

Locking the Name

As explained above, PowerBuilder automatically assigns the name. Once you


leave a menu item in which you are typing the text and come back later and
change the text, the name is not changed, since it is locked.

To change the name, you need to de-select the Lock Name check box. The
benefit of locking a menu item name is that, any references to it in the
application is still valid even after text change.

Microhelp Property

When using MDI windows, you can specify the help text that is to be
displayed on the status bar by typing in the Microhelp property. Enter text
for each menu item so that it will be displayed when the menu item is
selected.

The advantage of Microhelp over PowerTip is that Microhelp appears on the


status bar no matter how the functionality to which it is attached to is
invoked (by a mouse or a keyboard). The PowerTips are restricted to appear
only when the mouse pointer comes to rest over the appropriate icon.

Options under in the Stylebar tab are advanced at this stage and will be


explained in later sessions. We will explain Shift Over/Down in the "Menu
Inheritance" session and Menu Merge Option & Type Option in
the "OLE"session.

Assigning an Accelerator Key

An accelerator key is the underlined letter in the text of a menu item or a


window object. User can access the menu items or objects using the
keyboard instead of using the mouse by pressing the specified key along
with the Alt key. A well designed application should make use of this feature.
Offering full keyboard compatibility is a must for all professional applications.

An ampersand character (&) is placed in front of the letter to be used as an


accelerator key. For example, the accelerator key for the File menu bar item
is F, so you need to type '&File' for that. If you need to display ampersand
character in the menu bar/item text, provide two ampersands. For example,
to display 'Print in Black & White', you need to type 'Print in Black && White'.

Assigning a Shortcut Key

A shortcut key is a single key or a combination of keys that can be used for
selecting a menu item directly, without having to first open the relevant
menu bar item. If you look at the Exit option on the File menu item, you can
see that Alt+F4 has been added to it as a shortcut key:
Click on the Shortcut tab page. A full list of available shortcut keys
includes all the function keys, letters of the alphabet and the
specializedIns and Del keys. They can be used in conjunction with any
combination of the Alt, Ctrl and Shift keys.

Note that for the highlighted menu item, selected shortcut keys are
displayed in the box next to the menu item text.

Specifying ToolbarIcon Text & PowerTip

When the ShowText option is set to true for the toolbar, PowerBuilder


displays the text for the toolbar icon. You can specify the text to be
displayed by typing in the Text prompt under the Toolbar tab page. The
same text is used for PowerTip also.

Specifying Space Before Toolbar Icon

You can specify the space you want to keep before the toolbar icon in the
toolbar. The space is measured in PowerBuilder Units.

Specifying Toolbar Icon Order

You can specify the order in which the toolbar icons are to be displayed. By
default, PowerBuilder displays icons from top to bottom for each menu bar
item starting from the left.

Other Options
There are two options available for Object Type property. They are Menu and
MenuCascade. The default is the Menu. When this option is set, toolbar icons
display in the regular mode. If you want to define DropDowntoolbars, you
need to set this option to MenuCascade. When set, PowerBuilder allows you
to change Columns and DropDown options.

Assigning an Icon to the Menu Item

Similar to the icons on a Powerbar/Painterbar, you can assign an icon for


each menu option. To assign a toolbar icon, click on the Picture tab page and
you can either:

select from the stock of icons provided by PowerBuilder.

You can find some good icons from one of the example applications also.

If you have Art Gallery installed, you can find hundreds of bitmap files in that directory.

specify a custom icon by clicking on Browse button.

PowerBuilder ships several Stock Pictures and there are also various picture


files which are used in the example applications. If you create your own
icons, you should ensure that they are 16x16 or 32x32 pixels so that they
are displayed properly. PowerBuilder displays the icon you specified in the
above steps, as long as the menu is visible. Sometimes you may want to
display a different toolbar icon whenever the toolbar icon is down (i.e. user
pressed the icon). You can do so by providing a name for the Down Picture
Name prompt.

The selection of the icons can be crucial. A user should be able to identify
the action an icon represents by the picture displayed on it.

Dividing menu items into logical groups

You can divide a menu group into logical sections using separator lines. For
example, under a File menu bar item, you can group all the print options
together, all the Save options together and so on.

To specify a separator line, you simply supply a single hyphen as the menu
item text. PowerBuilder automatically replicates the hyphen to the length of
the longest menu option under that menubar item. PowerBuilder will
automatically give the separator line a name, like any other menu item, with
an identification number. However, if you are trying to paint more than one
separator line in a menu, PowerBuilder prompts you for a menu item name
for the separator line, instead of assigning the name.

Previewing a Menu

Select Design/Preview option from the menu to simulate the run-time


conditions and check if the structure is correct. At previewing time, Power
Builder will not show you Microhelp and PowerTips since menus are being
previewed and not being executed.

Summary
In this session you have learned about menu types, painting a menu and
various menu properties. For a quick summary of the 'Menu Painter'
browsemenu.ppt (a PowerPoint presentation). In the next session you will be
learning about connecting to the database from PowerBuilder.

Menu Guidelines
You have seen the mechanics behind menu creation, let's look at some of
the implications of using custom menus in your application. You should be
aware of these implications because, as opposed to adding functionality you
might be adding holes to your application.

The following list documents some of the important points concerning the
creation of custom menus for your application:

If the currently active sheet doesn't have it's own menu, then the menu and the toolbar
associated with the last active sheet remains in place and operative for the whole time the
sheet is active. If the currently active sheet has a menu but no toolbar, the previous toolbar
would still be displayed.
Menu toolbars only work in MDI frame and MDI sheet type of windows. If you open a non-
MDI window with a menu that has a toolbar, the toolbar won't be shown.
Menu toolbar buttons map directly to menu items, so clicking a menu toolbar button is same
as clicking its corresponding menu item.
Disabling a menu item will disable its toolbar button as well, but won't change the
appearance of the button.
Hiding a menu item doesn't cause DropDown or Cascading menu item toolbar buttons to
disappear. However, it does disable them by graying out of the button.
Hiding an item on a DropDown or Cascading menu doesn't cause its toolbar button to
disappear or to be disabled.
A double toolbar effect can be achieved if you have a menu with a toolbar on both the frame
and the sheet. They can be assigned in any manner.
Enabling and disabling a menu item or menu bar is less overhead to the system
thanHiding/Showing. PowerBuilder destroys the current menu and recreates the original
toolbar excluding the hidden items or menu bar items in case of Hiding/Showing. So
whenever possible, it is better to use  Enable/Disable options.
This method of altering the states of controls at run-time is dealt in depth in PowerScript
session.

Menu item names are unique throughout a menu and if you use the
same text for different menu options you get an error message till
you supply a different menu nameMenu Painter - Questions &
Answers
How is a DropDown Menu different from a Popup Menu?

 DropDown menu needs to be assigned to a window, where as a Popup menu


need not be assigned to a window, moreover you need to invoke the popup
menu from script.
 The nature of a popup menu is dynamic and context sensitive. Mostly the
contents of this menu is static.

What is the difference between an Accelerator key and a Shortcut key?

Accelerator key allows activation of the menu option without using a mouse. The
purpose of the shortcut key is same as an accelerator key. You can activate a menu
item with a shortcut key in a single step, where as an accelerator key needs two steps.
You can define any key as a shortcut key, where as an Accelerator key works only
with the combination of an 'Alt' key.
What is the max. length of a menu item name ?

40

What are the max. no. of characters you can display for a menu item?

64

What are the different types of menus available in PowerBuilder?

DropDown Menu, Cascading Menu and Popup Menu.

How many icons can you assign to a menu item?

Two icons. One for the normal display and another when the icon is down.

What is the default toolbar icon display order?

Starts from the left most menu bar item, from top most menu item to the bottom most
menu item and shifts towards right of each menu bar item.
How many levels of cascading menus can be defined?

There are no limitation on the levels that can be defined. Good applications won't
have more than three levels.
Can you show an ampersand (&) on a PowerBuilder menu item? If so, how?

Yes. You need to use double ampersands to display a single ampersand sign on a
PowerBuilder menu item.
Can multiple menu items display same text?

Yes. By default, when you assign the same text PowerBuilder prompts you about the
duplication and suggests a name to resolve it. You can either accept that name or
assign a different name.
I have got an excellent icon file (.ICO) and want to display it on the PowerBuilder
menu toolbar. What should I do?
Well, you can't assign a .ICO file to a toolbar.You need to either convert it into a
bitmap (.BMP) file or create a brand new bitmap file.

Menu Painter - Exercises

You need to paint three menus as part of the exercise. Again, don't forget
the fact that we will be using these menus in the PowerScript session. Don't
neglect painting these menus.

Upon creating menus, you can download files mentioned under 'Exported
Menu File Name' and import them into your PowerBuilder library in the
Library painter. Then you can compare these menus with your menu objects.
Please note that our menu object names are suffixed with '_asi'.

Menu Name Exported Menu File Name

m_sheet_menu m_sheet_menu_asi.srm

m_mdi_menu m_mdi_menu_asi.srm

m_popup_menu m_popup_menu

m_sheet_menu

Paint menu "m_mdi_menu" as shown in the following pictures. First picture


depicts the menu bar and the second picture depicts each menu bar item in
detail. The third picture is the toolbar you assign to this menu. You can see
the text below each toolbar icon to help you out in selecting a toolbar icon
from the stock pictures while painting the menu.
m_mdi_menu

This menu doesn't need any toolbar. There are only three menubar items.
m_popup_menu

As the name says, we will be using this menu as a popup menu. So, it
doesn't need any toolbar icons and it has only one menubar item.

Database Painter
Up until now, you've been creating objects for the PowerBuilder application.
However, without a source of data, the application would be redundant and
so, in this session, we will be concentrating on this minefield and how it can
dramatically improve the usefulness of a PowerBuilder application.

After this session you will be able to:

Create and maintain database tables, indexes and keys.


Referential Integrity constraints.
Retrieval and manipulation of data from tables.
Export data into different formats from databases.
Understand PowerBuilder's System Tables.

Estimated session time: 180+ minutes

Prerequisites:

You should have PowerBuilder (Desktop/ Professional/ Enterprise version)


installed on your computer.
SQL Anywhere 5.0 or greater installed on your computer.
Database background would help, however not necessary.

  Introduction
PowerBuilder 5.0 ships with SQL Anywhere (formerly Watcom database), a
database engine. All the example applications that are shipped with
PowerBuilder make use of the databases created in SQL Anywhere.
PowerBuilder can talk to different data sources, i.e.

Relational Databases, such as Sybase SQL Server, Oracle, Informix, Microsoft SQL Server,
DB2, SQL Anywhere (Watcom), etc..
Databases such as FoxPro tables.
Other sources such as Text Files, Excel Spreadsheets, etc..

The reason Powersoft ships SQL Anywhere along with PowerBuilder at free of
cost is, SQL Anywhere has a small foot print. Which means that it needs less
resources and works on your desktop. So you can develop applications by
connecting to a database created in SQL Anywhere. Once completed, you
can port it to other data sources with minimal effort.

Invoking Database Painter


To invoke a database painter, click the database icon on the PowerBar.
When you invoke it for the first time, PowerBuilder automatically connects to
the current version of the example database (for version 5.0, it is
psdemodb.db). If the database is not running, PowerBuilder automatically
starts the database engine and connects to it. If you are not invoking the
database painter for the first time, it will connect to the database that you
connected in the last session.

Once the database painter is open, PowerBuilder displays all the tables that
are available in the connected database. The following picture displays the
table and the view names which you see when connected to the example
database. If you would like to see system tables, you need to check
the "Show System Tables" checkbox.
Recall that objects you create in PowerBuilder are stored in PowerBuilder
library. The exception to that are the things you create in the database
painter --such as tables, indexes, views, etc.. They  don't get stored in the
PowerBuilder library, instead they are stored in the connected database.

For the Product Management System application, we need few tables. If


you create tables right away it will create in the example database. Let us
store all the tables you create in a separate database. That means we need
to create a database.

Creating a Database
To create a new database, select "File/Create Database..." from the menu
and provide name 'product'  when prompted.
PowerBuilder automatically supplies the User ID as 'DBA' and Password as
'SQL' (remember, each asterisk takes the place of a letter in
the Passwordfield). Later, we'll see how you can set up users and
permissions for a database, but for now let's enjoy the power of a Database
Administrator.PowerBuilder also generates the necessary information to
start SQL Anywhere database engine by placing it in the Start
command box.

You can click on the More>> button to identify other database specific


options and you can also check the Prompt for Password during Connectbox
at this stage. This option allows you to force the user to type in the
password each time they connect to the database. During development, it is
a good idea to disable this feature, so click on the OK button and we'll move
on.

  Creating 'units' Table


To create a new table, select Object/New/Table from the menu or click on
the   icon. This invokes the Create Table dialog box:
Type the following text for the prompts. We will explain about them later in
the session.

Name Data Type Width Null Decimals


unit Char 1 No <none>
unit_description varchar 10 No <none>

Save the table as "units" by selecting "File/Save" from the menu and close


the dialog box by selecting "File/Close". Once you close the dialog box,
PowerBuilder displays the created table in the database painter's work place
and it looks something like this picture:
 

Column Attributes
Each column in a table has a range of attributes, such as column name,
datatype, width, decimals, etc.. To view/change the schema of the units
table, invoke popup menu on the table heading. The values that you can
supply to each attribute depends on the database to which PowerBuilder is
currently connected to. Remember, the tables/indexes/etc… you create here
are specific to the connected database and would be stored in that.

Name

This is the name that you use to refer to a column and it can contain any
alphanumeric characters, spaces and the underscore character. As explained
earlier, the rules vary depending on the connected database. You need not
worry about using invalid characters, PowerBuilder gives you an error
message if you do it.

It is a good idea to use some form of naming convention for column names.
It helps you to identify them quickly in the script. In our example
application, we've used the underscore character to separate words in the
column names. In some databases, table and column names are case
sensitive. We don't know why PowerBuilder doesn't allow you to type names
in upper case.

Datatypes

This attribute defines the type of data that will be stored in the column. For
a database based upon the SQL Anywhere engine, there are 14+ possible
data types.

These include most of the common types such as char, numeric, date and
time. For explanation to the more obscure data types, you should either
check PowerBuilder on-line help for the SQL Anywhere engine or the
appropriate manuals from other sources. The list of possible data types will
change depending on the type of database you are connected to and the
version of the database.

Width

This defines the width, or the maximum number of characters a column can
contain. It is a good idea to limit the width of each column, so as to limit the
amount of memory assigned to data storage. This use of memory can be
wasteful if large amounts are allocated to store small amounts of data.

For example, if you know that the surname of all your contacts would never
exceed 30 characters then limit the column to this size. Again, all surnames
may not be exactly thirty characters, so it is a good idea to select varchar
instead of char datatype. The difference being that a "Char"datatype always
takes the amount of space allocated to it irrespective of the data inside it.
On the other hand, "varchar" takes only the space that is needed to store
the actual data.

If the column is of numeric datatype, there is a supplemental attribute


called Dec which defines the number of decimal places that should be
allowed.

Null

This is a Yes/No option which is used to determine whether or not a column


should accept a NULL value. A NULL is an empty undefined value which
shouldn't be confused with a zero-length string. The meaning of  NULL is
"unknown value".

Both NULLs and zero-length strings are used to indicate that an entry has
not been made. The distinction between the two entries is based on the
reason for omission. A NULL entry indicates that the information is unknown,
while using a zero-length string shows that the information is not available.
For example, you would use a NULL in a Phone field if you don't know
whether your contact has a phone, but use a zero-length string if your
contact definitely doesn't have one.

Values must be provided for all columns in the "units" table, so all columns
are defined as "NOT NULL".

Extended Attributes
Though the allowed value for each attribute differs from database to
database, all databases support the attributes explained previously.
PowerBuilder supports few more attributes called "Extended Attributes"
which are not part of the standard table definition. PowerBuilder stores all
the extended attributes in PowerBuilder specific system tables in the
connected database.

Going back one step, whenever you connect to a database for the first time,
PowerBuilder creates five tables namely "Pbcatcol", "pbcatedt", "pbcatfmt",
"pbcattbl" and "pbcatvld". PowerBuilder manages and stores all the extended
attributes in these tables.

What are extended attributes? They define:

how data should be displayed.

how to accept data from the user.

what validations are to be done while accepting the data.

the headings and labels for the column, etc…

the display and edit styles of the data stored in the tables.

The following table illustrates the extended attributes with a description of


their usage:

Attribute Description

Format Used to alter the format of the data when it is displayed. An example of a widely used format
style would be the alteration of European date format to the US style of presentation.

Edit Used to specify an edit mask for a column. An edit mask allows you to define a template to
format the data in a pre-defined manner.

Valid This can be used to specify a validation rule for the data; something like, all numbers must be
less than 31.

Justify You can specify left, right or center justified text.

Height Used to specify the height of the box which displays the data.

Width Used to specify the width of the box which displays the data.

Header Specifies a header for the column which is different from the field name. It is used in Tabular
and similar presentation style DataWindows.

Initial You can specify a default value for the column. An example would be to insert today's date if
the user left the field blank.

Label You can specify a label for the column which is different from the column name. It is used in
Freeform and similar presentation style windows.
Comment In this attribute, you can add comments for the column.

PowerBuilder will automatically fill in Header and Label text using the column


name, replacing underscore characters with spaces and capitalizing the first
letter of each word.

Format Styles

Format style specifies how the data should be presented. For example, you
might want to have two different format styles, one in millions format
(comma after every three digits) and another in metric format. Note that
these are specific to PowerBuilder. PowerBuilder stores these values in the
database. Other applications such as Excel, Visual basic, etc. don't have
these format styles. There are two steps in completing the format style
definition.

First you need to define the format style.

Then assign the format style to the column(s).

Select "Design/Display format Maintenance" from the menu. You see pre-


defined format styles. In most of the cases, they would serve the need. To
define a new one, click New button.
Before you start the definition, you need to select a datatype and provide a
name to the format style. Provide the definition in the 'Format' prompt. You
can check the formatting by typing a number into the "Test Value" box and
clicking the "Test" button. PowerBuilder will apply the formatting and display
the result.

The symbols used in the format mask depends on the data type that has
been defined for the field. The symbols you can use for string and number
data types are as follows:

Note that the Format attribute doesn't limit the number of characters in the
field - we've already done this by specifying the width of the field in the
table definition.

Numeric String Data


Symbol Meaning
Data Type Type
Numeric character - this symbol rounds off trailing
# X
integers automatically.

$,£,%,-,.,/ X X Displays the appropriate punctuation character.

@ X X Any character.

'....' X X Used to display characters between the quotes.

(....) X Used to specify a different format for negative numbers.

Used to separate formats, such as for positive and


; X
negative numbers.

[GENERAL] X Lets PowerBuilder choose a suitable format.

[CURRENCY] X Lets PowerBuilder choose a suitable format based on the


current Windows International settings.

Used before the format mask to display in the specified


[BLUE] X X
color.

An example to achieve the effects of   formatting symbols would be:

$#,###.##;[RED]($#,###.##)

This formatting will display a positive numeric input with a dollar sign,
thousand separators and two decimal places in the default font color. Any
negative inputs use the same formatting except that the font color is red.

For more explanation and examples look in PowerBuilder's on-line help.

Date and Time Formats

For date and time data types, there are an extra set of formats that can be
used to display the data. The following table lists these extra formats:

Date Time
Symbol Meaning
Type Type

d X Day as a number.

DropDownDataWindow X Day as a number with leading zero.

ddd X Day name abbreviation.

dddd X Full day name.

m X Month as a number.

mm X Month as a number with a leading zero.

mmm X Month name abbreviation.

mmmm X Full month name.

yy X Two digit year.

yyyy X Four digit year.


h X Hour.

hh X Hour with leading zero.

m X Minutes.

mm X Minutes with leading zero.

s X Seconds.

ss X Seconds with leading zero.

ffffff X Microseconds.

AM/PM X Displays AM or PM as applicable.

am/pm X Displays am or pm as applicable.

A/P X Displays A or P as applicable.

a/p X Displays a or p as applicable.

Again, check PowerBuilder's on-line help for more information.

Edit Styles
An edit style is used to limit the type of data that can be entered into a
field, while affecting how the data is entered. For example, you can limit a
date field to the month/day/year format .
PowerBuilder comes with a lot of pre-defined edit styles. You can also define
new edit styles. You can define six different edit styles, such as:

DropDownListBox
DropDownDataWindow
CheckBox
Radiobutton
EditMask
Edit

All these edit styles behave similar to the corresponding window controls.
You find the attributes in the above picture available in the window painter
also. Define an edit-style as shown in the picture, since we would be needing
it.

We won't be going into detail about properties of different edit-styles, they


are explained in the Window painter session. One style which was not
covered in the Window painter is "DropDownDataWindow" edit-style. We will
explain about it once we complete the DataWindow painter session.

Validation Rules
A validation rule defines what data is allowed in a column. Some of the
RDBMSes such as Sybase support validation rules in the server.

When a validation rule is defined in the server, irrespective of the client that
is trying to manipulate the data, server validates the data by applying the
validation rules. For example, let table "transactions" have
"transaction_type" column and you define a validation rule on the
"transaction_type" saying that the valid values are 'receipt', 'issue' and  
'return'. Now, you want to enter/change the data via Excel, Visual Basic, a C
program, etc.. Unless you provide a valid data, server will not allow you to  
change/enter data in the table. This is called 'server side' validation.

In PowerBuilder, you can define validation rules on the client side. It means
that when you provide the data, the client (PowerBuilder) validates the data
and sends the valid data to the database.

Difference between the client side validation and the server side validation is
that the validation rules defined in a client program is used only by the client
that defines it. In the above example, say you define a validation rule in
PowerBuilder and a Visual Basic client wants to change the data in the
server. Sybase will not validate the data, since the validation rule is not
defined in the server.

Then which is the right place to define the validation rules. It depends. In
the client/server environment the best thing would be to define at both the
places. Defining at the client will reduce a lot of network traffic. That is
because the client sends valid data, instead of sending it every time and
getting validation errors. Defining at the server would also be useful,
because, if you want to add a new client type, say Java, you don't have to
worry about wrong data.
To define a rule select "Design/Validation Rule Maintenance" from the menu.
Select New from the dialog box. Let us define a rule that the product number
should be greater than zero. Provide the name as shown in the picture and
select "Number" from "Type" DropDownListBox. You need to provide
definition for the 'Rule Definition' prompt. The keyword "@Col" contains the
value provided by the user. You can use functions available under
the "Functions" dialog box.

The @col stands for the value the user types in, so the rule states that the
length of the entry must be greater than 0. If the validation rule is broken, it
is useful to display an error message to guide the user towards the type of
input that is expected. This message is fully customizable, so try to make it
as informative and useful as possible.

The Match Option

Another facility that PowerBuilder provides for string data types is Match.
Using this option you can specify a range of specific values for a particular
position in the string. To see how it works, click on the "Match..." button.
The ^ (hat) symbol represents the beginning of the pattern, the dollar sign
($) represents the end of the pattern and you can specify the exact values
or range of values for any of the characters in between. We can use this
feature to refine our previous validation rule.

For example, the ISBN that corresponds to a Press book is 1874916 followed
by three digits, even though in certain circumstances the last one could be
an 'X'. The validation rule to test the ISBNs would be as follows:

^1874916+[0-9]+[0-9]+[0-9X]$

We can test the rule by typing a value into the "Test Value" box and clicking
on the 'Test' button. You can see that the ISBN 187491632X is a valid input.
If the input isn't valid, the test will detect it:

Click the OK button. Now the validation rule is defined. Once you define the
validation rule, you need to assign the rule to the columns for which it
applies. For example, you define a rule 'v_valid_product' that says 'value
should be greater than zero' and want to assign the rule to 'product_no' in
'product_master' table, then you need to click with the right mouse button
on the "product_no" in the "product_master" table and select 'Validation' tab
page and select the above defined validation rule. You can't do the same
right away since you haven't defined the table yet. Do it after completing the
exercises given at the end of the session.
Similarly you can assign edit and display format styles also.

Defining Primary Keys


A Primary Key is used to uniquely identify each row in a table. When you
apply a primary key to a column in a table, you are forcing each entry in
that column to be unique - the database engine will reject those entries
which will duplicate any existing entries in this column. Keys are important
because they are used to join tables in a database.

It is not mandatory to define a primary key for every table, but if you don't,
you won't be allowed to enter data into the table from the data manipulation
screen in the Database Painter.
To define a primary key, click with the right mouse button on the title bar of
the units table to bring up the table properties dialog box and click on
the "Primary" tab page.

Click on the unit column to add it to the Key Columns box. To define a


primary key with multiple columns, simply click on all those columns from
the column list.

Once you create the primary key, PowerBuilder displays the primary key with an icon 
( shown beside the heading of this section ). If you would like to browse about the
primary key, click on the icon.

Defining Foreign Keys


A Foreign Key defines the relationship between two tables. We just defined
a primary key "unit" for the "units" table. For now assume that we have
another table "product_master" which has "measuring_unit" column. Here
every product should be measured in a unit specified in the
"measuring_unit" column. For example, petrol in gallons, wheat in lbs. and
so on. "units" table has all the valid measuring units. To define a measuring
unit in the "product_master" table, it should exist in the "units" table. That
means that there is a relationship between "product_master" and "units"
table.

To define a foreign key, click with the right mouse button on the table title
and select "New/Foreign key". You see a dialog box similar to the one shown
below. Provide a name in the "Foreign Key Name" prompt. Select the table
name that has the primary key, i.e., units table. PowerBuilder automatically
displays the primary key from that table in the "Primary Key
Columns"prompt. Select "product_measuring_unit" column from the
"product_master" table.

The radio buttons allow you to specify the effect of deletion of a row in the
Primary Table. There are three options:

Option Description
Restrict If there are dependent rows in the "product_master" table, database doesn't allow you to
delete a row in the "units" table.
Cascade If a row is deleted in the "units" table, dependent rows in the "product_master" table are
deleted.
Set Null If a row is deleted in the "units" table, then a NULL value will be placed in the
"product_measurement_unit" column of any dependent rows in the "product_master"
table.
Once you create a foreign key, PowerBuilder display the foreign key with an icon
( shown at the heading of this section ). If you would like to browse about foreign key,
click on the icon.

Creating Indexes
Indexes are used to speed up data selection from a table by restricting the
number of rows that have to be searched. For example, if you had a table of
contacts with a gender field and assuming you had equal number of male
and female contacts, then indexing this field would half the number of
records that need to be searched by a query.

You've declared the "unit" column as a primary key to uniquely identify rows
in the "units" table, so this is a logical choice for an index. Click with the
right mouse button on the title bar of the "units" table and
selectNew/index option.

Name the index as xunits and click on the "unit" column. You can specify if
the indexed column must contain unique or duplicate values and you can
also have the option of indexing in ascending or descending order. We want
a unique and ascending index, so accept the defaults and click on
theOK button to add the index to the table. Please note that, most of the
relational databases don't accept the ascending/descending options.

Once you create the index, PowerBuilder displays the index with the
index icon ( shown at the heading of this section ). If you would like
to browse about index, click on the icon.

Data Manipulation
To view the data that is stored in a table or to even alter/manipulate it, click
on the table title with the right-mouse button and select "Edit Data"option on
the "Preview" icon from the PainterBar. When viewing data, PowerBuilder
uses the default presentation style, but you can use different style by
selecting "Objects/Edit Data" from the menu and selecting the appropriate
presentation style from the cascading menu.

Once you are in the 'Data Manipulation' window, you can insert new data or
change/delete existing data from the table.

Any data that is added/changed are held at the client site, that is in your
computer's memory. To reflect the changes in the back-end database, you
need to select "File/Save Changes to the database" from the menu.

Go to Data Manipulation window of the "units" table, click on the "Insert


Row"  icon and type the following data.

Pressing the TAB key when the cursor is in the "description" column will append a new row.

U unit

lb pound

in inch

gl gallon
Save the changes to the database by selecting "File/Save Changes to the
database" from the menu.

Note that PowerBuilder allows you to manipulation data in the data


manipulation window only when the table has a unique index. When no
unique index is present the table can be manipulated by SQL statements in
the Database Administration window.

Importing Data

At the moment PowerBuilder supports importing data from two file formats,
namely tab delimited text and the. DBF format. However, it is likely that in
future releases more file formats will be supported.

To import data, go into the Data Manipulation window and


select"Rows/Import.." from the menu.

For each row you import, PowerBuilder creates an INSERT statement and
when you click on the Save Changes icon, it sends it to the database. This is
a logged operation, so if you are importing large amounts of data, first
consider the memory on your local machine and the log space that would be
required for the database. If you are connected to SQL Server, you should
consider using a Bulk-Copy Program (BCP).

When the changes are saved , data will be written to the database. If the
table has an unique index and duplicate data is imported , PowerBuilder
doesn't display error at the time of importing. However, the connected
database will generate error while saving the changes back the database.

Exporting Data

We've seen how to import data from a tab delimited text file. It may occur to
you that it would be useful to export data to some other format. To allow
this PowerBuilder provides you with tools to support several popular file
formats.

To see how it works, select "File/Save Rows As..."  in the Data Manipulation


window of the "units" table.
As you can see, PowerBuilder provides you with a wide choice of file formats.
For example lets choose Excel with the Include Headers option selected ( so
as to know what the data refers to ) and then give the file a name,
say UNITS.XLS and click the OK button.

Now Alt+Tab out of PowerBuilder and open it up the spreadsheet:

You can see that we've the information from the units table in a standard
Excel spreadsheet.

The .XLS file format which PowerBuilder creates isn't the latest version, in


fact it is a Excel 2.1 worksheet. Fortunately, Microsoft operates a backwards
compatibility program, so Excel 5.0 will read the file. However any attempt
to save changes to the 2.1 version format will prompt you that it isn't the
latest version and asks if you want to update it.

The exporting feature can be very useful. We copied the table definition of 
"product_master" table into our example database, in the same way you
could export the actual data from a table into SQL Syntax or a text file and
then import it into another table.
Sorting Data

From the Data Manipulation window, PowerBuilder can be forced to sort the
displayed data in alphabetical or numerical order. Select"Rows/Sort..."  in
the "units" table.

Drag the "unit_description" column from "Source Data" column


into"Columns" column and click the OK button. The data will now be
displayed in alphabetical order:

We can also alter the sorting expression so that the data is displayed in
numerical order of length.
Filtering Data

Along with sorting the displayed data can be filtered. To perform this
select "Rows/Filter..."

An expression can be built using any of the available functions from the list,
fields in the table and a selection of mathematical operators. For example to
display the rows with a description of six characters or less, we would use
the following expression:

Only those rows that pass the filter criteria are displayed. It doesn't mean
that the rest of the data is gone, it is still available on the local machine and
there are no changes made to the back-end database. Remove the filter and
all the data will be displayed.

Most of the available functions are used with a particular type of data, so
you need to verify your expression for validity. Do this by clicking on
the"Verify" button.

Displaying Rows Description

While sorting, filtering, deleting and modifying data in the Data Manipulation
window, you may find it useful to see the summary of the things done to the
rows. You can see it by selecting "Rows/Described..."
Zooming

After you have sorted and filtered data, you may want to change the size of
the display on screen. To do this select "Design/Zoom..."

You can select from one of the pre-defined magnifications or type in a


custom value. When you click the OK button, the display will change to the
specified size.

Printing the Data

You can print or preview the current display using the standard "File" menu
options of "Print..." and "Print Preview". In Print Preview mode, you can turn
on the "Print Preview Rulers" to let you adjust the margins and using
the "Print Preview Zoom..." feature you can alter the magnification.
Both these options are selected from the "File" menu. Note that any
magnification changes that are made in the "Print Preview" mode are
discarded when the "Print Preview" is turned off and the display returns to
the size before the "Print Preview".

Getting the System Tables Back in Sync


In most cases, you won't be using PowerBuilder to create and alter table
definitions. In fact DBAs (Database Administrators) use other tools which are
specifically designed for database management. You will probably use
PowerBuilder as a front-end tool to display data from an existing database.
In such situations extended attributes that are offered by PowerBuilder are
not used at all ( unless you open the database and define extended
attributes ).

On the other hand, it is possible to create tables using PowerBuilder and


then alter them outside the PowerBuilder environment. For example, you
could alter the definition of PowerBuilder produced tables using SQL Central
tool. Whenever the tables are modified outside the PowerBuilder
environment, PowerBuilder's extended attributes become out-of-date.

In order to rectify this, PowerBuilder provides you with an option to


synchronize the attributes from the "Design" menu.
If there aren't any differences between the attribute definitions,
PowerBuilder displays a message telling you that synchronization isn't
required.

Using Logs
If you are curious to see the SQL (Structured Query Language, pronounced
as 'sequel') statements that are used to create a table you would be
interested in the logs. All DBAs save the schema to an ASCII file for future
use. To see the statements that created the "units" table, select the table
"units" and select "Object/Export Syntax To Log...". When the dialog box
asks you to specify the data source, click OK. An Activity Log icon appears at
the bottom of your screen.

If you double-click on the icon, it will bring up the SQL syntax which was
used to create the table.
Scroll down the screen to see the full syntax and appreciate the simpleness
in creating a table using the Database Painter rather than using a character
based SQL utilities such as ISQL.

You might wonder why you'd want to look at these SQL statements. If you're
not familiar with SQL, it is a good method of learning the language,
moreover there is a practical reason - it allows us to copy tables from one
database to another.

PowerBuilder doesn't provide you with the ability to 'cut and paste' tables
from one database to another. You must either manually reproduce the
tables or use the logs to recreate them automatically .

Select "Options/Save Log As..." and call it UNITS.SQL. Sometimes, you


may want to log all of your activities in the database. In that case, you can
select "Design/Start/Stop Log". If the log is not started, selecting this menu
option starts the log and vice versa.

PowerBuilder Attributes and System Tables


The following table lists all the PowerBuilder system tables that store the
PowerBuilder extended attributes information.

Table Description
Name
PBCATTBL Contains the font information for the text, labels,headers and so
on.
PBCATCOL Contains details of the extended attributes for each column in
each table in the database.
PBCATFMT Contains definitions of the available formats.
PBCATVLD Contains definitions of the validation rules.
PBCATEDT Contains definitions of the edit styles.

The following picture illustrates the PowerBuilder system table columns and
primary keys.
Database Administration Painter
Remember you sorted and filtered data in the data manipulation window.
There both sorting and filtering was done by PowerBuilder and not by the
connected database. You can restrict and sort the results from the connected
database by using WHERE and ORDER BY clauses in the SELECT statement.
In data manipulation window and database painter custom built SELECT
statements cannot be executed. It is possible only in the database
administration painter.

The commands that can be executed in the database painter are limited to
the boundaries of the painter i.e. table/view definitions and so on. Complex
SQL statements can be run in the connected database.
Executing SQL Statement

Invoke database administration painter either by


selecting"Design/Database Administration" or by clicking   icon. Let us
write a query and execute it. Type the following SQL statement:

select * from units where unit = 'U' ;

In this painter you need to terminate SQL statements with a semicolon.

Please notice the single quotations around 'U' in the query. For some
databases such as Sybase SQL Server/MS SQL Server, it doesn't matter
which quotations you use. But, for Watcom SQL/SQL Anywhere, you
have to use single quotations. Double quotations are for columns or
tables/view names. In MS SQL Server, from version 6.0 onwards use
appropriate quotations i.e. use double quotations so that SQL Server
interprets the special characters before it runs the query. If you don't
want SQL Server to interpret the special characters within the quotations
use single quotations.

To execute the SQL Statements select "Design/Execute SQL" from the menu


or click on   icon.

Query Plan

To optimize a query one would like to know details such as how much I/O it
needs or which indexes it uses and so on. For that select"Design/Explain
SQL" from the menu.

Even though the query plan is seen in PowerBuilder, it is returned by the


connected database. The output for the query plan varies from database to
database.
A single SQL statement can span on multiple lines. When the SQL Statement
is written on multiple lines only the last line needs to be terminated with a
semicolon.

Commenting Code

To comment a line place '//' without quotations at the beginning of the line,


that means anything after that in the line is considered a comment.
Sometimes, you might want to comment multiple lines. In that case,
place'/*' at the beginning of comments without quotations and end the
comments with '*/' without quotations.

Painting the SQL Statement

Sometimes, you might have big tables with long column names. We can't
remember each and every column and table/view name. PowerBuilder allows
you to paste SQL Statements in the database administration painter. For
example let us paste the SELECT statement we wrote above by
selecting "Edit/Past SQL" from the menu.

Double clicking on the "Select" icon prompts for the table selection. Select


"units" table and click the "Open" button. We want to select all columns from
the table. So, click on the table title with the right mouse button and
select "Select All" option.
Now, we need to paint the WHERE clause. Clicking on the row just below
the Where tab page will list all the columns in the table in a
DropDownListBox. Select "unit" column.

The next option "Operator" lists all the allowed operators in the connected
database. It defaults to '='. That's fine for this query.

Type 'U' under the value heading. Before you paste this SQL, you may want
to see it. Click on the "Syntax" tab page to list the SQL Syntax created as a
result of painting.

To paste the generated SQL in the database administration window, click


on  icon. PowerBuilder automatically appends the terminator character ';'
(semicolon) to the SQL statement.
Viewing/Pasting Stored Procedure Syntax

At times you may like to view/paste the source of a stored procedure. You
can do so by selecting "Design/Procedure Syntax". Select the procedure
name by clicking on the stored procedure name. The source is displayed in
the Syntax box. To read the source click on the Cancel button ( after reading
the syntax ). To paste the syntax click on the OK button.

Maintaining Users/Groups

If you are the Database administrator (depends on the connected vendor of


database)  you can add/remove users from the database by
selecting"Design/Maintain Users" from the menu. Unless the user name is
defined in the database, the user is not allowed to login into the database.
Once the users are added it might be logical to put them into different
groups. You can do so by selecting "Design/Maintain Groups" from the
menu. The procedure of maintaining users and groups vary from database to
database.
Maintaining Table Security

A table owner or a database administrator can grant/revoke privileges to


other users by selecting "Design/Table Security" from the menu.

Database Profiles
Remember the first thing we did in the session "creating a database". From
there on everything that was created is stored in the "product" database.
When creating a database there are few things that happen behind the
scenes.

PowerBuilder first creates the database.


Creates a database profile.
Connects to the database using the database profile.

What is a database profile? A database profile is nothing but an ASCII file. It


consists of details that are required to connect to a database, such as login
name, password, the driver that is used to connect to a database and so on.
When you close the database painter, PowerBuilder stores the database
profile name that is used to connect to the current database. When you
invoke database painter for the next time, PowerBuilder reads the database
profile name and connects to the database specified in the database profile
using the parameters specified in the database profile file.

All profile file names have ".ini" extension. When you install PowerBuilder, it
installs few ".ini" files such as pb.ini, pbodb050.ini, etc.. Each profile file is
logically divided into sections.

Every database profile is stored in the PB.INI file, located in the


PowerBuilder directory. The general database related information is stored in
a section called[Database]. The [DBMS_PROFILES] section
of PB.INI contains a list of the current database profiles, currently available
profiles and a history of profiles which have been used.

Each section name is enclosed in a square bracket. All the variables and
values related to a section are listed under that section. Under a section,
each line consists of a variable name and its value separated by a '='.
Following is a listing of two sections from pb.ini file.

[Database]
DBMS=ODBC
Database=product
UserId=dba
DatabasePassword=
LogPassword=
ServerName=
LogId=
Lock=
DbParm=Connectstring='DSN=product'
Prompt=0
Vendors=ODBC,SYB SQL Server v4.x,SYC Sybase System 10 CTLIB,IN5 I-Net v5.x,MSS (Msoft)
SQL Server 6.0,O71 ORACLE v7.1
AutoCommit=0
AutoQuote=1
Columns=8
ForeignKeyLineColor=0 0 255
IndexKeyLineColor=255 0 0
PrimaryKeyLineColor=0 128 0
NoCatalog=No
ReadOnly=0
ShowIndexKeys=1
ShowReflnt=1
StayConnected=1
TableDir=1
TableListCache=1800
TableSpace=*
TerminatorCharacter=;
HideComments=0
ShowRefInt=1
pipeline_default_source=4
StripComments=0
LEXICON=

[DBMS_PROFILES]
CURRENT=Product
PROFILES='Product','Powersoft Demo DB V5','ABNC Main DB V5','ABNC Sales DB V5'
History='Product','Powersoft Demo DB V5','ABNC Main DB V5','ABNC Sales DB V5'

[PROFILE Product]
DBMS=ODBC
Database=
UserId=
DatabasePassword=
LogPassword=
ServerName=
LogId=
Lock=
DbParm=Connectstring='DSN=product'
Prompt=0
AutoCommit=0

Let's see how to setup these database profiles.


Select "File/Connect/Setup" and select "Product" and click on "Edit" button.
Section Description
Profile It is the name given to a profile and is used whenever you want to connect to the
Name database. PowerBuilder creates a section with this name in the pb.ini file.
DBMS The name of the database system, it could be Sybase, Oracle, Access etc. If you want
to use an ODBC driver, just type ODBC. Actually it tells PowerBuilder about the
specific driver that is used to connect to the database. You have an option of using the
Native driver or ODBC. When you type the a DBMS name other than ODBC it means
that you want to use the native driver.
User ID This is an ID used to identify the user.
Password A security password.
Database The name of the file in which the database is held in. For example, our database is
Name held in a file calledproduct.db.

The entries in the "CONNECT OPTIONS" are optional depending on the type


of DBMS you are connecting to. For example, if you are connecting to a SQL
Server you need to supply "Server Name", "Login ID" and "Login Password"
as opposed to the User ID and Password.
The last prompt in the dialog box is "DBPARM", which is used to specify any
database specific parameters. For example you can specify a "TimeOut" for
the client or a "Locks" isolation level when connecting to SQL Server. In our
"Product" profile, the "DBPARM" section simply contains a connection string
specifying the name of the database. This is automatically filled when we
create a profile, so don't worry about it.

Any additional entries that you can add to the DBPARM are in the realms
of SQL Server rather than PowerBuilder. Please refer to the SQL Server
or to other back-end database server manuals for more information.

You don't have to create separate profiles for every database that you want
to connect to. If you check the "Prompt for Database information during
connect"option on the profile setup screen, you'll be prompted to select the
name of the database you intend to connect whenever you connect using
that profile,.

Remember, for the DBMS prompt we specified ODBC. How PowerBuilder


knows which ODBC driver to use. Let us learn more about ODBC in the next
section.

Database Profiles in v6.0


The improved and redesigned database profile dialog box in version 6.0
displays existing database profiles using a treeview control sorted by
database interface.
This dialog box prompts you for database specific parameters which wasn't
available till version 6.0. Another good thing about this dialog box is, all the
parameters are categorized. That means, you don't have to remember 10s
of parameters for each database, instead you can fill-it-in. Once you provide
all the details, you can also preview and copy the SQLCA syntax from the
'Preview' tab page, that means, you don't have to type in all the code.

If the ODBC configuration file is not existing for a specific database, you can
configure ODBC right from this dialog box.
Infact, they can remove 'File/Configure ODBC...' menu option in the
database painter, since that option is already available in this dialog box.

ODBC
Microsoft's Open Database Connectivity standard defines a standard SQL
grammar and two sets of function calls based on the SAG CLI specification.
They are named core grammar and core functions respectively. It allows you
to connect to a vast array of database systems.

ODBC Architecture

In general the realm of ODBC can be split into four major components:

Application.

Driver Manager.

Driver.

Data Source.
Each of these components fit together to make a bridge between the two
resources that are needed to exchange data:

Let's look at each of the components in detail.

Application

This is the program that is used to access data from the back-end database,
typically running on the MS-Windows Operating system ( and the back-end
database can be located anywhere ). When looking at an ODBC setup a
PowerBuilder application which accesses data from Sybase SQL Server can
be considered as the application. Any ODBC functions that you need to call
are made from the application.

Driver Manager

This is a DLL which controls loading of the necessary drivers to connect to


the required database system. When an ODBC call is made from an
application, the Driver Manager scans the necessary .INI files to determine
which driver to use and where it is located.
Driver

The driver is the heart of ODBC. It takes care of network protocols that are
required to connect to the data source. It also   translates and submits the
SQL statements to the data source.

Note that there are currently three standards for SQL: ANSI '86, ANSI '89 and ANSI '92. This has
lead to the proliferation of 'flavors' of SQL and prompted the need for this ODBC translation
layer. It is therefore at times necessary for the ODBC driver to translate between these
standards for effective communication between the application and the database.

Generally, the back-end database system processes the SQL statements


passed to it by the driver, but in the case of text files and some DBMS which
don't support SQL, the driver takes care of processing the SQL statements
and sends the results back to the application.
Data Source

This is an ASCII file which contains the DBMS name and other necessary
details such as Login Name, Password, the location of the database to
connect to and as well as any DBMS specific parameters. In the case of
Sybase SQL Server, you may be specifying the Server Name, Database
Name, Server Login ID, Password and other DBMS specific information such
as application name to display in the server's connection list and so on.

ODBC takes care of finding the SQL Server address on the network and
connecting to the SQL Server by looking into the win.ini file or windows
95/NT registry or sql.ini file.

As an application developer, you only deal with two components: function


calls from the application and the data source details. When using
PowerBuilder, the data source details are in the database profiles ( into
which you've already looked ).

The interesting feature of ODBC is that you can connect to more than one
data source from the application at the same time by simply using another
profile.
The ODBCINST.INI File

When you first install PowerBuilder, you are prompted to select the ODBC
drivers that need to be installed. The selected drivers are installed in
theWINDOWS/SYSTEM directory and the ODBCINST.INI file, which
contains the list of installed drivers gets updated. The [ODBC Drivers]section
of this file contains a list of the installed drivers.

[ODBC 32 bit Drivers]


[ODBC Drivers]
Sybase SQL Anywhere 5.0=Installed

Each installed driver has a section in the ODBCINST.INI, which contains


the full path name for the required driver:

[Sybase SQL Anywhere 5.0]


Setup=c:\SQLANY50\win32\WOD50T.DLL
Driver=c:\SQLANY50\win32\WOD50T.DLL

PowerBuilder uses this information to set the driver options when you
configure ODBC.

The ODBC.INI File

There is another .INI file which we should look at - the ODBC.INI file. This


is present in the WINDOWS/SYSTEM directory and contains full connection
information for all databases. The [ODBC Data Sources] section specifies the
DBMS to use for your databases, defined by either the manufacturer of the
ODBC driver or by your profiles.

[ODBC 32 bit Data Sources]


product=Sybase SQL Anywhere 5.0 (32 bit)

[ODBC Data Sources]


Peat=Sybase SQL Anywhere 5.0
powrpim5=Sybase SQL Anywhere 5.0
qnote=Sybase SQL Anywhere 5.0
stuff=Sybase SQL Anywhere 5.0
dwfast=Sybase SQL Anywhere 5.0
rio=Sybase SQL Anywhere 5.0
ppo=Sybase SQL Anywhere 5.0
inbound=Sybase SQL Anywhere 5.0
document=Sybase SQL Anywhere 5.0
contact=Sybase SQL Anywhere 5.0
codesnip=Sybase SQL Anywhere 5.0
apptrack=Sybase SQL Anywhere 5.0
cashtrak=Sybase SQL Anywhere 5.0
PFC=Sybase SQL Anywhere 5.0
ABNC Sales DB V5=Sybase SQL Anywhere 5.0
ABNC Main DB V5=Sybase SQL Anywhere 5.0
Xref=Sybase SQL Anywhere 5.0
Powersoft Demo DB V5=Sybase SQL Anywhere 5.0

For each of these definitions ODBC.INI has a separate section which


contains the complete connection information for that database. For example
the [Powersoft Demo DB], [product] sections look like this:

[Powersoft Demo DB V5]


Start=c:\SQLANY50\win32\dbeng50.exe -d -c512
Driver=c:\SQLANY50\win32\WOD50T.DLL
PWD=sql
UID=dba
DatabaseName=PSDEMODB
DatabaseFile=c:\PowerBuilder\Powersoft\PowerBuilder 5.0\Examples\Code Examples\
PSDEMODB.DATABASE

[product]
Driver32=c:\PowerBuilder\pb5i32dk\WOD50T.DLL

This section has the DLL name along with the path. When you specify ODBC
as the DBMS in the profile, the ODBC Driver Manager scans this file for the
profile name and loads the appropriate driver.

This is probably the most important .INI file. It contains the full information


( including passwords) about all your database connections. Considering this
it is important that this file is protected on your system and not freely
accessible.

A word of caution, it is important that you never try to manually alter any of the entries in
any of the .INI files, doing could have a serious effect on your ability to connect to your
databases.

Configuring ODBC Profiles

In this section, let us see what PowerBuilder demo DB has.


Select"File/Configure ODBC..."
It lists all the installed drivers and allows you to select or create data
sources for any of the available data source drivers. The list of drivers on
your system may differ depending on the software on your system and the
options that were selected when installing PowerBuilder.

Select Sybase SQL Anywhere 5.0 and select "Powersoft Demo Database


V5" and click "Edit" button.
The quickest way to fill all the details is by clicking on the "Browse..."button
and specifying the Database filename.

PowerBuilder will automatically fill in the "Data Source


Name" and"Database Alias" using the name of the database. You should also
select the "Local" radio button as the database is on your local drive. Type
in "User ID" as 'DBA' and "Password" as 'SQL'.

Its not necessary that you fill in User ID and Password options, but if you don't then every time
you connect to this database you will be prompted for your User ID and Password. When you
distribute an application, the database profile an application uses is very important for purpose
of security - you only want users with password to get access to the database!
Click the Cancel button and exit from the database painter.

Summary

In this session you have learned about connecting to the database from PowerBuilder, creating
databases, tables, indexes and PowerBuilder extended attributes. You also learned executing SQL
statement directly in the administration painter. For a complete summary of this session, browse
'database-painter.ppt' PowerPoint presentation.
Database Painter Exercises
You need to create the following objects. The left most column in the
following table lists the object that you need to create and also has the link
to the deatil list of those objects. The second column lists the files that have
SQL statements to create those objects. You can use these files in two
different ways. One, you can execute them in the database administration
painter and objects will be created for you. We don't recommend this way.
Instead we would like you to create those objects and export those object
definitions and compare with the SQL that is listed in the files(second
column). The thid column lists the files that inserts sample data into those
tables. The data is also displayed in the picture for each table.

Tables:
Table Name SQL to create table, index SQL to create Data
units units.sql units-data.sql
product_master product_master.sql product_master-data.sql
trans trans.sql trans-data.sql
product_images product_images.sql None
Edit Styles
e_tran_type
Validation Rules
v_no_empty_column
v_no_zero_column
"units" Table

Create the 'units' table as shown in the following picture and enter the data
as shown.

Create dialog box for the table Data

Property Value
Primary key unit
Index Name xunits
Index Columns unit. Ascending, Unique
"product_master" Table

Create 'product_master' table as shown in the picture and enter the data as
shown.

Property Value
Primary key product_no
Index Name xproduct_master
Index Columns product_no. Ascending, Unique.
Foreign Key Name: fmeasurement_unit
Foreign Key product_measurement_unit referring to unit in the units table

Data

"trans" Table

Create 'trans' table as shown in the picture and enter the data as shown.

Property Value
Primary key tran_no, tran_serial_no
Index Name xtrans
Index Columns tran_no, tran_serial_no. Ascending, Unique.
Index Name xtrans2
Index Columns tran_date. Ascending, Duplicate.
Foreign Key Name: ftran_item_no
Foreign Key tran_item_no referring to product_no in product_master table

Data

'product_images' Table

Create 'product_images' table as shown in the picture. This table doesn't


have any sample data. The reason is that, you need to follow special
procedure to insert images into the table, which is not explained and is too
advanced at this stage. We will explain this in the OLE session.

Property Value
Primary key product_no
Index Name xu_product_images
Index Columns product_no. Ascending, Unique.
Foreign Key Name: fproduct_no_images
Foreign Key product_no referring to product_no in product_master table

Once you define all the above tables, it should look like in the following
picture:

"e_tran_type" Edit Style

After defining, assign it to "tran_type" column in "trans" table.


"v_no_empty_column" Validation Rule

After defining, assign this rule to "product_description" in "product_master"


and "unit-description" in "units" table and "unit" column in "units" table.
"v_no_zero_column" Validation Rule

After defining, assign this rule to "product_reorder_level" column in


"product_master" and "tran_qty", "tran_serial_no", "tran_no",
"tran_item_no" in "trans" table.
DataWindow Painter
DataWindow is one of the cornerstones on which PowerBuilder is built upon
and perhaps coincidentally one of the most extensively used components
when building an application.

In this session ( the first two devoted to this topic ) we'll introduce you to
the DataWindow Painter environment and show you how DataWindows are
used to retrieve information from a data source. We'll also cover various
methods of retrieving data and cover some of the options which relate to
them.

By the end of the session, you should be able to produce easy-to-understand


and impressive DataWindows which communicate data efficiently.

After this session you will be:

Building a DataWindow.
Connecting to a database.
Working with different data sources.
Importing and exporting data.
Using stored procedures.
Using different presentation styles.
Using the Design environment.
Using the DataWindow options.

Estimated session time: 180+ minutes.

Prerequisites:

You should have PowerBuilder (Desktop/ Professional/ Enterprise version)


installed on your computer.
SQL Anywhere 5.0 or greater installed on your computer.
Database background will be helpful, however it is not necessary.

Introduction
A DataWindow is a data aware object and is used to retrieve, manipulate
and display data from a database. DataWindow reduces to a minimum the
need for the code ( which has been specially developed to get the data from
a database into a presentable format on screen ) by internally creating
native database related commands.

There are two main parts to a DataWindow - retrieval of data from the
database and display of that retrieved data. Let us start with how to connect
to a database and retrieve the data and then we can learn how to present
the data in different styles.

Objects and Controls, Data and Users

There are 4 main steps in creating a DataWindow and using it in your


application:

1. Select a data source and a presentation style. In other words the way data is to be extracted from a
database and the format in which the data should be displayed.

2. Define appropriate SQL statements which would provide information to the user; this is referred to as
the 'Data Source' definition. In data source you define the data to be brought from the database, for
example a SELECT statement to retrieve all product information.

3. Paint the DataWindow (define fonts, colors, location for each field, etc.) to appropriately display the
information.

4. Associate the DataWindow object with a DataWindow control (you have learned about this control in
the window painter) on a window, so that the data held in the object can be displayed to the user.

5. Write PowerScript statements, functions to act on the DataWindow control.

The following diagram illustrates how PowerBuilder uses a data source,


DataWindow objects, DataWindow controls and the user interface:

A DataWindow object definition consists of any display information, initial


values, validation rules and SQL statement definitions required to present
the user with the appropriate data, ready for alteration or review. Once a
DataWindow object has been defined it has to be associated with a
DataWindow control placed on a Window.

In simple terms a DataWindow object is for data retrieval. It contains


information necessary to retrieve the data to be seen on the window, the
formatting that is needed to apply on the information and the manner in
which it has to be passed to the DataWindow control. Remember that the
difference between a DataWindow object and a DataWindow control (you
learned in the Window Painter session) is that the control simply displays the
information, while the object gets the appropriate information and formats it
as required. DataWindow control is a container for the DataWindow object.

DataWindow objects are independent of DataWindow controls and so can be


associated with any number of controls. A very powerful feature being that
these associations can be changed dynamically at run-time.

Creating a DataWindow
To invoke the DataWindow Painter, click on the DataWindow icon   from
the PowerBar. As this painter deals with the retrieval of information from a
database, PowerBuilder automatically connects to the last database used.
When connected to the database, create a new DataWindow by clicking on
the "New"button. PowerBuilder presents the following.

The first task in creating a DataWindow is the declaration of


a "DataSource" and a "Presentation Style". Clearly, the former affects the
selection of information from the database, while the latter affects
presentation of the data. We will be using the default presentation style
of "Freeform" while we examine various data sources that are available.

Before we move on to look at the different options that PowerBuilder has to


offer in regard to the data sources, it is useful to take a quick tour of the
various views of the DataWindow object that will be encountered.

DataWindow at design time

While designing a DataWindow object, the three main views that cross path
are:

Preview

Design

Select

Each of these views are used to look at the contents of the DataWindow in a
different way. Using "Preview" you can have a look at the data chosen from
the database with the commands in the "Select view", in a format defined in
the"Design view".

Preview View

Use this view of a DataWindow object for two main reasons:

To see the data that is the result of the SQL statements defined.

To review the layout of the data - this is the layout that appears in the DataWindow control on the
window.

If the "Preview when built" option is checked in the "New


DataWindow" dialog box, PowerBuilder retrieves the data with the default
settings and presents the data in this view ( as the user sees it ) when the
definition of the data source is completed. If this option is unchecked,
PowerBuilder takes you straight into"Select view".

Select View

In this view you define the SQL statements. The screens seen in this view
would be different depending on the type of data source selected in
the "New DataWindow" dialog box. Once the data source is defined, you
move onto"Design View".

Design View

PowerBuilder displays the default layout of the DataWindow based upon the
presentation style selected in the "New DataWindow" dialog box. The layout
can be changed according to the needs. Once happy with the data layout
move to"Preview view" ( explained earlier ) to preview.

Connecting to a Data Source


Now that we had a quick tour of the DataWindow painter, let's return to the
creation of a DataWindow. One of the fundamental objectives of a
DataWindow is the collection of information from a database. The method by
which it performs this task is complex and worth investigation.

PowerBuilder provides five different methods of connecting to a data source.


They have different structure and effect on the overall application. Those five
methods are:

Quick Select
SQL Select
Query
External
Stored Procedure

Let's look at each of them in turn.

 Quick Select Data Source


This method is often used to select data from a single table even though
multiple ( related ) tables selection is possible. Defining a data source is as
simple as selecting the table and the corresponding wanted columns
followed by a sort order and a selection criteria ( to obtain specific set of
data ). To see how this works, invoke the DataWindow painter, select 'New'
from the 'Select DataWindow' dialog box and select "Quick
Select", "FreeForm" and click on theOK button.
All the available tables and views are listed in the "Tables" ListBox and when
you highlight one of those entries, the related columns will be displayed in
the"Columns" list. Right-clicking on a table or a field name will display
comments associated with it.

The interested table and the associated fields are selected by highlighting
them. PowerBuilder will add the selected fields   in the box at the bottom of
the window. To further refine the information that is returned to the
PowerBuilder application specify a sort order (either ascending or
descending) and any selection criteria for each column.

By reviewing the "Select" view of this DataWindow you can see that we've


asked for all columns from the "product_master" table to be displayed.
We've specified an ascending sort order on the "product_measuring_unit"
column along with few restriction on what data should display.
If there are multiple criteria in the "Criteria" row then all the conditions in
the row must be met - this is known as a logical AND. The OR row is used to
specify OR conditions, in other words one of them must be met. The
following is the SQL statement.

SELECT
"product_master"."product_no", 
"product_master"."product_description", 
"product_master"."product_balance", 
"product_master"."product_reorder_level", 
"product_master"."product_measuring_unit" 
FROM "product_master" 
WHERE ((("product_master"."product_balance" <= 200)
AND ("product_master"."product_measuring_unit" = 'U'))
OR (("product_master"."product_balance" >= 450)
AND ("product_master"."product_measuring_unit" = 'GL'))) 
ORDER BY "product_master"."product_measuring_unit" ASC

You can also use the keywords AND and OR in a criteria for a column.
PowerBuilder automatically converts this graphical definition into SQL syntax
before requesting the information from the database. While performing this
conversion it looks at the layout of the criteria and places ANDs and ORs in
the appropriate places in the SQL statement.

A criteria can contain names of other columns in the table. This allows us to
compare two 'dynamic' values rather than having to stick with static entries
(constant values). For example, we could have specified a criteria that
required the 're-order-level' to be greater than the 'balance'.
Click on the OK button. You will be taken into the design mode. The layout
here represents the "FreeForm" presentation style. Let us don't go into
details about the layout since we will be learning about it in
the "Presentation Styles"section, so don't do anything at this time.

Switching between views

We can switch between views. Click the   icon to switch between "Select"  


and "Design" views. Similarly clicking on   icon will take you to
the "Preview"and "Design" views.

Switch to preview view. If there is no data enter few rows and save the
changes to the database by selecting "File/Save Changes to Database" from
the menu. Switch back to the design view. Close the DataWindow painter. If
you would like to save it do so.

SQL Select Data Source


This is the most flexible and extensively used method for creating a
DataWindow. It gives control over the SQL statements even for those who
don't know the syntax of SQL.

Invoke the DataWindow painter again, select 'New' from the 'Select
DataWindow' dialog box and select "SQL Select", "FreeForm" and
click OK button. PowerBuilder presents the tables/views available in the
connected database. Select "product_master" and "trans" and
click "Open" button.

When the tables having foreign key relationship ( defined in the database )
are opened, PowerBuilder automatically displays the join icon and also
creates the SQL statement with the join.

The join in the above picture bring all information from the "trans" table and
also pulls the "product_description" from the "product_master" table. All
the "selected columns" appear in the 'Selection List' at the top of the
window. To rearrange the columns click on the column name (next to
the "Selected Columns" ) and drag and drop at the place where the column
is to be placed.

Where Clause

The WHERE clause of the SQL SELECT statement is for specifying criteria for


the data to be displayed:
This is similar to the "Criteria" row of   "Quick Select" style DataWindow.
Select columns from the DropDownListBox using operators to specify the
type of comparison required. In this example, you can see that we've
specified that the "tran_type" should be equal to 'R'. The "Logical" column
allows you to build up complex criteria's with AND and ORstatements.

Note that you don't have to supply the quotation marks around the value.
PowerBuilder decides if it is needed based on the type of data and will add
them as needed.

A right-click on the "Value" box allows you to select various options from the


following pop-up menu:

Selecting the "Columns" option brings up another window with all the


columns in the selected tables. Selecting "Functions" will allow you to select
a function available in PowerBuilder. The "Select" option allows you to create
a nested SELECT statement. If you want to type a value, you don't need to
invoke this popup menu, you can type it in as well. There is another option
- "Arguments..." - which you can use if you have to set up anyRetrieval
Arguments. We'll show you how to use these arguments in a moment.

Sort

This is where you specify a sort order for the columns you want to display:

PowerBuilder displays all the selected columns in the list on the left-hand
side. By dragging the columns from left to right, you can define the sort
criteria for them.
For example, we could sort based on "tran_date", simply by dragging it from
the left to the right column.

A field can be specified to sort either ascending or descending by checking or


clearing the Ascending checkbox.

If there is more than one column in the sort order, the connected database
will sort on the first column in the list, then the second and so on from top to
bottom.

Group Clause

This allows you to group your data on one or more columns. For example,
you might choose to group your data on transaction type. This might be
useful for departments interested in a particular transaction type. Grouping
allows you to put more structure into the data by simply rearranging them.

When using SQL Anywhere database, you must include every non-aggregate
column that is to be displayed in the GROUP BY clause of the DataWindow.

This effectively invalidates the usefulness of grouping data, but with other
databases, it isn't necessary to include all the columns in the GROUP BY
clause.

Having Clause

It is used to specify criteria for a group and is created similar to the WHERE
clause.  As an illustration we could further refine the above example to
select rows whose total receipts of transaction is more than 100.

You can see that the structure is exactly the same as the WHERE clause. Our
DataWindow is quite simple so we don't need to specify any extra criteria.
This clause is seldom used with SQL Anywhere database because of its poor
support for the GROUP BY clause ( Actually that's not poor support. They are
sticking to the ANSI standards where as Sybase SQL Server enhances the
ANSI SQL and allows you to do so ) .

Compute Clause

This allows defining of computed columns based upon one or more existing
columns. For example, to show the balances that are above the reorder level
you can say "excess_balance = product_balance - product_reorder_level".
Don't get confused between Sybase's transact-SQL computed columns with
COMPUTE clause in the SELECT statement. Right-clicking on the "Computed
Column", PowerBuilder brings up a menu.  It allows you to select columns
from your tables as well as predefined PowerBuilder functions.

Syntax

The final tabbed dialog box displays the SQL statement created by
PowerBuilder.  It is based upon the entries made in the other tabbed dialog
boxes.

The SQL statements can't be editted from here. If you know SQL and prefer
to type the syntax then select "Design/Convert To Syntax" to display the full
editable SQL. Here you can edit the SQL and if you want to see the edited
SQL in the graphical format, you can do so by selecting "Design/Convert to
graphics" from the menu.

The DISTINCT Clause

When you are creating a SELECT statement, you can ensure that no
duplicate rows are displayed by specifying "Distinct" from
the "Design" menu. PowerBuilder adds the word DISTINCT after SELECT and
will return unique rows only in the resulting subset of information.

There won't be a match if two columns with NULL values are compared
for equality in a WHERE clause. If you are using one of the more flexible
database engines, you can get around this problem by using the
DISTINCT clause.

When using SQL Anywhere SQL, specifying DISTINCT automatically sorts the
result sets, but this isn't true with SQL Server and is something that should
be noted when porting applications from one database to another.

Retrieval Arguments

Instead of hard coding SQL SELECT   statement's criteria at design time


control over it can be given to the user by the use of Retrieval Arguments.

To retrieve all receipts you can write a query as below:

select * from trans where tran_type = 'R'

This query is called hard-coded query. Take the case where the user wants
to retrieve details of another transaction type. You got to write another
query. Well, that can be done, but then it's not efficient programming.
Instead write a generic query and accept input from the user and return the
results depending on the input. For example, you can rewrite the same
query as:

select * from trans where tran_type = @UserInput

The word "@UserInput" is a variable and is going to be filled by the user


input. You can observe that the variable name is prefixed with an "@". This
is the Sybase naming convention. The naming convention varies from
language to language. In PowerBuilder, you need to prefix host variables
with : (colon). In this context the term "host" means PowerBuilder. Except
for that variable in the statement, the rest of is Server specific.

select * from trans where tran_type = :UserInput

The above query  is what you type in PowerBuilder. For example, if user
specified 'T', PowerBuilder replaces ":UserInput" with 'T' and sends the
following query to the database.

select * from trans where tran_type = 'T'

Even before using variables in the SQL Statements you need to declare the
variable by selecting "Objects/Retrieval Arguments..."  from the menu.
Supply the name "tran_type" and specify the data type as String.
Once you define the retrieval arguments, you can use them in the query by
invoking the popup menu in the Value option and
selecting "Arguments" option.

When previewing, PowerBuilder prompts for the retrieval arguments. Type in


either 'R' for receipts or 'I' for issues and the relevant data will be retrieved.

Note that once a retrieval argument is specified, the same will be used
until the close of the current session or re-query the database by clicking
on the Retrieve icon from the PainterBar.

Joining Tables

The join operation is the hallmark of the relational database model. More
than any other feature, a join distinguishes relational database management
systems from other types of DBMSs. We've seen how PowerBuilder
automatically joins database tables which have the appropriate primary and
foreign keys defined, a process that is graphically depicted in the SQL
SELECT DataWindow between the "product_master" and "trans" tables:

There are basically four types of join:

Join Description

Equi or A relationship between two tables where the values in the two critical columns are compared
Natural on the basis of equality, with all the columns in both tables appearing in the results set. Note
that only one of the two joined columns is included, as they are identical.
This is the default join created by PowerBuilder.

Theta Theta joins use the comparison operators as the join condition. Comparison operators include
equal (=), not equal(!=), greater than(>), less than(<), greater than or equal to (>=) and less
than or equal to(<=).

Self A join used for comparing values within a column of a table. Since this operation involves a
join of a table with itself, two temporary (correlation) names are to be given to the table. The
correlation names are then used to qualify the column names in the rest of the query.

Outer A join in which both matching and non-matching rows are returned. The operators *= and =*
are used to indicate that all the rows in the first or second tables should be returned,
regardless of whether or not there is a match on the join column.

If primary and foreign keys are not defined for the tables, PowerBuilder
will try to join the tables based on common column names. You should
be aware of this, but it isn't bad as you can easily delete any unwanted
joins.

To change the type of join or to determine the type of joins in someone

else's database, double-click on the join box  .

Apart from displaying the type of joins, it gives an explanation of exactly


what will be selected from both tables. You can see in the first case that only
rows that are equal in both tables will be selected, whereas the next option -
an outer join - allows all the rows from one table with equivalent rows from
the other. The bottom four represent various theta joins that are possible.

Saving as a Query

You may want to save a defined SQL SELECT statement for future use. The
simplest way to do this is to save it as a query for re-use. Select "File/Save
Query" or "File/Save QueryAs..." from the menu.

A query is stored in the PowerBuilder library, along with all other objects in
the current application, as opposed to saving it as a text file containing the
SQL statements themselves.
You can also create queries outside the DataWindow Painter; this
environment is called the Query Painter. You can then choose to create a
DataWindow based upon an existing query. We'll look at this next.

Query as Data Source


Creation of Queries is similar to the creation of SQL SELECT statements,
except that it has its own Painter and are created outside the DataWindow
environment. With queries we can use multiple base DataWindows on the
same SQL statements without having to repeat the definition.

Create a new DataWindow and this time select Query as the data source.
PowerBuilder asks for the name of the query on which the DataWindow
should be based. Select the query that we just saved and click OK. If this
DataWindow is previewed,  the "Specify Retrieval Arguments" window will
popup for the transaction type. If you type in 'R', PowerBuilder will show a
preview of the DataWindow.

By selecting query as the basis for a DataWindow, we are not creating a


dynamic link between the two components. It means that the changes made
to one object won't be reflected in the other.

 External Data Source


When data retrieval is considered, databases, SQL and queries cross the
mind. However, they aren't the only ones for storing data; you can retrieve
data from an external source such as a text file.

The reason we use DataWindow even though we are not dealing with the
database is its power. It has a good sorting, filtering, printing, and whole lot
of other good features which work efficiently with only few lines of code.

An "External" Source means that PowerBuilder doesn't know the source of


the data. That means that we need to define fields for the Data Window
along with their data type. SQL statements can't be defined for these type of
DataWindows. When you try to create a DataWindow with external data
source, PowerBuilder prompts for the fields definition as shown below:
This is like the database table definition, providing the column names, data
types and lengths. To populate an external DataWindow programmatically
we use file functions or embedded SQL statements in the PowerScript code.

We need an external DataWindow for the Product_Management_System, so


create it and declare the result set as shown in the above picture.

Click OK button and save the DataWindow as "d_error_information".

We'll be using this DataWindow to display error information if something


goes wrong in our application. We could use window controls such as
StaticText, SingleLineEdit and MultiLineEdit instead of this DataWindow, but
if we do, we would have to call a whole string of print functions to print the
error information. By using a DataWindow we can print all the information
with only a single print function.

Stored Procedures as Data Source


A stored procedure is essentially a set of SQL statements that are stored in
the database. When you create a stored procedure, the back-end database
parses and converts it into internal object-ids and stores them in the
database. It would be faster when you execute it since it is already parsed.
Also, since a stored procedure is stored in the database, the client
application only needs to send the stored procedure name and any
associated parameters. This can drastically reduce network traffic and also
help to speed up execution.

We'll look at stored procedures in depth in the later session on embedded


SQL, but for now let us create a DataWindow with stored procedure as the
data source.

Invoke the DataWindow painter and select "FreeForm" and "Stored


Procedure" and click OK button. PowerBuilder lists all the stored procedures
available in the connected database; as shown in the following picture.

Once you select the stored procedure, PowerBuilder displays the stored
procedure definition at the bottom of the window. PowerBuilder
automatically detects the result set of the stored procedures and defines
them. Just in case, to define the result set manually, select the "Manual
Result set" option.

Note that the stored procedure option is available only if the database to which you are
connected to supports it.
Select "dbo.sp_tables" stored procedure and click the OK button. This will
take you to the design view. when you comeback to the data source by
clicking on the  icon, you see the result set of the stored procedure, as
shown in the picture below. Click "More" to see more details. Here, you see
the actual SQL statement that PowerBuilder sends to the connected
database.

Note that a stored procedure can return multiple result sets. By default,
PowerBuilder brings the first result set and the result set definition also
reflects to the first result set. To retrieve another result set, set it in
the "Result Set" option.

execute dbo.sp_tables;0 @table_name = :table_name, @table_owner = :table_owner,


@table_qualifier = :table_qualifier, @table_type = :table_type

You can group any number of stored procedures and give them the same
name. When you do that you need to assign a number for each group
member. While executing  if the group number is not specified, Sybase
automatically executes the first member in the group. To execute a specific
group member, specify the group no. after the stored procedure name
separated by a semicolon, similar to the above statement.

DataWindow Presentation Styles


Till now we've seen how to retrieve information for the DataWindow, but
that is only half the story. The other half would be displaying it. While doing
it we need to consider in terms of enhancement of the data as well as its
graphical simplicity.

To accomplish this, we will look at the various presentation styles that are
built-into PowerBuilder, and also how and when each style should be used.

Just as there are several ways of populating DataWindows, there are several
ways of displaying that information. PowerBuilder provides us with a wide
variety of presentation styles, each of which can be used in different
situations to provide the best layout.

We will look at each of those in turn before we look at the design view of the
DataWindow Painter, and create some DataWindows that we will be using in
our 'Product_Management_System' application

Freeform Presentation Style


We've used Freeform presentation style while learning data sources. Let's
learn all the presentation styles using SQL SELECT data source. Follow the
following steps to create a FreeForm presentation style DataWindow.
Invoke the DataWindow painter.
Select "FreeForm" and SQL SELECT options and click the OK button.
Select "product_master" table and click "Open" button.
Select all columns of   "product_master" table by clicking with the right mouse button on the table title
and selecting "Select All" option.
Click on   icon to switch to design view.

You see a DataWindow similar to the following picture.

This is the 'Design View'. Design view allows you to define what goes where
in a DataWindow. It is split into several bands depending on the type of
presentation style you are using. You can see/design the contents of a band
just above the band with the band name and an arrow next to it. For
example, all the product details shown in the above picture is in the detail
band. You can see that there is nothing painted in other bands. For getting
sufficient space in the header band to paint, click on the band and drag it
down. The following table explains different bands in the DataWindow.

Band Description
Header Displays a title at top of each page .
Header Used in Crosstab and Group styles to display group headers. ( Not shown in the
group picture.)
Detail Contains the main body of information. At design time one record is painted. In
Preview or at run-time, this band will repeat as many records as the query brings.
Trailer Used in Crosstab and Group styles to display group trailers. ( Not shown in the
group picture.)
Summary Can be used to display the summary and is printed at the end of the report. Can be
used to print report totals/averages, etc..
Footer Displays the page summary such as page no, page totals/averages, etc. at the bottom
of every page.

In the above picture, the right side column where each field is displayed in
shadow boxes, represent the columns from the database. That means, when
the DataWindow is previewed, fields from the right side column will display
the actual value. ( It can be seen in the following picture. )

The left side column where each field is displayed in boxes, represent labels
for each column. Remember specifying PowerBuilder extended attributes in
the database painter? The labels specified in the PowerBuilder extended
properties are used to create labels in the DataWindow. Sometimes you may
want a different label. Well, click on the specific label to change and type
new text.

Like any other controls/objects in PowerBuilder, every label and database


field in the DataWindow has a name. This name can be used while
programming. For example, take the name of "Product No:" label. Click with
the right mouse button on the label and select properties. You will see the
name as: "product_no_t". For labels/headings, PowerBuilder creates the
name by suffixing "_t" to the column name. For data fields, it keeps the
same name whatever it gets from the database ( the name you used in the
SELECT statement ).

SELECT product_description FROM product_master

If the above statement is the data source, the name for the data field ( right
side ) would be "product_description" and the name for the label would be
"product_description_t".

SELECT desc1 = product_description FROM product_master

If the above statement is the data source, the name for the data field ( right
side ) would be "desc1" and the name for the label would be "desc1_t". In
database terms, the name "desc1" in the SQL statement is called aliasing.
The syntax for aliasing a column might differ from database to database.
The above example followed the Sybase/MS SQL Server convention.

Let us see how the data looks like in this presentation style. We know that
there is no data in the tables. Switch to preview view by clicking   icon,
enter few rows by clicking   icon, save changes to the database by
selecting "File/Save Changes to database" option from the menu.
Remember that product_measuring_unit is the foreign key from units table. That
means, values you enter in the product_measuring_unit should exist in the units table.
We typed few rows in the units table while learning the database painter. If you didn't
enter data in the units table and get error while saving product_master, create a
freeform presentation style DataWindow for units table, by following the steps listed at
the beginning of this section. Go to preview mode and enter few rows, save them to the
database and close the DataWindow painter for the units table. You will be back to
where we were.

It is a good idea to have consistent DataWindows with perhaps a company


logo, descriptive text and date in the header band and the page number in
the footer band. If the DataWindows are consistent then it makes it easy for
users to find the information they want.

Come back to the design view by clicking on   icon. Now let's paint the
company information in the header band. Click on the header band and drag
it down till you have sufficient space.

Similar to a window, lot of controls can be painted in the DataWindow. Insert


a text control in the header band by selecting "Objects/Text" from the menu
and by clicking at the place wherever the company heading is to be placed.
Similarly use predefined functions such as Page n of n, Count(), Sum(),
Avg() from the "Objects" menu. While using aggregate functions such
as Count(), Sum(), Avg()you need to select the column on which you want
to apply the function and then select the function from the "Design" menu.
For example, to add all the product_balance counted in units, select
"product_balance" column and select Sum() from the Objects menu. ( Sum()
function on 'product_balance' in this situation would give wrong results,
since products in the SELECT statement are not restricted to a single
measuring unit. It means that calling sum() would sum up all the quantities
irrespective of the measuring unit, which is wrong. However, this function
would only work if products are grouped by measuring unit and are placed in
the sum function, in the group trailer band which will be explained in the
GROUP presentation style ). However, to display the no. of records it doesn't
matter which field is selected. Aggregate functions take different arguments.
Let's see them in detail after the presentation styles.

Paint the DataWindow as shown in the above picture. "Total Products:"


object in the picture is the text object. Insert the 'text' object by selecting
'Objects/Text' from the menu. Now preview the DataWindow. We do not
need this DataWindow, however, if you like you can save it and then come
out of the DataWindow painter.
By mistake, if you paint any object in a wrong band, don't worry, drag them onto the correct
band.

Freeform style is similar to the database forms and is best suited for data
entry rather than data display. However, to display data one record at a time
for close examination, this style is recommended

 Tabular Presentation Style


Follow the following steps to create a DataWindow in tabular presentation
style.

Invoke the DataWindow painter.


Click "New" button from the "Select DataWindow" dialog box.
Select "Tabular" and "SQL SELECT" options and click OK button.
Select "product_master" table and click "Open" button.
Select all columns from the "product_master" table by clicking on the table title with the
right mouse button and select "Select All" option.
Click on   icon to switch to the design view.

The Tabular presentation style displays data in columns with headers, like a


two-dimensional table:

In the free form presentation style, labels are used for data fields and are
placed in the detail band along with the data itself. In tabular presentation
style, headings are used and are placed in the header band.

This style is often used for reports, grouping columns and for DropDown
DataWindows. The number of columns and rows displayed on the screen at
any point of time depends on the size of the DataWindow control.
 Grid Presentation Style
Invoke the DataWindow painter but select "Grid" instead of "Tabular".
DataWindow generated with the Grid presentation style is similar to the one
with Tabularpresentation style, except that its rows and columns are
separated by grid lines:

The added advantage with the Grid style is that, at execution time users can
resize columns and can even move entire columns around by clicking and
dragging the column heading.

Unlike the Tabular and Freeform styles, headings and columns cannot be moved in the
design view of a Grid style DataWindow. If new columns are added in the SELECT list
by editing the data source, they will always be appended to the existing columns even if
placed between existing columns. To reorder the columns, switch to preview, move the
columns and switch back to design view. Any changes made in the preview mode will
be reflected in the design view.

Whenever you invoke the popup menu on an object, you see the properties
of that object. To see the properties of the DataWindow itself, you need to
invoke the popup menu by clicking with the right mouse button on the
empty space.
 

PowerBuilder makes this style even more flexible by allowing alteration of 
the basic grid characteristics. You can choose to:

Turn off the grid lines completely.


Only have them on when printing or previewing.
Restrict row resizing and column moving.
Selecting the Grid Off option automatically disables column movement. Note that under
these conditions, the Grid presentation style acts exactly like the Tabular style.

 Group Presentation Style


The Group presentation style allows you to perform the necessary grouping
of data at the client side rather than at the database end; database side
grouping occurs only when the GROUP BY clause is used in a SELECT
statement.

We've mentioned the problem with the GROUP BY clause and SQL


Anywhere database, so it allows us to get around the problem and still be
able to present grouped sets of data.

Invoke the DataWindow painter but this time select "Group".

At the time of switching to the Design view, PowerBuilder prompts as shown


in the above picture. In this dialog box, you can specify the columns on
which you want to group. Drag and drop the columns you want to group in
the "Columns" box. You can also specify a group title.
When you build a DataWindow with the group presentation style,
the GROUP BY clause isn't added to the SQL statement. PowerBuilder
automatically adds trailers containing the sum of grouped columns, together
with title information, the current date and page numbers.

Note that the trailer summations are always added to the DataWindow, even if the data that
is presented doesn't warrant such an addition. For example, in the above picture,
PowerBuilder is adding "product_balance" column, which doesn't make sense, since
products have different measuring units. Fortunately, we can modify the presentation styles
and so it is possible to remove the useless trailers.

To add a new group do so by selecting "Rows/Create Group" from the


menu.

 N-Up Presentation Style


The N-Up presentation style displays data in a format similar to that of the
newspaper columns, allowing you to use space efficiently by displaying more
than one record across the pages. Another example would be a telephone
directory, where you find multiple columns. Let's create a DataWindow with
"product_no" and "product_description" fields and with two records per row.
Follow the steps for creating a "Group" style DataWindow, instead select "N-
UP" presentation style. Select only "product_no", "product_description" from
"product_master". PowerBuilder prompts you for the number of records per
row. Type in 2.

PowerBuilder displays the data from left to right and then top to bottom as
you see in the example above. PowerBuilder doesn't allow you to alter this
organization, since there isn't any option to display the data from top to
bottom and then left to right.

Once you specify the number of records for the detail row and switch to the Design
View, you can't change the number of records. If you want, you need to do so from
scratch.

 Label Presentation Style


The Label presentation style allows you to create labels from the existing
data. Typical use of this style as you might know is for printing addresses.
Let us generate labels with "product_no" and "product-description" to stick
them on the product packages.
Create a DataWindow, this time select "Labels" style. Select "product_no"
and "product_description" from the "product_master" table.

You can choose from a vast selection of pre-defined label sizes or create a
custom label size. You can also alter the spacing, number of labels per page
and specify top to bottom or left to right display. Unlike the "N-Up"
presentation style, you can change the specification even when you are in
the design view, by invoking the popup menu by clicking on an empty space
in the DataWindow or by selecting "Edit/Properties" from the menu.

 Crosstab Presentation Style


If not for this presentation style, you end up writing hundreds of lines of
code in the PowerBuilder application, or the DBA has to write huge stored
procedures. Let's say the "trans" table has the following data.

Say for example you want to print a report that lists all the products and
quantity issued each day. That means, you list all the products one per each
row, and list the dates horizontally. Remember, each month has different
number of days, 28, 29, 20, 31. ( 20 is not a mistake, if the report is
generated on 20th of a month, then the report should list dates only till 20th
). That means you need to paint four reports and use the appropriate one
depending on the month. To print only those dates in the heading for which
there is data is really a tough job. Let the report you want look like:

If Crosstab presentation style is used, then there is no need of four reports.


Instead, paint one and PowerBuilder will take care of the rest. PowerBuilder
also prints the summary at the end of each record (right most side) and at
the end of the report. Well, you can also print footer for each page. Let's see
how to paint this type of DataWindow.

To create the DataWindow, follow the same steps you followed for the
previous DataWindows, but select "Crosstab" presentation style. This time,
select "trans" and "product_master" table. Paint the data source as shown in
the following picture:

For the example purposes we hard coded the query under


the "values"column. This query brings all the receipts for the month of
August 1996 from "trans" table. Switch to design view by clicking    icon. 
PowerBuilder prompts you for the Crosstab definition.
There are three parts to a Crosstab: columns, rows and
values. "Columns"appears in the header band and repeats at the top of each
page. The columns specified in the "Rows" prompt would appear on each
record, at the left most side. You can drag columns from 'Source Data'
ListBox and drop on other ListBoxes. The "Rebuild columns at runtime" is a
very important attribute. If you select this option, PowerBuilder generates
new columns at runtime, if necessary. For example, in 'trans" table, we have
data just for four days. Painting the DataWindow at this time would generate
four columns. If the "Rebuild columns at runtime" option is not selected and
the same report is executed when it has data for all the days in August
1996, you still get data for those four days only. But, if you select this
option, PowerBuilder generates the new columns at run-time on the fly. Click
on the OK button.
Preview the DataWindow by clicking the Preview   button. You might find
the Grand totals at the bottom useless, since the sum of Hard disks and
Monitors doesn't make sense. You can remove those totals at the bottom.
However, the totals on the right hand side are good.

 Graph Presentation Style


PowerBuilder allows you to retrieve data and display it as a Graph,
with/without the data appearing along with the Graph in the DataWindow.
Whilst the graph engine might not be as powerful as those bundled up with
some spreadsheet packages, it should be able to produce enough varieties
to cater to most business needs.

Invoke the DataWindow painter and select "Graph" and "SQL SELECT" and
select "trans" table. We assume that by this time you might know how to
paint SQL SELECT statements. Paint the data source so as to get the
following SELECT statement.

SELECT "trans"."tran_date", 
"trans"."tran_type", 
"trans"."tran_item_no", 
sum( tran_qty ) 
FROM "trans" 
WHERE ( "trans"."tran_type" = 'R' ) AND 
( "trans"."tran_item_no" = 1 ) 
GROUP BY "trans"."tran_date", 
"trans"."tran_no", 
"trans"."tran_type"
You can type "sum( tran_qty )" in the compute tab page.

Go to the design view. PowerBuilder prompts for the properties of the graph
as shown in the following picture.

The value "compute_0004" in the Value prompt  is the computed column


name for sum(tran_qty), generated by PowerBuilder. It might be different
on your computer, but there's nothing to worry about. This is the default
graph type PowerBuilder uses. In fact, PowerBuilder supports a bunch of
other graph types, select them from "Graph" tab page. Click OK button and
you go to the design view. Go to preview, and you see a report similar to the
following picture. When in design mode and you can invoke the "Graph
Properties" dialog box by clicking with the right mouse button anywhere in
the workspace.

 Composite Presentation Style


A Composite presentation style allows you to design a DataWindow using
multiple existing DataWindows. Till PowerBuilder version 4.0, it was difficult
to print two DataWindows side-by-side. This presentation style is a solution
for that problem. Let's create a DataWindow to display

Product details for product number 1 from "product_master" table.


All transactions for product number 1 from "trans" table.

Actually this can be done with a SQL join and a single DataWindow. 
Presentation becomes a problem. To overcome that, create a freeform
presentation style DataWindow for "product_master". Select all columns for
product_no 1. Save this DataWindow as "d_product_master_test". Create a
tabular DataWindow using "trans" table, select all columns from the table for
tran_item_no 1. Save this DataWindow as "d_trans_test".
Invoke the DataWindow painter and select "Composite" presentation style
and click OKbutton. Here, data source cannot be selected. PowerBuilder
prompts you for DataWindows. Select "d_product_master_test" and
"d_trans_test" in the same order. It would look like:

<="" body="" width="730" height="273">

Nested Reports
Let's consider a business requirement where a user wants to print all
products from the 'product_master' table and transactions for each of those
items. His specification being that the product information ( from
product_master ) be listed on the left side, one field per line like the free
form presentation style and transactions ( from trans table ) be listed on the
right side, one transaction per line like the tabular report, i.e. something
similar to the picture show below.
To think about it, he is asking for a combination of a free form and tabular
presentation styles, which is not possible, since you can specify only one
presentation style per DataWindow. One solution is, choose tabular
presentation style and arrange all fields from product_master one per line
and place all fields from trans side by side, as shown in the following picture.
The idea is good. However, you find the problem only when you preview the
DataWindow. You waste space, since each record takes the sum of the
height of fields from product_master and the spaces between them.

Powersoft has a facility to insert a report ( a DataWindow ) into a


DataWindow from version 4.0. onwards. Let's see if this facility provides any
solution. Try this.  Paint a tabular DataWindow that retrieves all the
transactions for a given product no from trans order by tran_type,
tran_date, tran_no and save the DataWindow, say as
'd_product_transactions'. Now, create a free form DataWindow and select all
the fields from 'product_master' order by product_no. When in the design
view, select 'Objects/Report' from the menu and click on right side of the
detail band. You will be prompted for the report name, select
'd_product_transactions' and select 'Arguments' tab page. Choose
product_no for the argument. Add a thick line at the bottom of the detail
band as shown in the picture. Now, preview the DataWindow, you see the
results exactly the way the user wanted. Bingo! it worked. This type of
DataWindows are called nested DataWindow.  They are not updateable. This
style is useful only when you have two or more related DataWindows and
would like to generate a report using them.

When you preview the DataWindow, it might be different from the picture at
the beginning of this page, i.e., you might find the horizontal line you placed
at the bottom of the detail band appear at incorrect places, may be crossing
the transactions. Don't worry about that for a now, you find the solution
later in this session.

RichText Presentation Style


This presentation allows you to display data with a wide variety of font
attributes for each field. When you use this style you need not use MS-Word
for mail-merge applications. We don't have the right data to demonstrate
this presentation style. To try out this style, invoke DataWindow painter and
select New from the 'Select DataWindow' dialog box. Select 'SQL Select' and
'Rich Text' and click OK button. Select all the columns from the
'product_master' table and click on SQL toolbar icon. You will be presented
with a dialog box that allows to choose options you would like to have at
run-time for this DataWindow. Choose the necessary options.

One thing you might notice is that, the fields are placed in the detail band,
as in a free form presentation style DataWindow. However, the labels to the
fields are not named, instead the labels are free text. Text can be typed
anywhere, and you no longer have to insert a text object to display a text.
Think this presentation style as a mini MS-Word program. The fields are
enclosed in curly brackets. Click on the field and it blinks. Unlike other
presentation styles, double-clicking on the field name doesn't invoke the
properties dialog box. Invoke the popup menu and choose 'Properties'
option.

Things that might surprise you would be, for input fields you can no longer
choose the edit style from a variety of edit styles --such as DDDW, DDLB,
EditMask, RadioButton, etc.. AutoSizeHeight property is no longer available,
but each field has 'AutoSizeHeight' feature enabled unless you choose 'Fixed
Width' option. Summary band is not available in this style. Objects such as
Sum() and Avg() can't be inserted in this style, though computed fields can
be created and used in them. Please note that, inserting a report in this style
is not permitted.

Sorting & Filtering data


The SELECT statement specified in the DataWindow painter's data source is
processed by the database. That means, any WHERE clause specified in the
SELECT statement is also processed by the database. The WHERE clause
filters the data brought to the PowerBuilder application. What if after
bringing the data to the PowerBuilder application, users wants to filter the
data they see on the screen? The traditional solution would be to send the
modified SELECT statement to the database and get the new results to the
DataWindow. When there are hundreds of users connected to the database,
this puts load on the database. To shift the load towards the Client
( PowerBuilder application ) side, specify filter criteria in PowerBuilder, by
selecting "Rows/Filter" from the menu when in design view.

For example, if 'trans' has say 100 rows, of which  40 rows are of type
receipts and 60 rows are of type issues. By giving

SELECT * FROM trans

would bring all 100 rows to PowerBuilder and by giving

SELECT * FROM trans where tran_type = 'R'

database server sends only 40 rows. However, if you issue the first SELECT
statement and filter it in PowerBuilder, the database server sends all 100
rows and PowerBuilder filters out 60 rows and displays only 40 rows. What
exactly does that mean? It is reducing load on server in terms of searching
for eligible rows (all receipts), however, it is increasing load on the server
since it has to read all the rows and send all the rows to the client. Since
database is sending all the rows to the client, the network traffic is
increased, which is not good. Basically, filtering on the client side is good
only if the user wants to filter data from the result set.

Similarly, the whole sorting load can be moved away from the database, by
selecting "Rows/Sort" from the menu and specifying the sort criteria. If the
sort order is specified using the ORDER BY clause in the SELECT statement,
the database server sorts the results before sending them to the
PowerBuilder application. To move all the sorting load to PowerBuilder, do
not specify the ORDER BY clause, instead move the criteria to the
'Rows/Sort' dialog box.

Let's take the same example of   'trans' tables with 100 rows, of which it has
40 receipt rows and 60 issue rows. If you issue:

SELECT * FROM trans WHERE tran_type = 'R'


ORDER BY tran_date, tran_no
SELECT * FROM trans WHERE tran_type = 'R'

The database server sends the same number of rows to PowerBuilder in both
the cases. So, there is no increase or decrease of the network traffic .
However, in the first case, the database server sorts the results before
sending it to the client and in the second case, it doesn't sort the results.
Which one to choose? Good question. It depends on the type of client your
company wants to implement, a fat client or a thin client. For fat client, the
second statement will do and for thin client the first statement.

In short, anything you specify in the SELECT statement is processed by the


connected database. To move the load onto the client, specify in the
PowerBuilder design view.

Prompt for the Criteria


There may be situations where user wants to query on different criteria,
which you don't know at design time. It is a tough job but for PowerBuilder.
In PowerBuilder, it can be done very easily by selecting 'Rows/Prompt for
Criteria' from the menu. At run time, PowerBuilder prompts for the retrieval
arguments for those columns that have been selected in this dialog box.
To see how it works, create a DataWindow without any WHERE clause and
specify the "prompt for Criteria" columns. Preview the DataWindow. For the
selected columns, PowerBuilder prompts for the arguments. There is another
method  'Query Mode' for querying the DataWindow, which will be explained
in later sessions. 'Prompt for Criteria' method of querying is good only when
you want to restrict the user into querying on few columns. For example, to
restrict the user from querying on columns that do not have indexes.

Data Retrieve Properties


Sometimes, a query might return hundreds of rows and take time to retrieve
all that data. A typical user ( any user ) would like to have a quick response
time. PowerBuilder, by default doesn't display the data in the DataWindow
until it completes retrieval of the data. To force PowerBuilder into displaying
data as it retrieves, or to retrieve data only so much as to display one full
screen, you need to turn on "Rows/Retrieve/Retrieve As Needed" from the
menu. For example, let's say, you select the above options and you are
expecting the query to return 2,000 rows and   say, only 12 rows can fit at a
time on the window . Now, if you retrieve the data, PowerBuilder retrieves
only 12 rows. When the user scrolls, PowerBuilder needs data to display so it
will retrieve another 12 rows and display them on the screen.

In another situation, may be you want to bring the whole data from a table
which has say 20,000 rows. The memory may not be enough to bring all
that data. Hence, select "Rows/Retrieve/Rows to Disk" from the menu.
PowerBuilder writes the data to the disk as it retrieves and you will not get
'Your system is running out of memory, Please close some applications' error
message from the MS-Windows operating system.
Suppressing Repeating Values
Sometimes you don't want to show repeating values, instead you want to
display them once. For example, the following picture retrieved a full
transaction. As you see, the tran_no, tran_date and tran_type is same for
each item in the transaction. You may want to show those details only once.

You can suppress the repeating values by selecting "Rows/Suppress


Repeating Values" from the menu. The following picture displays the same
report after selecting the option for "tran_no", "tran_date" and "tran_type".
It has a group by presentation style affect.

Specifying Data to be Retained


Sometimes, you may want to create a prototype PowerBuilder application
when the database is not yet created. Here, you can't retrieve the data from
the database since it is not ready. For prototyping purposes you need few
records only. A traditional solution for this problem is to store data in a text
file and read the text file through a program and populate the DataWindow.
With PowerBuilder's "Data retain" feature, programming is not necessary.
Some data can be stored in the DataWindow's definition itself. When data is
stored like that, PowerBuilder automatically displays it whenever the
DataWindow is opened in the window or whenever it is previewed even
without a Retrieve() function being issued ( Retrieve() is a function used in
scripts to retrieve data into the DataWindow at run-time ).

Select "Rows/Data" from the menu. PowerBuilder prompts for the data as


shown in the following picture:

Here add, insert or delete any of the information which is saved in the
DataWindow and if the database is ready, you can also retrieve data from
the database and store it along with the DataWindow definition in the
PowerBuilder library painter.

Note that any changes made to the information at this point won't affect the data contained
in the database. This is simply another layer of data control which allows you to refine
information displayed in the DataWindow. In most cases, you would not want to alter data
at this level, as you must have already refined your data set in the appropriate SQL
statement.

DataWindow Options
You should now be confident by now to create your own DataWindow using
various presentation styles and data sources. In this section, we'll run
through some of the other options available both in Design view
and Preview.

Column Specifications

Let's go into details about columns we placed in the DataWindow.


SelectRows/Column Specifications from the menu. PowerBuilder opens the
the following dialog box.

Column names that are listed in the SELECT statement can be seen under


'Name' column. When a user inserts a new row in the DataWindow, by
default it displays a blank record. May be for some columns you would like to
display default values. For example, to display "Not Defined" for the
'product_description' column, specify the same in the "Initial Value" prompt.
Remember defining extended attributes in the database painter? While
creating a DataWindow, PowerBuilder by default takes those extended
attributes. However, changes made to the extended attributes won't affect
DataWindows that were already created. They affect DataWindows that are
to be created in future. To synchronize extended attributes, use 'DW Sync'
utility which is part of 'Advanced Developer's kit'.

Similarly, validation rules and validation messages. You can notice in the
above picture that PowerBuilder automatically changes the validation
definition depending on the datatype. For example, we created
"v_no_zero_column" as "@col > 0", for which the datatype was a "Number".
Here the same definition is changed to "real( GetText()) > 0". That's because,
the value entered by the user is always in a string format. Before comparing
it with a numeric value, we need to convert it into a number. More
on GetText() in the PowerScript session.

If you scroll right in the "Column Specifications" dialog box, you see another


heading "DB Name". It's the column name in the database. For example, for
product_no, the name in the DataWindow is "product_no" and the name in
the database is "product_master.product_no", the default name. The name
of a column in the DataWindow can be changed in the columns dialog box,
however  "DB Name", the data type or its width can't be changed here. To
see, close this dialog box, invoke the properties dialog box for "product_no"
and change the name and invoke the "Column Specifications" dialog box
again. You would see the new name under the "Name" heading.
PowerBuilder uses  "DB Name" when it talks to the database. In  
programming, we always use the 'Name' property and we do not use the 'DB
Name' property. That is for PowerBuilder internal purposes only. Close this
dialog box.

Other Column Properties


Displaying as Picture

Now to other properties. Sometimes, you may have image file names in the
database and images itself outside the database. For example, let's assume
that "product_master" has a column "product_image" which contains the
images file name. When a DataWindow is created and viewed, PowerBuilder
displays the image file names. It would be appropriate if it displays the
image instead of the file names. This can be done very easily. Click with the
right mouse button on the column name and invoke the properties dialog
box and turn on "Display as Picture" property in the "General" tab page. In
this case, PowerBuilder takes the column value as the name of the image file
( the image file name should have proper PATH included otherwise
PowerBuilder looks for the file in the working directory ) and reads the image
from the disk and displays it.

Column Edit Style & Validation Rule

By default all columns have "Edit" edit style, unless defined otherwise in the
database painter. All the edit styles you saw in the database painter are
available in the DataWindow painter. We are not going into details of each
edit style, because, it was already done in the database painter. The same is
the case with the validation rule and the display format.
Any changes made to the PowerBuilder extended properties for a
DataWindow is specific to that DataWindow only. At any point of time, now
or in the future, they will not affect other DataWindows. That is not true for
the changes made to PowerBuilder extended attributes in the database
painter. They affect all future DataWindows.

Changing the Record Height Automatically

Let's explain it with the help of an example. Take the table "book_details"
that stores details about books. It has a column "comments" which is of
string datatype and allows 256 characters. When you create a DataWindow
for this table, you have to make sure that the data in this column fits
properly. The space taken by 256 characters on report is lot. In there, some
records may not have data, i.e., no comments. Painting the DataWindow
with a fixed amount of space would waste stationery.

For situations like these, PowerBuilder provided a special property called


"AutoSize Height" in the "Position" tab page. If this property is selected,
PowerBuilder automatically adjusts the record size depending on the
contents of the column. If there is no data in the column, it takes only one
line. If there is text, it would take the space required to accommodate the
text. Cool feature, isn't it.

Sliding Objects

Do you remember placing horizontal line in the nested reports lesson and it
being displayed at wrong place at preview-time, as shown in the following
picture?
When a report is placed in the detail band, the detail band is set to
'AutoSizeHeight' automatically. Depending on the height of the nested
report, the detail band height changes automatically. However, if you place
any other object in the detail band, PowerBuilder displays the object exactly
at the same place where it was placed. In the above example, you were
expecting the horizontal line to be displayed at the bottom of the record and
so placed the line accordingly. However, at run-time the height is changed
because of the nested report. To get the desired results, what you need to
do is, go to the properties dialog box for the horizontal line and select
'Position' tab. Select 'All Above' option for the 'Up' prompt under the 'Slide'
group, close the properties dialog box and preview it. The horizontal line will
be at the place where you wanted it to be.

Computed Fields

Computed fields allow you to produce very complex expressions using any of
the PowerBuilder's built-in functions. For example, the difference between
"produc_balance" and "product_reorder_level" can be done in two different
ways. One method is to place this calculation in the SELECT statement itself.
When the computation is part of the SELECT statement, the connected
database does the computation and sends the results to the client
application, such as a PowerBuilder application. To have client side
computations, use "Computed Fields" feature. Select "Objects/Computed
Field" from the menu and click at the point where you want to place the
computed field. PowerBuilder prompts for the Computed Field definition as
shown in the following picture.

For the above example, give, product_balance - product_reorder_level in the


expression box.

Coming to the classic computation, 'divide by zero' error, a big headache in


some databases. When a number is divided by a zero, an error occurs. Some
databases do not have functions to check and substitute for the zero value if
the column has a zero value. You can solve this problem by moving the
computations to the client side.

If( col1 > 0, ( (col1/col2) * 100), 0)


The above expression says, if the value of col1 is greater than zero,
calculate the percentage otherwise, return zero.

Print Specifications

You can specify printer parameters for printing a DataWindow in two places:
in the design view of the DataWindow painter or in the script before printing.
It is a good idea to set up options in the DataWindow painter itself, so that
each DataWindow can have its own set of custom parameters.

To display the print specifications for a DataWindow, select "Design/Print


Specifications...".

The document name you specify here will appear in the print queue. Like
any other document, it also has a standard margin and paper print options,
but the difference is that the margins are in PowerBuilder Units by default.
Change this to a more understandable form by
selecting "Design/DataWindow Style..." and by changing the units.

A timer interval is useful when you have fields derived from


the time() function. It can also be changed here. For example, you can add
a computed field to a DataWindow and specify the expression
as time(today()) to effectively display a clock on the DataWindow. Now all
you need to do is change the "Timer"Interval so that the clock is updated
every second, minute or whatever.

Preview Options: Split Horizontal Scrolling

While previewing a DataWindow, all the zoom and row description options
that were available in the 'Data Manipulation' view in the database Painter
are available. An extra feature available is the ability to divide the
DataWindow into two horizontal areas, which can scroll in the sync mode,
independent of each other.
To split a DataWindow need move the cursor over the black rectangle at the
bottom left hand corner of the DataWindow. When the cursor changes to a
double arrow, click and drag it, to position the split.

This feature is most useful when the information is spread across the page
and you need to relate something on the far right to something on the far
left side of the page.

Exercises
You need to paint the following DataWindows. The necessary details are
listed below. Please don't skip these exercises. You will be using them in
your coming session, "PowerScript".

DataWindow Object Names Completed DW Objects for Comparison


d_units_maint d_units_maint_asi.srd
d_units_dropdown d_units_dropdown_asi.srd
d_product_custom_query d_product_custom_query_asi.srd
d_display_product d_display_product_asi.srd
d_products_maint d_products_maint_asi.srd
d_trans_data_entry_header d_trans_data_entry_header_asi.srd
d_trans_data_entry_detail d_trans_data_entry_detail_asi.srd
d_transactions_monthy_rep d_transactions_monthly_asi.srd
d_error_info_display d_error_info_display_asi.srd
d_units_maint
Property Value
Data Source SQL SELECT
Presentation Style Tabular
Tables units
Columns All
Data Source definition SELECT "units"."unit",
"units"."unit_description" 
FROM "units" ORDER BY "units"."unit"
Other issues: -None-

d_units_dropdown
Property Value
Data Source SQL SELECT
Presentation Style Tabular
Tables Units
Columns All
Data Source SELECT "units"."unit", 
definition "units"."unit_description" 
FROM "units"
ORDER BY "units"."unit"
Other issues: Remove headings from the header band and move the header band all the
way up.

d_product_custom_query
Property Value
Data Source SQL SELECT
Presentation Style Free Form
Tables product_master
Columns All
Data Source definition SELECT "product_master"."product_no", 
"product_master"."product_description", 
"product_master"."product_balance", 
"product_master"."product_reorder_level", 
"product_master"."product_measuring_unit" 
FROM "product_master"
ORDER BY "product_master"."product_no"
Other issues: Set product_measuring_unit edit style to DDDW ( d_units_dropdown )

d_display_product
Property Value
Data Source SQL SELECT
Presentation Free Form
Style
Tables product_master
Columns All
Data Source SELECT "product_master"."product_no", 
definition "product_master"."product_description", 
"product_master"."product_balance", 
"product_master"."product_reorder_level", 
"product_master"."product_measuring_unit" 
FROM "product_master"
WHERE "product_master"."product_no" = :a_product_no
Other issues: :a_product_no is a retrieval argument. Screen is same as
"d_product_custom_query" DataWindow. Set product_measuring_unit edit style
to DDDW ( d_units_dropdown ).
d_products_maint
Property Value
Data Source SQL SELECT
Presentation Style Tabular
Tables product_master
Columns All
Data Source definition SELECT "product_master"."product_no", 
"product_master"."product_description", 
"product_master"."product_balance", 
"product_master"."product_reorder_level", 
"product_master"."product_measuring_unit" 
FROM "product_master" 
ORDER BY "product_master"."product_no"
Other issues: Set product_measuring_unit edit style to DDDW ( d_units_dropdown ).

d_trans_data_entry_header
Property Value
Data Source SQL SELECT
Presentation Style Tabular
Tables trans
Columns tran_no, tran_date, tran_type
Data Source definition SELECT "trans"."tran_no", 
"trans"."tran_date", 
"trans"."tran_type" 
FROM "trans"
Other issues: Set the edit style of 'tran_date' to EditMask.

d_trans_data_entry_detail
Property Value
Data Source SQL SELECT
Presentation Style Tabular
Tables trans
Columns All, but delete the following columns from the display.
tran_no, tran_date, tran_type
Data Source definition SELECT "trans"."tran_no", 
"trans"."tran_date", 
"trans"."tran_type", 
"trans"."tran_serial_no", 
"trans"."tran_item_no", 
"trans"."tran_qty" 
FROM "trans"
Other issues: -None-

d_transactions_monthy_rep
Property Value
Data Source SQL SELECT
Presentation Crosstab
Style
Tables product_master, trans
Columns tran_qty, tran_date from "trans" table. "product_description" from
"product_master" table
Data Source SELECT "product_master"."product_description", 
definition "trans"."tran_date", "trans"."tran_qty" 
FROM "product_master", "trans"
WHERE ( "trans"."tran_item_no" = "product_master"."product_no" )
and 
((month( "trans"."tran_date" ) = :a_month ) AND 
( year( "trans"."tran_date" ) = :a_year ) AND 
( "trans"."tran_type" = :a_tran_type ) )
Other issues: Join two tables on "product_no". The retrieval arguments are :a_month, :a_year
and :a_tran_type. Datatype of the first two is number and the last one is a string.
d_error_info_display
Property Value
Data Source External
Presentation Style FreeForm
Tables -Not applicable-
Columns See the picture
Data Source definition See the picture
Other issues: -None-

Design View Screen Shot:


PowerScript Basics
In previous sessions, you have learnt about painting various objects that
make a PowerBuilder application. That is only part of the application
development process. You also need to write code using PowerBuilder's 4th
generation language, PowerScript.

PowerScript is a powerful Object Oriented language. When using it you may


notice that in many cases only one line code is all that is needed to
accomplish the much needed functionality. We'll be looking at the simplicity
of the coding language, the flexibility of the scripting environment and where
the code should be added to get the desired effect.

After this session you will be able to:

Understand PowerScript features.


Code examples to understand PowerScript basics.
Compile and save scripts.

Estimated session time: 60+ minutes

Prerequisites:

You should have PowerBuilder ( Desktop/ Professional/ Enterprise version )


installed on your computer.
Introduction
Take COBOL as an example for procedural programming language. There are
four different divisions to the source code: Identification, Environment, Data
and Procedure. Each of these sections are executed in order, line-by-line,
until the end of the source code. The result is 'pre-defined' for a given entry
and all stages must be completed before a result is produced.

PowerBuilder is based on the concepts of Object Orientation and handles the


problem in a different way.

Event Driven Programming

Switching from COBOL/C, FoxBase/Dbase for DOS environment to


PowerBuilder environment may result in a cultural shock. In PowerBuilder
environment, you write code for events which are triggered by the system
whenever an event occurs- this is called Event Driven Programming. Simple
examples would be opening a window, it triggers the 'Open' event. Clicking
on an object triggers "Clicked" event for that object.

When using Event Driven Programming, you provide scripts for events to
which you want the object to respond. When you release the object into the
programming soup, it floats around waiting for an event message to be
forwarded to it and then runs the appropriate script, when it comes across
the event.

For the purpose of understanding, let us create a window with two


CommandButtons "cb_left", "cb_right". Save the window as
"w_script_practice".

If you remember, we wrote a single line of code in the Application's open


event. We need to change that. Invoke the application painter and click on
the Script   icon or select Edit/Script from the menu. Delete the script and
write the following.

Open ( w_script_practice )
Now, run the application by clicking on the   icon or press Ctrl + R keys.
Click on the buttons, anything happening? Nothing! That is because, we
didn't write scripts to the clicked event.

If for an object, script doesn't exist for an event, nothing happens when
that event occurs and the object goes back into waiting for the next
event message.

This is known as 'defensive' programming, since you're relying on the user


to select the next course of action, rather than guiding them through a strict
series of actions. On the other hand, you are allowing the user to take
control and choose what happens after what and in what order, rather than
having them to stick to a rigid and predefined order of events.

Go back to the Window painter. Invoke script editor for cb_left


CommandButton and write the following code.

MessageBox( "Message Title", "You clicked me." )

Run the application again and now click on the cb_left button and see what
happens.

Every object in PowerBuilder has a set events. Each object can have
different events. Some may have only couple of events and others might
have a list of events. You can browse the events for each object from the
object browser by clicking on   icon.
Let's see events for the CommandButton. Click on the "System" tab page
and select "CommandButton". On the right side, double click on the "Events"
option.

Apart from the events fired by the user's interaction with the basic
PowerBuilder objects, there are few other internal or system events for
which we can write the code. For example, whenever you print a
report,PrintStart event for the DataWindow is fired and
the RetrieveRow event occurs whenever PowerBuilder retrieves a row from
the database andRetrieveEnd event occurs whenever PowerBuilder
completes retrieving data from the database.

Here, the entire code is not as a single large listing. Each script is small and
compact, hence it is easier to test and debug the PowerBuilder application's
code rather than an equivalent example based in a procedural language like
COBOL.

Scripting Basics
Before we start coding, it's a good idea to establish some naming
conventions, a few guidelines about writing comments and some other basic
things that control the look and feel of the script. Here are some general
guidelines.

Identifiers

All PowerBuilder variable/object names should follow the following naming


conventions.

They must start with a letter and can have up to 40 characters.

Spaces are not allowed.

They are case insensitive.

They can include letters, digits and the following special characters: dash ( - ), Dollar ( $ ), Percent
( % ), Hash ( # ) and Underscore ( _ ).

Variable Declarations

Variables have to be declared before they are used in the PowerScript code.
Compiling a script in which a variable is used even before it was declared,
gives the following error message:

The following is the syntax for declaring a variable.

<Data Type> <Variable Name> = [<Variable Value>]

For example, in the above script, we want to declare the counter and total
variables as integers:

integer li_counter
integer li_total = 0
The variable initialization is optional. In the above example the initial value
for li_total variable can be left off, as PowerBuilder assigns a default value of
zero to integer data types.

By default, string data types are assigned an initial value of "" and Boolean
data types a value of FALSE.

As explained earlier, both the variables can be declared in a single line:

integer li_counter, li_total = 0

Standard Data Types

There are two types of data in PowerBuilder: standard and enumerated. The


following table lists the standard data types:

Datatypes Range
Boolean TRUE or FALSE.
Character (char) A single ASCII character.
String Any ASCII character. Length: 0 to 60,000.
Integer (int) -32,768 to +32,767.
Long -2,147,483,648 to + 2,147,483,647.
Real Single floating point, six digits precision,
range 1.17 E -38 to 3.4 E +38.
Decimal Single decimal numbers with up to 18
digit.
Double Single floating point, 15 digits precision,
range: 2.2E-308 to 1.7E+308.
Date Includes full year (1000 to 3000).
DateTime Date and Time together.
Time Time in 24-hour format - supports fraction
of a second (up to six digits).
UnsignedInteger (Uint) 0 to 65,535.
UnsignedLong (Ulong) 0 to 4,294.967,295.
Blob Binary large object (No limit).

Enumerated data types are used as arguments in functions and to specify


the attributes of objects. To see the supported enumerated data types,
invoke the browser by clicking  icon and click on the "Enumerated" tab.On
the left hand side you will see the attributes that needs a value of
enumerated datatype. Click on the attribute name and click the properties
option on the right side, you will see the valid enumerated values for that
attribute.
The following example demonstrates the usage of an enumerated datatype.

To display a 'Yes' and a 'No' button in the message box invoked by clicking on the cb_left
CommandButton, write the following code in the "Clicked" Event

MessageBox( "Hello!", "I understood using enumerated datatypes.", &


Information!, YesNo!, 1 )

Accessing Object's Attributes

Each object has certain attributes or properties. To see properties of a


CommandButton, invoke the Object Browser and select "System" tab page
and click on "CommandButton" option. Now double-click on the properties,
which is located in the right side box.
To access object attributes, use the object name and the attribute name
with a period in-between. For example, to store the window title in a
variable, you can write:

String ls_WindowTitle
ls_WindowTitle = w_script_practice.title

To change the window title, you can write:

w_script_practice.title = "New Title"

Let us hide the "cb_left" button whenever user clicks on the "cb_right"
button. Write the following for the "Clicked" event of the "cb_right" button.

cb_left.visible = false

Functions
PowerBuilder has a vast range of built-in functions which can be used in the
scripts. We've already seen some of them while creating validation rules for
your database tables. To save you from remembering the function names,
PowerBuilder allows you to paste functions from the generated list into the
code by simply selecting "Edit/Paste Function..." or by clicking the   icon.

This feature also allows you to paste user-defined and external functions into
the code.
Let's redo the code for hiding the "cb_left" button in "Accessing Object
Attributes" topic. Change the code of "Clicked" event for "cb_right"
CommandButton to:

cb_left.hide()

We did the same thing, i.e., hiding the left side button, however, we are
calling a function instead of manipulating the 'Visible' attribute directly.
Function calling convention is similar to accessing object properties. Object
name and the function name are separated by a period. Here, it means that
a function that is declared at cb_left CommandButton is called.

There are some global functions, i.e., they can be called from anywhere in
the application and there is no need to prefix it with an object name. For
example,

MessageBox( "Title", "You clicked me." )

is a global function and you can call it anywhere in the PowerBuilder


application. To see the list of all global functions, invoke the object browser,
select 'System' tab page and double-click on 'Functions' option. You see all
the global functions on the right side.

Scripting Structures
PowerBuilder supports several common coding structures for decision
making and looping. To see the supported structures, click on the "Paste
Statement" icon   :

This allows you to paste a skeletal framework of the required statement in


the code. It provides a uniform layout and reduces development time. For
example, if you paste the "If Then Else" statement in your code, you get the
following structure:

IF <condition> THEN
<action1>
ELSE
<action2>
END IF

You can make changes to the statement, substituting specific variables, test
conditions and so on. In the previous section, we wrote code to hide
"cb_left" CommandButton, and no code to display it back. Let's do that using
the IF statement. Change the script for cb_right's clicked event to the
following.

IF cb_left.visible THEN
cb_left.Show()
cb_right.text = "&Show"
ELSE
cb_left.Hide()
cb_right.text = "&Hide"
END IF

Run the application and click on the "cb_right" button multiple times and see
what happens.

FOR...NEXT

This control structure is used to iterate one or more commands for a certain
known number of times. To see how this code works, do the following:

Place a ListBox on the window and enter values shown in the picture. Make
use of  the 'Items' tab page to enter the values. Place a CommandButton
and name it 'cb_for_next_test' and set the text to 'For…Next'. Write the
following code to the clicked event of 'cb_for_next_test'. The following code
displays the text value of each item in the ListBox.
// Object: cb_for_next_test CommandButton in w_script_practice window
// Event: Clicked
Integer li_TotalItems, li_Counter
li_TotalItems = lb_1.TotalItems()
For li_Counter = 1 to li_TotalItems Step 1
MessageBox("Item No #" + String(li_Counter), lb_1.Text( li_Counter ))
Next

In the above code, two integer variables are declared. Follow the naming
conventions. The first letter indicates the scope of the variable. This includes
'l' for local, ''i' for instance, 's' for shared and 'g' for global. You will be
introduced to variable scoping in the later sessions, till then keep in mind the
above said. The second letter indicates the datatype of the variable. For
example 'i' for an integer variable. Sometimes, you come across multiple
datatypes starting with the same letter, such as a date and a datetime. Here
both are starting with letter 'd'. So, use 'd' for date and 'dt' for datetime.
There is no limitation on the number of characters you allocate for a variable
name, just end it with an underscore. For a datetime variable reportdate,
give the name as ldt_reportdate. Some people capitalize each word in the
variable instead of using underscore ( this is called 'C' language naming
convention ), i.e., lDtReportDate. PowerBuilder way of naming is to use
underscores and it is up to you and your organization to decide the
standard.

In the second line we are calling a function for the ListBox lb_1. This
function returns the total number of items available in the ListBox. Once the
total count is known,  a MessageBox() function is used to display the text
value of each item in a loop.

The variable after FOR is initialized to the value after the '=' sign, i.e.,1 in the
above code. It automatically increments with the   value specified after
the STEP keyword. Omitting the STEP keyword would set the increment value
to 1, the default value.

In the above MessageBox() function, we are sending two parameters, a title


and a message. The first argument is the title which should be a string
argument, for that reason we converted the counter into a string value by
calling the String() function. For the second argument, Text() function is used
to return the text value of the specified item number for the ListBox. Run the
window and click on the 'FOR...NEXT' button and see how it works.

In the above case, item details are displayed from top to bottom. What if the
details are to be displayed in the reverse order? Well, it is simple. Change
the value from 1 to -1 after the STEP keyword and also interchange the first
and the last value.

// Object: cb_for_next_test CommandButton in w_script_practice window


// Event: Clicked
Integer li_TotalItems, li_Counter
li_TotalItems = lb_1.TotalItems()
For li_Counter = li_TotalItems to 1 Step -1
MessageBox("Item No #" + String(li_Counter), lb_1.Text( li_Counter ))
Next

In the above code, li_Counter is initialized to the largest value and is being
decremented by 1 because of the -1.

What if you need to break out of the loop for a certain condition? Well, do it
by calling Exit. To exit from the loop after displaying five items, write the
following code:

// Object: cb_for_next_test CommandButton in w_script_practice window


// Event: Clicked
Integer li_TotalItems, li_Counter
li_TotalItems = lb_1.TotalItems()
For li_Counter = 1 to li_TotalItems Step 1
MessageBox("Item No #" + String(li_Counter), lb_1.Text( li_Counter ))
If li_Counter = 5 Then Exit
Next

'IF' statement comes in different flavors. The above format doesn't need any
END IF keyword, since we had only one line of code and placed it on the
same line.

DO...UNTIL

Similar to the FOR...NEXT controlling structure, PowerScript has few more


structures, such as DO...UNTIL. This controlling structure allows you to
execute one or more commands repeatedly until a condition is met.
DO...UNTIL comes in different formats.

DO WHILE...LOOP

This statement executes all the commands specified between DO WHILE and
LOOP, as long as the condition set on the first line ( specified on the DO
UNTIL line ) is true. FOR...NEXT statement is useful when there are counters
with fixed increments, where as this statement is used when there are no
counters and some conditions need to be checked. This statement can be
used in places where FOR...NEXT statement is used, but   incrementing the
counter is programmers responsibility.
DO UNTIL...LOOP

This statement works exactly opposite to the DO WHILE...LOOP statement.


The command block is executed as long as the condition specified on the
first line ( specified on the DO UNTIL line ) is not true.

DO LOOP...WHILE

In both DO WHILE and DO UNTIL, condition is specified before the set of


commands and it is evaluated before the commands are executed. This type
of statement is useful in places where the command block is to be executed
at least once even before the condition is checked. When this statement is
used, the commands are executed at least once and the condition is
evaluated at the end of the command block execution and commands will be
executed as long as the condition returns true.

DO LOOP...UNTIL

This statement works similar to DO LOOP...WHILE statement however, the


commands are executed as long as the condition is not true.

CHOOSE CASE...END CHOOSE

This statement is useful to execute command(s) depending on the value of


an expression or a command. Place a CommandButton and name it
'cb_list_window_controls' as shown in the following picture and write the
following code.

// Object: cb_list_window_controls in w_script_practice window


// Event: Clicked
Integer li_TotalControls, li_Counter
WindowObject lwo_Control
li_TotalControls = UpperBound( w_script_practice.Control[] )
For li_Counter = 1 to li_TotalControls STEP 1
lwo_Control = w_script_practice.Control[li_Counter]
CHOOSE CASE lwo_Control.TypeOf()
CASE CommandButton!
MessageBox( "CommandButton",
lwo_Control.ClassName() )
CASE ListBox!
MessageBox( "ListBox", lwo_Control.ClassName() )
CASE ELSE
MessageBox( "Others", "Other Window Control" )
END CHOOSE
Next

UpperBound() returns the maximum number of elements in a given array


( Arrays are explained in the future lessons ). Here it returns the number of
controls placed in the window. Similarly TypeOf() function returns the type of
control/object. The result of it is used in the CHOOSE CASE statement to
display its name in a message box. This command and
the ClassName()functions at the moment are advanced to you. With a FOR loop
for iteration we move from one control to another. In the loop, using
the CHOOSE CASE   statement, we are calling the  MessageBox() function, with
different arguments for each value.

Run the window and click on the cb_list_window_controls CommandButton


and see what result you get. See if the given control is a CommandButton or
a SingleLineEdit control, etc..

Comments
It is always a good idea to have comments to the code. There is nothing
more frustrating than trying to debug someone else's code ( or even your
own old code! ) with no comments to guide.

PowerBuilder uses the same ( two ) methods as C++ to designate


comments:

The double slash method (//). This comments out text on a line-by-line basis. For example:

// This is a comment which uses the single


// line comment style. We have to put the comment
// characters at the beginning of each line.
The slash and asterisk method (/* ... */). This is the commenting method used to comment out a
block of text which may span several lines. For example:

/* This is the comment style which is used to


comment out a large block of text. We don't have to
put the comment character at the beginning of each line,
only at the beginning and the end of the comment.*/

The Comment   and Uncomment   options on the PainterBar allow you to


quickly comment and uncomment lines of code. This is helpful when
debugging a script, to comment\Uncomment lines in order to find errors.

Line Continuation Character

PowerBuilder, with the help of the special ampersand character ( & ), allows
you to split commands that don't fit in a line. It should be the last character
of the line and note that a variable name can't be split:

MessageBox("Save","Do you want to save" + &


"changes? ", Question!, OkCancel!,2)

When using SQL statements in PowerScript, continuation character is not


needed. By default, everything after a SQL keyword is considered a single
line till a semicolon is encountered . For this reason, it is vitally important
that a semicolon is added at the end of the SQL statements. For example:

SELECT product_description INTO :lproduct_description


FROM product_master
WHERE product_no = :a_product_no;

Statement Separator

You can write more than one command in a single line by separating them
with a semicolon:

SQLCA.dbms = "Sybase"; SQLCA.ServerName = "SQLServer1"

Generally, it isn't a good idea to put more than one statement on a single
line, simply because it makes the code difficult to read. It makes debugging
complex, since any debug error message refers to a line number and doesn't
specify the command. If there are multiple statements on a line, you would
still have to determine which statement is causing the error.

To overcome this problem, put each statement on separate lines. There is no


difference in efficiency from PowerBuilder standpoint. Moreover it has an
added advantage of improving the readability of the code, while easing
maintenance.

Arrays
An array is a series of memory locations that share a name and are
identified by an index number. Arrays allow us to refer to a series of
variables by the same name, but use a number ( an index ) to tell them
apart. This helps in writing a smaller yet simpler code.  In many situations
loops deal efficiently with number of cases by using an index number.

For example, say there are ten students and want to display their names,
without arrays you would probably code,

Integer i
String ls_Student1, ls_Student2, ... ls_Student3
ls_Student1 = 'David R'
ls_Student2 = 'Prasad B'
...
ls_Student10 = 'Mary J'
MessageBox( "Student #1", ls_Student1 )
MessageBox( "Student #2", ls_Student2 )
...
MessageBox( "Student #10", ls_Student10 )

If you use arrays, you can do it with fewer steps.

Integer i
String ls_Students[10] = {'David R', 'Prasad B', ...'Mary J'}
For i = 1 to 10
MessageBox( "Student #" + String(i), ls_Students[i])
Next

We know, it is not a great real world example, but it puts through the point.

PowerBuilder supports single and multi-dimensional arrays. Each dimension


can have up to 65K elements; the only limit to the dimensions being the
computer's memory.

To declare an array, follow this syntax:

<Data Type> <Array Name> [ <Number of Elements> ]

All standard data types can be used in an array definition, for example:

Integer products [6]


Char letters [10,10]

The exception being the use of enumerated data types for the same task.
When using single dimension arrays, initial values can be assigned to them
by simply supplying them following the declaration. For example, if we want
to assign initial values for the above integer array, we could do it as:

Integer products[6] = {1,2,3,4,5,6}

An array is like a simple table. The horizontal direction is called a dimension


and the vertical side gives the number of elements i.e. the index. For
example, let's take the product listing for three products and put them in an
array. It looks like the following:

Product No
1
2
3

When programming we need to first declare the array:

Integer products[3]

and then initialize each element

products[1] = 1
products[2] = 2
products[3] = 3

Refer to the first element as products[1], and product no 3 as products[3].


This type of arrays are useful for storing data. In the above array, we stored
only product numbers and no other details. Let's declare a two-dimensional
array and store product no in one dimension and total receipts for that
product in another.

Integer products[3,2]

Programmatically, we assign data to these elements as below:

products[1,1] = 1
products[2,1] = 2
products[3,1] = 3
products[1,2] = 350
products[2,2] = 238
products[3,3] = 793

In a readable format, the data would look like:

Product No Total Receipts


1 350
2 238
3 793

In simple terms, the number of records are number of elements and number
of columns are number of dimensions. In the above example, we have 3
records ( 3 elements ) and 2 columns ( 2 dimensions ). To make the
example a little complex, we store receipts per product per month. In that
case, month would be the second and receipts would be the third dimension.
In readable format, data in a three dimensional array would look like:

Product No / 1 2 3 4 5 6 7 8 9 10 11 12
Month No
1 50 0 10 0 0 0 0 150 30 20 50 40
2 2 8 7 2 1 23 37 0 0 0 0 150
3 700 0 0 0 0 0 0 0 0 0 0 93

Programmatically, we assign data to these elements as:

Integer products[3,12,1]
products[1,1,1] = 50
products[1,2,1] = 0
products[1,3,1] = 10
...
products[2,1,1] = 2
products[2,2,1] = 8
products[2,3,1] = 7
...
products[3,1,1] = 700
products[3,2,1] = 0
products[3,3,1] = 0
...

Single dimension arrays can also be dynamic. This enables us to use them
when the number of elements are not know. By default, PowerBuilder inserts
elements into the array starting from 1. Following this principle, the values
shown in the above example would be referred as products[1],
products[2] ... products[6].

To alter this default action, specify the starting and the finishing values as
follows:

Integer totals [3 To 8] = {1,2,3,4,5,6}

Note that this is still a 6-element array. The elements are now labeled 3 to 8
rather than from 1 to 6.
These methodologies ( initialization and start/finish label values ) can be
applied to multi-dimensional arrays also. Care should be taken since,
PowerBuilder works in a top to bottom and left to right manner. As an
example, take the following initialization:

Integer totals [1 to 3, 2 to 3] = {1,2,3,4,5,6}

PowerBuilder allocates in the following order:

1,4
2,5
3,6

To test this, replace the Clicked event script for cb_left with the following:

Integer array1 [1 to 3, 2 to 3] = {1,2,3,4,5,6}


MessageBox( String( array1[1,2] ), array1[1,2] )
MessageBox( String( array1[2,2] ), array1[2,2] )
MessageBox( String( array1[3,2] ), array1[3,2] )
MessageBox( String( array1[1,3] ), array1[1,3] )
MessageBox( String( array1[2,3] ), array1[2,3] )
MessageBox( String( array1[3,3] ), array1[3,3] )

You can observe that the second dimension started from 2, instead of 1.
That is because the array were declared that way. When you start working
with arrays, you may find it useful to programmatically identify its limits.
PowerBuilder provides two functions to determine the upper and lower
boundaries: UpperBound() and LowerBound().

The following example uses the FOR statement. Window object has a property


called "Control[]". This property is an array and contains all the control
names that are placed in the window. Replace the Clicked event's script for
cb_left CommandButton with the following.

Integer i, l_TotalControls
l_TotalControls = UpperBound( w_script_practice.control[] )
FOR i = 1 TO l_TotalControls STEP 1
MessageBox( "Control No: " + String( i ), &
w_script_practice.control[i].ClassName() )
NEXT

UpperBound() function gives the highest element in the specified array. With


a FOR statement for looping,  we are listing all the control
names.ClassName() function returns the class name. More
about ClassName() later.
There are only two controls in the w_script_practice window. The following
code refers to the 10th element from the Controls[] array, which is not in
the window.

If you refer to array elements, outside of the declared size, a run-time error occurs,
which in turn terminates the application unless an error handing script is present.

Special Characters

Use special characters such as tab or new line in a string by prefixing them
with the tilde character ( ~ ). The following table lists the special characters:

To denote these special characters... ...use these character combinations


Newline ~n
Tab ~t
Vertical tab ~v
Carriage return ~r
Formfeed ~f
Backspace ~b
Tilde ~~
Decimal number ~nnn
Octal number ~oxxx
Hexadecimal number ~hyy

The following example demonstrates the use of a new line character.

MessageBox( "New Line Demo", "Line One" + &


"~n" + "Line Two" )

MessageBox() is a global function. It takes at least two arguments. One for the
title and one for the message. If a new line character is not given in the
message, it is displayed on one line. If the above code is executed,
PowerBuilder displays the following message box.
PowerScript Pronouns
When working with controls and windows, there are three very important
pronouns that you may find useful:

Pronoun Description
This Represents the object for which the code is
written. For example, if you
write Close( this )for a window event, it closes
the window. Writing the same code for a window
control would produce an error since you can't
close a window control.
Parent Represents the object that contains the object
you are working with. For example, the Parent
for a window control is the window which
contains the control.
ParentWindow This is used exclusively in menu scripts and
refers to the window to which a menu is
attached.

Using these pronouns save time and more over make the code reusable. For
example,  write a generic script which closes a window and use it for all your
windows. Let's rewrite the above code to hide and show the cb_left
CommandButton.

Conventional Code New Code using PowerScript Pronouns


IF cb_left.visible THEN IF cb_left.visible THEN
cb_left.Hide() cb_left.Hide()
cb_right.text = "&Show" THIS.text = "&Show"
ELSE ELSE
cb_left.Show() cb_left.Show()
cb_right.text = "&Hide" THIS.text = "&Hide"
END IF END IF

Till now, we didn't write code to close the window. Place a new
CommandButton in the window and write the following code for its Clicked
event:
Close( Parent )

When the user clicks this CommandButton, PowerBuilder will close the
window. That is because the CommandButton is placed in a window and
referring to "parent" from its script means that we are referring to the
window. Close ( This ) can't be used, because, you can't close a
CommandButton; you can only hide it.

Errors and Warnings


Before you run a script, it must be compiled. PowerBuilder automatically
compiles a script if you try to exit the Script Painter after changes have been
made to the script. However, PowerBuilder also allows you to compile a
script by selecting"Design/Compile Script".

If there are any errors and/or warnings while compiling the script,
PowerBuilder displays them at the bottom of the screen and won't let you
save any changes to the script until it successfully compiles ( without any
errors ).

Errors are caused by statements which PowerBuilder doesn't understand, but


warnings can be caused by, for example, undeclared variables. A option of
turning off the Compiler and Database warnings is available. Saving of the
script is possible even though warnings are generated.

PowerBuilder overrules these options if you try to save the actual object and
displays the generated compiler warnings.
Summary

We've shown how to navigate around the scripting environment and


explained some of the variable declarations and basic scripting guidelines.
We've also gave some simple examples of PowerScript. For a complete
summary of this session, watch 'powerscript-basics.ppt' , a PowerPoint
presentation.

In the next session we'll look at database connectivity and show how to
create profiles and configure ODBC connections. We'll also discuss .INIfiles
and get into advanced scripting when we add the necessary script to our
Login window.

Questions & Answers


What is an enumerated datatype?

A variable of an enumerated data type can be assigned a fixed set of value. Values of
enumerated data types always end with an exclamation mark (!).
Can a - (dash) be used as part of an identifier name?

Yes, but, before using it turn on that option by selecting "Design/Options" from the menu
in the Script Editor window. Otherwise, PowerBuilder generates an error.
What is the character used when a statement is spanned on multiple lines?

& ( Ampersand ).
Is the following statement correct?
String Test
Test = 1000 + "sometext'
PowerBuilder implicitly doesn't convert an integer value into a string. You need to
explicitly convert it by calling a "String()" function.
What is the character used when multiple statements are on a single line?

; ( Semicolon )

Which Window Object's property keeps track of all the controls in a window?

control[]

Write a script to change the window's title to "This is my practice Window?"

WindowName.Title = "This is my practice Window"

Write code for hiding the window in two different ways.

1. WindowName.Visible = False
2. WindowName.Hide()

What is the maximum number of dimensions an array can have?

There is no limit. The limit depends on the computer's memory.

Are Identifiers in PowerBuilder case sensitive or Insensitive?

Identifiers in PowerBuilder are not case sensitive.

Exercises
Please complete the following exercises. We advise you not to download the
solution till you complete the exercises. Please note that the following
exercises are not part of the 'Product Management System'  project, these
are designed to give you experience in events & PowerScript only.

# Problem Description
1. Paint the window shown below. The same window is used in exercises 1 to
4. The train picture on the window is a picture control, below it is a
SingleLineEdit control and a ListBox and a StaticText control. The rest are
CommandButtons.

In this exercise, write the script to 'Add to ListBox' CommandButton for


adding the text provided in SingleLine Edit control to the ListBox.
Tip: AddItem()

Solution: - w_script_practice2.srw
2. Write script to display the ListBox's selected item's text on the StaticText control.

Tip: SelectionChanged Event

Solution: - See solution of exercise one.


3. Write script to the 'Hide All' CommandButton to hide all controls in the window except self
and change the text to 'Show All' and vice-versa.

Tip: Clicked event, Hide(), Show() and Visible Property.

Solution: - See solution of exercise one.


4. Write script(s) to move the picture control ( train ) along with the mouse pointer in the window
when clicked. Stop moving the picture control when clicked on the picture control again.

Tip: You need to declare an instance variable by selecting


'Declare/Instance Variables...' from the menu. We know that this topic is
not yet covered, but, knowing one point is good enough for this exercise.
The instance variable is available throughout the window. You need to
write script to Clicked event of the picture control and mousemove event of
the window. You may want to use PointerX() and PointerY() functions to
get the mouse pointer's x and y co-ordinates. Good luck!

Solution: - See solution of exercise one.

PowerScript - Database Operations


In previous sessions, you have learned about various painters. You also
painted few objects and learned PowerScript fundamentals. We are sure that
you are ready to do some real stuff such as connecting to the database
through the script and do some real-world transactions.

After this session you will be able to:

Connect to the database using PowerScript.


Retrieve and manipulate data in the database.
Query, Sort, Filter, Print the data using DataWindows.
Understand DataWindow internals and write PowerScript code to manipulate DataWindows.
Write scripts for error handling.

Estimated session time: 240+ minutes

Prerequisites:

You should have PowerBuilder ( Desktop/ Professional/ Enterprise version )


installed on your computer.
You should complete all the exercises till DataWindow painter.

The Transaction Object


As learned in the database painter, whenever a database/DataWindow
painter is invoked, PowerBuilder automatically connects it to the database
( to which it was connected the last time ). This happens in the development
environment only. A run-time environment doesn't have painters, it consists
of the distributed programs and objects. What does this mean to us? It
means that we need to connect to the database through the script at run-
time.

PowerBuilder needs information such as login name, password, database


name and so on,  to connect to a database. This information is supplied by
the program. PowerBuilder stores this information in an object called
"Transaction Object". PowerBuilder uses this information to load proper
database drivers and to logon to the database.

A transaction object contains information required to connect to the


database and results if any of the last executed SQL statement. Unlike
objects ( such as window, menu, etc. ) you saw till now,  transaction object
is an invisible object. That means, it doesn't have any visible properties such
as color, border, font and so on. PowerBuilder supplies a global ( can be
accessed from anywhere in the application ) transaction object called SQLCA
( Structured Query Language Communication Area ). It is available when an
application starts and is automatically destroyed when application execution
is completed . A transaction object has 14 properties, as shown in the
following table:

Attribute Data Type Description


DBMS String Database vendor name, such as Sybase, ODBC...
Database String Database Name
UserId String User Name or User ID
DBParm String DBMS specific
DBPass String Database Password
Lock String The isolation level
LogId String Login ID for the server
LogPass String Server Password
ServerName String Server Name
AutoCommit Boolean True/False
SQLCode Long The success or failure code of the most recent operation
SQLNRows Long The number of rows affected.
SQLDBCode Long Database vendor's error code.
SQLErrText String The database vendor's error message.
SQLReturnData String Database vendor-specific information.

To connect to a database, you must populate the transaction object and use
the "connect" statement to make the transaction object try for the
connection. If an error occurs, for example, if an invalid password is
detected or the database isn't available, then the SQLCode property will
contain a value other than zero and the SQLErrText property is populated
with an error message.

If an error occurs, you can display it and prompt the user whether to try
again or not. We'll use this feature in the code in the login window to handle
errors. When users run the application, the first thing we want them to do is
to login, using the correct profile. First let's display the login window to the
user. Write the following code for the open event of the application object:

open( w_login )

Open function opens a window and displays it on the screen. After the user
fills in the information for all the prompts, we need to validate it and connect
to the database using the user input. That means, we need to write the code
to connect to the database, for the clicked event of the OKCommandButton.

Connecting to the Database


We populate the Transaction Object ( SQLCA ) and connect to the
database, when the user enters the connection information and clicks on
the OK CommandButton. The code for the clicked event of the OK button is
as follows:

// Object: cb_ok in window w_login


// Event: clicked
// Declare Variables
int lUserAnswer
// Populate SQLCA with the user input
SQLCA.dbms = sle_dbms.text
SQLCA.database = sle_database.text
SQLCA.userid = sle_name.text
SQLCA.dbpass = sle_password.text
SQLCA.dbparm = "Connectstring='DSN=product'"
// Connect to the database
connect;
// Check for errors
if SQLCA.sqlCode <> 0 then
lUserAnswer = MessageBox("Login Error", &
SQLCA.SqlErrText + "~r" + &
"Do you want to try again ? ", Question!, &
YesNo!, 2 )
if lUserAnswer = 2 then
halt
else
return 0
end if
else
close( parent )
end if

The first two lines in the code gives an idea about the object and the event
to which the code should be written. The first line specifies the object name
and the second line tells you the event for which you need to write the code.

After declaring the variables, we are populating the SQLCA properties with
the values from the SingleLineEdit controls in the w_login window. We
connect to the database using the connect statement and check if
theSQLCode property's value is zero or not. Please note that
the connectstatement is terminated with a semicolon, since, it is an
embedded SQL statement.

if SQLCA.SQLCode <> 0 then

If the SQLCode isn't equal to a zero, an error has occurred in the connection


and we use the MessageBox() function to display the error message to the
user. This dialog box also asks the user if they would like to try again. If
they answer a 'no', we halt the execution, but if they answer 'yes', we return
them to the login window,   to try another combination. Using
aYesNo! argument, displays two CommandButtons to the user. If the user
selects the first one, i.e., 'Yes',  the   MessageBox() returns 1 otherwise, 2.

Since this loop is handled programmatically, it is easy to count the aborted attempts while
connecting to the database. If this number becomes excessive, there may be a possibility that
someone is attempting to hack into one of your databases. At this point, you may alert the
network administrator, so that the necessary steps in safeguarding the databases are taken.
Let us implement these checks later.

When PowerBuilder encounters the Connect statement, it automatically uses


values from the SQLCA object. The full syntax for the Connect statement is:

Connect <using TransactionObjectName>;

To connect to the database using a different transaction object, just specify


that transaction object in the Connect statement. If you don't specify any,
PowerBuilder uses SQLCA by default. You will learn more on creating
transaction object in later sessions.

MessageBox() function comes in different flavors. In the "PowerScript Basics"


session, we just gave two arguments; but, in the above code we gave more
than two. The first argument is the title of the message box, while the
second one is the message displayed to the user. Third argument is an icon
to be displayed at the left hand side of the message. Here we asked
PowerBuilder to display a question mark. You have few more icons to choose
from. Please note that this is an enumerated datatype argument, and ends
with an exclamation mark. That means, you have to give the pre-defined
values. We advise you to check the PowerBuilder online help for
the MessageBox(). The next argument specifies the icons ( buttons ) to be
displayed below the message. PowerBuilder counts the buttons from left to
right. For example, if the user clicks the left most button, MessageBox()returns
1 and so on. The next argument specifies the default value to return if the
user doesn't click any of the displayed buttons.

If there are database errors, but if the user wants to try again, we are
calling return 0. This statement completes the execution of the script and
returns. Does this mean PowerBuilder closes the window? No. PowerBuilder
gives the control back to the user. Zero is the script execution status.
Typically, a zero indicates a successful execution and any non-zero return
status indicates an error in the script execution.

Calling the halt command stops the execution and the application ends. If


you notice in the above code, you can see that we are not using sle_server
control. Don't worry. This value is not required for the SQL Anywhere
database, however, you need to have it if you are using Sybase/MS SQL
Server.

If everything goes fine, i.e., user connects to the database, we are closing
the parent of the cb_ok CommandButton, which is the w_login window itself.
When this window is closed, the control goes to the next line in the
applicaiton object's open event. While testing this window, provide the
following details to connect to the "product" database successfully:

"DBA" for Login Name, "SQL" for Password field, "ODBC" for DBMS field,
"product" for Database Name field. Don't type the quotation marks.

Allowing the user to cancel the login


Sometimes, may be by mistake, user executes the application. Then he
would like to come out of the application instead of proceeding with the
login. We make a provision for this by writing the following code for
theclicked event of the cb_cancel CommandButton. If the user clicks on this
button or press the Esc key, we simply stop the execution of the application:

// Object: cb_cancel in window w_login


// Event: clicked

Halt

A connection error can be simulated by not typing in a password or changing


one of the values. When a connection error occurs, you'll get a message box
telling you what the error is and asks if you want to try again.

If the users are on a Novell network,   the user information can be got
automatically by using the Novell Network Bindery Service function
callnwDSWhoAmI(), or by using the Windows SDK call GetEnvironmentVar().
These would enable you to distribute a single .INI file for all users, calling
the relevant function rather than reading the hard coded userid from
the .INIfile.

To use these functions, you need to purchase additional Novell Network Bindery Service
DLLs from Powersoft. Register the DLLs with your application by declaring them as local
or global external functions. You can then call them like any other user-defined function in
your script. We'll look at how to use Windows SDK calls in a later session, where we cover
how to declare external functions.

If  the full path for the .INI file is not specified, PowerBuilder first looks in
the directory from where PowerBuilder was started and then looks in the
working directory specified while creating the relevant program items. This is
true only when you are running the application under the development
environment, i.e., from within PowerBuilder.

When you create a .EXE file and run it independently, PowerBuilder first


looks in the working directory specified for the .EXE file program item. If the
file isn't found in that directory, it then searches in the directories appearing
in the AUTOEXEC.BAT path.

Instead of clicking on the cb_cancel CommandButton, if the user press the


Esc button, we want to do the same thing, i.e., close the application. How is
it done? To tell you the truth, there is nothing that needs to be done. Why?
Because, you already took care of it by turning on the cb_cancel's 'Cancel'
property, when you painted the w_login window in the window painter
exercises. What does it mean ? When the user presses the Esc button,
PowerBuilder automatically fires the clicked event of the button that has its
'Cancel' property turned on.

If there aren't any connection errors, we close the login window and open
the w_product_master window. Append the following line of code to the
Open event of the application object.

// Object: Application Object


// Event: Open
Open( w_product_master )

Actually, when PowerBuilder encounters an Open() function, it opens the


specified window and doesn't wait for the results of that command and
continues with the next command. That means, it should open "w_login" and
"w_product_master" simultaneously and the user should see both the
windows at the same time. In practice,  "w_product_master" is not seen
until "w_login window" is closed. Why? This is because, "w_login" window is
a window of type "response". That means, PowerBuilder doesn't execute the
next line of code, until the response window is closed.

Linking DataWindow to the Database


What we did till now was to make a connection to the database from the
PowerBuilder application. Before database manipulation, there is one more
step we need to complete, i.e., linking DataWindow to the database? You
may say, "We already connected to the database, now why should we link a
DataWindow to the database?'. It's a good question.
PowerBuilder is designed to work in heterogeneous database environment.
That means two things for us. Firstly, you can connect a PowerBuilder
application to any database. Secondly, you can have different database
connections open at the same time in the same application. If database
connections from multiple databases are open, which database should a
particular DataWindow use? Hmm!!!.

The solution for this problem is, linking a DataWindow to a database by


calling either SetTrans() or SetTransObject().

It might seem strange, since we've already defined the data source for the
DataWindow object. There are two main benefits to this:

Database Independence

As long as the result set is same, a single DataWindow can be used to


manipulate data from many databases. For example, you may have a
production database and a historic database with the same table structures
and permissions. You could use a DataWindow to connect to both, by simply
changing the database attribute of the SQLCA object.

Multiple Database Support

It allows you to connect to multiple databases within an application, at the


same time. You can create multiple transaction objects and connect to
various databases for each DataWindow.

We do this in the Open script for the window, by using

the SetTransObject()function. So add the following lines to the Open event


script for the w_product_master window:

// Event: Open
// Object: w_product_master

dw_product.SetTransObject( SQLCA )
dw_query.SetTransObject( SQLCA )

Note that there is another function which allows you to set the transaction
object - SetTrans(). If you use this function, you don't have to
call Connectstatement, but,  you loose control over transaction management
and the application automatically connects and disconnects to the database
whenever the Retrieve() or Update() functions are called. When you
useSetTransObject(), it gives you more control over the transactions. That
means, you need to take care of connecting to the database; as we did in
the cb_ok CommandButton script in the w_login window. Please note that, in
both the cases, you need to populate SQLCA object. You will be learning
more about transaction management in later sessions.

The major problem in using SetTrans()is that, continually connecting and disconnecting to a


database takes both time and processor power, and resources on both the client machine as well as
on the database server machine.

Recall painting the w_product_master window in the window painter


exercises ? As explained in the window painter, a DataWindow control is a
container for a DataWindow object. If there is no DataWindow object sitting
in the DataWindow control, then the DataWindow control is of no use to us.
The reason we didn't assign DataWindow objects is that, the DataWindow
objects weren't ready by DataWindow painter session. No problem, let's do it
now.

Go to the properties of "dw_product" and type "d_products_maint" ( no


quotation marks please ) for "DataWindow Object Name" prompt and
clickOK CommandButton. Similarly assign "d_product_custom_query" for
dw_query DataWindow control.

Retrieving Data from the Database


Okay, we laid the foundation, i.e., assigned the DataWindow object to the
DataWindow control, connected to the database and set the transaction
object to the DataWindow control. Now, what we need to do is, call a
function to retrieve the data from the database and populate the
DataWindow and display it in the format painted in the DataWindow painter.

// Object: cb_retrieve in w_product_master


// Event: Clicked
dw_product.Retrieve()

This Retrieve() function is defined at a DataWindow control. In other words,


we are calling an object function. To call an object function, you need to give
an object name, followed by the function name, separated by a period. That
means, DataWindow control name, a period  and the function name.

All the information defined in the DataWindow will be retrieved and displayed
in the DataWindow control. Sometimes,   DataWindows have SELECT
statements with arguments. In those cases, you can send the arguments
within parentheses.
If you supply values exceeding the defined arguments in the SELECT
statement, PowerBuilder does not generate error. Instead it ignores the
extra arguments. PowerBuilder added this functionality only from version 5.0
onwards. In previous versions, it generates an error. Since beginning of the
course, you were doing various exercises, but didn't see the fruits of your
labor. You will be seeing it now. Run the application and click on the
'Retrieve' button and you will be seeing the data in the DataWindow
control. Happy!

Take time to review the programming you did till now using PowerScript. Especially, if you didn't have
event driven programming experience, because, it is very easy to get lost in writing scripts, at so
many places. The following is a chart of the programming you have done so far.

Adding a Row to the DataWindow


// Object: cb_add in w_product_master window 
// Event: clicked

Long ll_InsertedRow
ll_InsertedRow = dw_product.InsertRow( 0 )
dw_product.ScrollToRow( ll_InsertedRow )

The row number returned by the InsertRow() function is of  long data type


and represents the row number of the new record. Using the zero parameter
for the InsertRow() adds ( appends ) the new row to the end of the result set.
Any non-zero parameter to the InsertRow() would add a blank row just before
the row number specified as the parameter. Even though a new row is added
to the DataWindow, by default, the cursor remains where it was. Hence, you
need to call the ScrollToRow() function to scroll to the newly added row.
In case you can't see the new blank row,   go the DataWindow painter and open
"d_product_maint" and paint borders for every column and save the DataWindow and
comeback ( run the application ).

Deleting a Row from the DataWindow


// Object: cb_delete in window w_product_master
// Event: clicked
long lDeleteThisRow
int lUserAnswer, lItemNo, lUpdateStatus
lDeleteThisRow = dw_product.GetRow()
If lDeleteThisRow > 0 then
lItemNo = dw_product.GetItemNumber( lDeleteThisRow, 1 )
lUserAnswer = MessageBox("Delete","Do you " + &
" want to delete product #" + String(lItemNo),&
StopSign!, YesNo!, 2 )
if lUserAnswer = 1 then
dw_product.DeleteRow( lDeleteThisRow )
lUpdateStatus = dw_product.update()
if lUpdateStatus = 1 then
Commit using SQLCA;
else
RollBack using SQLCA;
MessageBox( "Delete", "Error in deleting " &
+ String( lItemNo ) + "Error Message: " &
+ SQLCA.SqlErrText )
return -1
end if
end if
end if

GetRow() and DeleteRow() functions are usually paired. We use


the GetRow()function to return the current row. If it exists, it returns an
integer greater than zero. Depending on this value, we ask the user to
confirm the deletion. If they confirm it, we
call DeleteRow() and Update() functions and commit the deletion. If there are
any problems, we roll it back and display an appropriate error message.

If only the DeleteRow()is called, PowerBuilder deletes the row from the


DataWindow only and the changes are not reflected onto the database.
When using the "Delete" CommandButton, some applications implement
deleting the rows from the DataWindow. They save the deleting from the
database part for the "Save" CommandButton. Both are fine. How it is
implemented depends on the users requirement. Some users would want the
functionality of un-deleting rows for later.

Note that Commit and Rollback are database related commands, and so
should be terminated with a semicolon.
For each function you learn here, we advise you to read PowerBuilder online
help in detail.

GetItemNumber() returns the value of the specified row and column. This


function is used when the column datatype is numeric. If the column
datatype is string, you need to call GetItemString(). We can as well ask the
user 'Do you want to delete record #??'. However, our motto is to make it as
user friendly as possible, hence, it would be useful if prompted with the
product number or the product description. That's why, we are
callingGetItemNumber()to get the product number. Other useful functions to
study are GetItemDateTime().

You may not be familiar with the words commit and rollback. This is
transaction processing in action. While using the SetTransObject(), we have
to take care of committing or rolling back changes to the database. If a
commit statement is used, it means that the changes are confirmed and
they are to be reflected in the database, but then if we rollback the
changes, the database has to return to the state it was before
the Update() function was called.

Saving Changes to the Database


// Object: cb_save in window w_product_master
// Event: Clicked
int lUserAnswer, lUpdateStatus
lUserAnswer = MessageBox( "Update", &
"Apply Changes ?", Question!,YesNo!,2)
if lUserAnswer = 1 then
SetPointer( HourGlass! )
lUpdateStatus = dw_product.Update()
if lUpdateStatus = 1 then
commit using SQLCA;
else
SetPointer( Arrow! )
RollBack using SQLCA;
MessageBox( "Update", "Error in update" + &
"Error Message: " + SQLCA.SqlErrText )
return 0
end if
end if
SetPointer( Arrow! )

The first thing we did was get a confirmation from the user regarding
applying changes to the data. If the reply is positive, we call
the Update()function and commit the changes, otherwise we ROLLBACK. While
saving information to the database, it is a good idea to change the mouse
pointer to an HourGlass, to indicate about the on going operation.
You should always keep the user informed about the things going on in an
application. If a lengthy operation is in progress, you should give them an
indication of it, otherwise, the user might think that things have gone wrong.
The following table illustrates some of the general guidelines for lengthy
operations:

Duration Action
<= 4 seconds Optional HourGlass cursor.
5 - 15 Display the HourGlass cursor.
seconds
15+ seconds Display a message box and preferably an indicator for the
progress.

Sorting Data
Calling Sort() function for the DataWindow, sorts the DataWindow on the
specified criteria. However, Sort() itself takes no parameters. We need to set
the sort criteria with another function namely SetSort(). For example, if you
want to sort on product_no, you need to write the following code.

dw_product.SetSort( "product_no A" )

To set the sort criteria on product_balance and product_no:

dw_product.SetSort( "product_balance A, product_no A" )

We hard coded the sort criteria in the above statement. That's not practical.
In real projects, we would like the user to sort data on the column(s) of
his/her choice. This makes the application more interactive, dynamic and
user-friendly.

What would happen if a null value is passed as an argument for SetSort(),


and Sort() function is called ? As a result, sort criteria will not be available for
PowerBuilder, so it will prompt for it.
A "Null" value means "unknown", or "not defined". If a variable is set to a
space, it has a value of  " ".  If you set it to a zero, it still has zero as its
value. If you want to say you don't know the value, set the value to NULL.
However, PowerBuilder doesn't support setting a variable value to NULL
directly. You need to call SetNull() function for that.

// Object: cb_sort in w_product_master window.


// Event: Clicked
String Dummy
SetNull( Dummy )
dw_product.SetSort( Dummy )
dw_product.Sort()

Filtering the Data


It is exactly same as sorting, except that the function names are different.
Call SetFilter() instead of SetSort() and Filter() instead of Sort().

// Object: cb_filter in w_product_master window.


// Event: Clicked
String Dummy
SetNull( Dummy )
dw_product.SetFilter( Dummy )
dw_product.Filter()

The following dialog box is for the filtering criteria.


After filtering the data to see the unfiltered data again, click on the "Filter"
button and remove the filter expression.

Printing the Report


This is a single line script:

// Object: cb_print in w_product_master


// Event: Clicked
dw_product.print( TRUE )

A parameter of TRUE allows the display of the printing status dialog box


with a Cancel CommandButton. This allows the user to stop the print job at
any time.

If you don't pass parameters to this function, PowerBuilder prints the report
without displaying the above dialog box.
Print Previewing the Report
If a DataWindow doesn't fit on the screen, either horizontally or vertically, it
may be a good idea to allow the user to see a print preview before it is
actually sent to the printer.

// Object: cb_Print_Preview in w_product_master


// Event: Clicked
if dw_product.Describe("datawindow.Print.Preview") = "yes" then
dw_product.Modify("datawindow.Print.Preview = no")
else
dw_product.Modify("datawindow.Print.Preview = yes")
dw_product.Modify("datawindow.Print.Preview.Rulers = yes")
end if

The Describe() function returns the state of the control and we use


a Modify() function to change it. Describe() and Modify() are some of the
special functions. They are important because, they give control on
DataWindows. As the name says, Describe() gives status of the specified
parameter, where as  Modify() changes the value of the specified
parameter.

For example, if you want to hide a DataWindow control, what you do? You
call dw_product.Hide(). The Hide() function acts on the DataWindow
control. If you want to act on the object that is in the DataWindow control,
i.e., the DataWindow object, you need to use the  Modify()function.

There are two types of things that you can modify in a DataWindow object;
they are, either the DataWindow object itself or a field within the
DataWindow object.

Take the example of  printing a DataWindow. Here, you won't be printing a
field, instead you will be printing the DataWindow object itself. That means,
you are acting on the whole DataWindow.

In an other example, say you want to display the "product_balance" in red


color if the balance is less than the "product_reorder_level". That means,
you want to change the foreground color of one field, product_balance.

In the above code, we were trying to find if the DataWindow was in the print
preview mode. To act on the DataWindow object   itself, you need to send
"DataWindow" as the parameter literally, followed by the properties.

dw_product.Describe("DataWindow.print.preview")  returns either "yes" or a "no".


If it is not in the print preview mode, we are turning on the print preview
mode by calling the Modify() function.

dw_product.Modify("datawindow.print.preview.rulers=yes")  turns on the print


preview rulers.

You will be learning in depth about Describe() and Modify() in later sessions.


Till then if you need some more help, look for "describe" PowerScript
function. Once you are in that help topic, go to DataWindow Object
properties from the "See Also" button. Make a bookmark, because, you will
be referring to it in your real world projects many times.

Setting up the Printer


We'll allow users to specify their printer options by clicking on the
'cb_printer_setup' button. The script is a single function call:

// Object: cb_printer_setup of w_product_master


// Event: Clicked

PrintSetup()

This brings up the standard Windows printer select dialog box. PrintSetup()is a


global function just like the MessageBox(), that's why there is no object name
prefixed with the function.

Exporting Data to Another Format


With a single function call, you can export reports to different formats,
including HTML format, SQL, Excel, Text, etc…

// Object: cb_export in w_product_master window


// Event: Clicked
dw_product.SaveAs()

You will be prompted the following dialog box. For fun save in different data
formats, one at a time and check out the exported data.

In version 6.0, you can generate HTML forms from a DataWindow and this feature
is explained in detail in    'PowerBuilder -WWW' session.

Querying the Database Dynamically


When the users click on the 'Query' button, we would like to give them a
chance to input the query criteria and retrieve the data based on the given
input. We have two DataWindow controls in the w_product_master,
dw_query and dw_product. Actually, we don't need two of them, one is good
enough. The reason we are using two of them is, to allow the user to input
the query criteria in a form interface and see the results in the tabular form.
This also allows us to demonstrate data sharing between two DataWindows.
As you might know, dw_query DataWindow control is hiding behind
dw_product. We need to bring it to the front using BringToTopproperty.

// Object: cb_query for w_product_master


// Event: clicked

dw_query.BringToTop = True
dw_query.modify('datawindow.querymode = yes')

Then we need to put dw_query in the query mode. The DataWindows dealt
till now were in regular mode. Changing the DataWindow to query mode
inserts about ten blank rows and allows the user to provide a query criteria.
Once the user types in the query criteria, (s)he is going to retrieve the data
by clicking on the 'Retrieve' CommandButton. Change the Clicked event code
for the cb_retrieve CommandButton as follows:

// Object: cb_retrieve in w_product_master window


// Event: Clicked

dw_product.BringToTop = True
dw_query.AcceptText()
dw_query.Modify( "DataWindow.QueryMode=no" )
dw_query.Retrieve()

The above code brings dw_product DataWindow control to the front and puts
dw_query into regular mode and retrieves data from the database. You
might have observed a new function, AcceptText(). By default,
PowerBuilder doesn't take the changed value of the field in which the cursor
is present, unless the user press tab or clicks on some other field. Since we
are not going to ask the user to press tab after entering data in each field,
call AcceptText() to take the changed value, even  the current field also.

Here's something to speculate. Did you find anything wrong in the above
code? No! Don't worry, the code's fine, otherwise you couldn't have compiled
it anyway. The problem is that we are retrieving data in dw_query , but, it is
hiding behind dw_product. Then how is the user going to see the data? Let's
solve this problem in the next section.

haring Data between DataWindows


Before we proceed into the technical stuff, we have a question to answer.
Why do we need two DataWindows? That is because, we would like to give
the user a form like interface for query criteria entry and report format for
report display.

Though the presentation styles are different in these two DataWindows, the
datasource and the data are same. In that case, we can ask PowerBuilder to
share the data between these two DataWindows. This can be done by calling
the ShareData() function.

Append the following line of code to the Open event for w_product_master
window.

// Object: w_product_master window


// Event: Open
// Append the following code to the existing code.
dw_query.ShareData( dw_product )

With this code, dw_product is sharing data from dw_query. dw_query is


called the "Primary DataWindow" and dw_product as "Secondary
DataWindow". A primary DataWindow can share data with any number of
DataWindows. A secondary DataWindow also can share data with another
DataWindow in which the secondary DataWindow becomes the primary
DataWindow.

Only the data is shared between the DataWindows, not the presentation
styles. That means, DataWindows can have different sort criteria and 
presentation styles. If you delete a row in one DataWindow, the data source
is same, it is also deleted from all other sharing DataWindows. Similarly, if
you add a row, it will be available in all shared DataWindows.

Sharing data allows us to utilize the resources more efficiently. At this point
run the application and see how the 'Query' and 'Retrieve' options are
working.

We wrote code for all options in the window, except for closing the window.
Write the following code for it.

// Object: cb_close in w_product_master window


// Event: Clicked
Close( Parent )

The above code closes the window. Once the window is closed, the control
goes back to the application's open event ( which opened this window ).
There no code after opening this window. Hence, PowerBuilder closes the
application.

Questions & Answers


We know that you have learned many new things till now in this session. It
is the time to stop a while and review what we did and what you can recall.
Answer the following questions, and if required read this session multiple
times, till you digest the concepts. As we proceed further, we will be going
deep into the subject, and we don't want you to be lost. Please note that,
this session has no exercises. After these questions, the session continues.

How do you retrieve data from the database into the DataWindow?

DataWindowControlName.Retrieve() retrieves data from the database and populates the


DataWindow.
What happens if you provide more arguments than those defined in the SELECT statement
to the Retrieve() function ?
PowerBuilder generates an error if the PowerBuilder version is prior to 5.0. Otherwise, it
ignores the extra arguments.
Does deleting a row by calling Delete() in the DataWindow delete the row in the Database?
If not, what is   to be done to apply changes to the database?
DeleteRow() deletes from the DataWindow only and doesn't delete a row in the database.
You need to call Update() function for the DataWindow control to apply changes to the
database.
What is a Transaction object?

A Transaction object contains the necessary information needed to connect to a database


and also contains the result of the last executed SQL statement.
What is SQLCA?

SQLCA is SQL Communication Area, a type of transaction object. It is a global variable


and is available to any PowerBuilder application.
Which SQLCA's property contains the error code of the last executed SQL Statement?

SQLCA.SQLCode

How do you stop an application?

By using HALT statement.

Describe the functionality of AcceptText() function.

AcceptText() accepts the changed text in the current field, even if the user doesn't press the
tab key or click with the mouse button on some other field.
Is it possible to share data between two or more DataWindows? If so, how?

Yes. Just call PrimaryDw.ShareData( SecondaryDw ).

What command rolls back the changes done to the database?

Call: ROLLBACK USING TransactionObjectName ;

Write the code to put the DataWindow in the query mode.


DataWindowControlName.Modify( "DataWindow.QueryMode=yes" )

How do you turn on the 'Print Preview Rulers' for a DataWindow?

DataWindowControlName.Modify( "DataWindow.Print.Preview.Rulers=yes")

List the functions learned till now in this session.

MessageBox(), Open(), SetTransObject(), SetTrans(), ShareData(), Retrieve(),


InsertRow(), ScrollToRow(), Close(), DeleteRow(), Update(), Print(), PrintSetUp(),
Describe(), Modify(), SetSort(), SetFilter(), Sort(), Filter(), SaveAs(), SetPointer(),
AcceptText() and SetNull().
List all the statements learned till now in this session.

Database Statements: Connect, Commit, Rollback.


Other Statements: Halt.
How do you change the mouser pointer?

SetPointer( PointerName )

Describe the functionality of SetTransObject().

SetTransObject() tells the DataWindow to use a specified transaction object while talking
to the database. Using this function also gives more control over transactions to the
programmer, such as committing and rolling back the transactions.
__________ adds a row to the DataWindow.

DataWindowControlName.InsertRow( Row no. before which you want to Insert )

__________ moves the cursor position to the specified row in a DataWindow.

DataWindowControlName.ScrollToRow( RowNo )

__________ brings the specified object to the front.

ControlName.BringToTop = True

__________ displays a window.

Open( WindowName )

Populating User Defaults in the Login Window


We know that  by now you might have run the application multiple times.
The frustrating about that is, each time you run the application you need to
type the database information in the login window. Wouldn't it be nice to see
all those details ( may be except the password ) populated automatically in
the login window ? It can be done by writing the details to a file when the
user closes the application, and reading it back when he logs in again ?

Let's learn about writing to a file in the next section. First let's learn about
reading an initialization file. To read an initialization file, we need to use
the ProfileString() function. It takes four parameters, the file to read,
section name, variable name and the default value if the variable is not
defined in the file or the file is not found. If the path to the file name is not
given, PowerBuilder first checks the working directory and then the PATH.
Write the code as follows:

// Object: w_login
// Event: open
sle_DBMS.text = ProfileString( "c:\workdir\product.ini" , &
"product app" , "DBMS" , "" )
sle_Database.text = ProfileString( "c:\workdir\product.ini" , &
"product app" , "Database" , "" )
sle_Name.text = ProfileString( "c:\workdir\product.ini" , &
"product app" , "Name" , "" )

The above code reads "c:\workdir\product.ini" file and reads the values
under "product app" section. The values are automatically populated into
appropriate controls in the w_login window. If the variables are not found, ""
is populated in the appropriate control.

You may wondering why we didn't just hard code the DBMS, database and
userid in the open event script. Supposedly we do that and later something
changes, for example, say you moved your database to Sybase SQL Server,
then you need to physically open up the open script for all the applications
that you have distributed, to modify the code and reflect the changes. If you
use a .INI file, all you need to do is distribute a new .INIfile containing the
updated information or ask the user to change that file on their computer.

Saving User Defaults


First let us decide the right place to write the code for saving the user
defaults. It is a good idea to write the code in the application's close event.

// Object: Application Object


// Event: Close

Int l_ReturnStatus, l_FileHandle


l_ReturnStatus = SetProfileString( "c:\workdir\product.ini" , &
"product app" , "DBMS", SQLCA.DBMS )
// Let us create the file as it is not existing.
if l_ReturnStatus <> 1 THEN
l_FileHandle = FileOpen( "c:\workdir\product.ini", LineMode!, &
Write!, LockWrite!, Replace! )
FileClose( l_FileHandle )
SetProfileString( "c:\workdir\product.ini" , &
"product app" , "DBMS", SQLCA.DBMS )
End If

SetProfileString( "c:\workdir\product.ini" ,&


"product app" , "Database", SQLCA.Database )
SetProfileString( "c:\workdir\product.ini" , &
"product app" , "Name", SQLCA.UserID )

In the above code, we are saving the value of DBMS. The function returns -
1, if it is unsuccessful. An unsuccessful SetProfileString() means that the file is
not there and so we need to create the file. FileOpen() opens a file in the
specified mode ( write mode ) with specified locks on the file ( Write
lock ). OpenFile() creates the file if the file is not existing. FileClose() closes the
file. Once the file is created, we are setting the DBMS value.

We are setting the values by reading from the SQLCA object, recall that we
set values to SQLCA in the w_login window. Whatever values you populate
in the SQLCA will remain there till you close the application, unless you
modify them in between.

Run the application and see whether it is working. It is a good idea to see
the contents of "product.ini" and how they looks like.

[product app]
DBMS=ODBC
Database=product
Name=DBA

Displaying Help in the Login Window


Do you remember defining TAG values for each SingleLineEdit control in the
w_login window? We defined those values to display them as help for the
user.

w_login window is not a window of type MDI with MircroHelp, it is a response


window. That means, we don't have the status bar to display help. That is
the reason for painting a StaticText control "st_help" at the bottom of the
window.
Write the following code in "GetFocus" event for all SingleLineEdit controls in
the w_login window.

// Object: All SingleLineEditControls in w_login window


// Event: GetFocus

st_help.text = This.tag

Write the following code in "LooseFocus" event for all SingleLineEdit controls
in the w_login window.

// Object: All SingleLineEditControls in w_login window


// Event: LooseFocus

st_help.text = "Ready"

What we are doing here is, setting the tag value of the current control as the
text of the st_help control in the GetFocus event. When the control looses
the focus, we are setting the help to a generic word 'Ready'. Run the
application and see how it works.

Retrieve Only as Needed

This option is available in the DataWindow painter from the 'Rows' menu and
you must select it when you paint the DataWindow. The amount of data
retrieved depends on the size of the DataWindow control. PowerBuilder
automatically performs this calculation and adjusts the result display if you
change the size of the control.

When the user starts scrolling down the DataWindow, PowerBuilder retrieves
another screen full of data. A possible disadvantage of this method is, if you
print the DataWindow, only the displayed rows are printed. This also has an
effect on determining the number of rows a table has; you'll only receive a
count of the number of current records.

Another effect of using this method is that the remaining information is held
in the back-end database's memory, and this may use considerable system
resources and affect the server's response time.

You can get round these problems by dynamically changing the 'Retrieve
Only As Needed' status. For example, you could add the following line in the
clicked event of the Print CommandButton at the beginning of the script,
i.e., Print(TRUE) would be the last statement:

dw_product.modify( &
"datawindow.retrieve.asneeded = false" )
dw_product.Retrieve()
This cancels the "Retrieve Only As Needed" option, so all the information
would be printed.

Note that if you specify a sort order using the Rows/Sort option, or if you use any aggregate
functions such as sum() or avg() in the DataWindow Painter, i.e., in the SELECT statement,
then the Retrieve Only As Needed option will be ignored

Prompt for Criteria


You have learned about allowing the user to do dynamic queries.
Sometimes, you may want to restrict the fields that a user can query. Why
would anyone want to restrict a query? Well, sometimes it may be for
performance sake, such as, querying on a field might take time and hold the
server resources or to stop querying on certain fields that doesn't make
sense. In that situation, using "Prompt for Criteria" option is a good idea.

As you learned in the DataWindow painter, you can specify the fields to
prompt the user for query criteria. If you haven't set it in the DataWindow
painter and want to do it dynamically depending on certain conditions, you
are welcome to do it. The following line sets prompt for criteria for
"product_measurement_unit":

dw_product.Modify("product_measurement_unit.Criteria.Dialog=yes")

Till now we didn't use Modify() to change the column property. The above
example shows how to use it. If you want the user to provide a value for the
column in the Criteria dialog box, write:

dw_product.Modify("product_measurement_unit.Criteria.Required=yes")

Criteria dialog box uses the edit style painted in the DataWindow. If you
want to override the edit style and allow the user to type the value in the
criteria dialog box:

dw_product.Modify("product_measurement_unit.Criteria.Override_Edit=yes")

The above code overrides the edit style and displays a regular edit control
box. This is specially useful when the edit style is   DropDownListBox.

For practice, set few columns for criteria and run the application and set
them back.

Error Handling
Till now, we wrote lot of code. In some places we checked the returned
codes of functions, and in some places we skipped it. Every programmer
thinks that (s)he wrote the perfect code and it's going to work excellently,
but not in software. Remember one thing, no matter how many times you
test, it's still not enough. So, if something which we didn't expect at
design/development time happens, let's not blow the application. We need
to provide some door where we can inform the error to the user, and let him
decide the future action.

PowerBuilder provides an event to trap errors, i.e., SystemError event at the


application object. When an error ( of course not all errors ) occurs in the
application, the script written for this event is executed.

Whenever an error occurs, PowerBuilder populates the error information in a


global object namely "Error". The Error object is one of the built-in global
objects used by PowerBuilder. "Error" object has the following structure:

Property Data Meaning


Type
Error.Number Integer PowerBuilder error number.
Error.Text String Error message.
Error.WindowMenu String Name of the Window or Menu object in which the
error occurred.
Error.Object String Name of the object in which the error occurred. If
an error occurs in a window or a menu, this string
will be the same as Error.WindowMenu.
Error.ObjectEvent String The name of the event where the error occurred.
Error.Line Integer The line number where the error occurred.

When an error occurs, SystemError event is triggered at the application level


and PowerBuilder displays its default error message.   In most cases, the
application will terminate. Every time we get an error we don't want our
application to terminate, so we trap these errors by writing code for the
SystemError event.

Even a few lines of comments added to the SystemError event allows us to


continue executing our application. Unfortunately, this still doesn't help if the
error is a General Protection Fault (GPF). In that case, except for closing the
application there's little that can be done .

Open the application painter and add the following code to the SystemError
event:

// Object: Application
// Event SystemError
Open( w_error )

This opens up the w_error window painted in window painter session. Now,
let's display the error information. For that, we need to write some code in
the open event of w_error window.

Open the "w_error" window and associate "d_error_info_display"


DataWindow object with "dw_error_info" DataWindow control. ( Forgot about
associating a DataWindow object, then do this. Go to properties for the
"dw_error_info" DataWindow control and type "d_error_info_display" without
quotes for the "DataWindow Object Name" prompt. )

Write the following code for the open event of "w_error" window.

// Object: w_error
// Event: Open

dw_error_info.insertrow( 0 )

dw_error_info.SetItem( 1, "Error_No", error.Number )


dw_error_info.SetItem( 1, "Error_Message", error.Text )
dw_error_info.SetItem( 1, "Error_Line_No", error.Line )
dw_error_info.SetItem( 1, "Error_WindowMenu", error.WindowMenu )
dw_error_info.SetItem( 1, "Error_Object", error.Object )
dw_error_info.SetItem( 1, "Error_Object_Event", error.ObjectEvent )

The first statement is inserting a row into the DataWindow. Obviously it


would be row number one, since we don't have any rows. As you know,
when we insert a row it is blank. We need to populate this blank row with
the error information; the information we got from the "Error" object. We
can change the value of a field in the DataWindow by
calling SetItem()function. It takes three parameters, row number, column
number/name, value.

Now we have to add some functionality to the CommandButtons on the


window. We have four CommandButtons which allow us to continue with the
application, abort the application, print the error messages or save them to
a log file.

The Continue CommandButton

To continue with the application, we simply close the w_error window:

// Object: cb_continue in w_error


// Event: Clicked

Close(Parent)
Once PowerBuilder executes the script written for the application's
SystemError event successfully, it continues with the execution of the next
statement after the error line. As we don't have any more script in the
SystemError event, closing this window allows the user to continue with the
application.

The Abort CommandButton

If the user wants to abort the application, we call the close event for the
application, causing it to gracefully close:

// Object: cb_abort in w_error


// Event: Clicked

Halt Close

We know that you learned about Halt command previously. Simply using
the Halt command without the Close parameter would terminate the
application immediately. By adding this parameter, we force PowerBuilder to
execute any code that was added to the application's close event.

The "Print" CommandButton

For the Print CommandButton, we want to print the DataWindow control


using the Print property:

// Object: cb_print in w_error


// Event: Clicked

dw_error_info.Print( TRUE )

This will print the contents of DataWindow control to the current default
printer.

The "cb_Save_to_Log" CommandButton

This button allows the user to append the latest error information to an error
log. To accomplish this task, we need to do several jobs. These jobs include
opening an external log file, appending information in it and then closing the
file.

The script for this task is complicated:

// Object: cb_Save_To_Log in w_error


// Event: Clicked

Int lFIleHandle
lFIleHandle = FileOpen( "Product.Err", LineMode!, Write!, &
LockWrite!, Append!)
If lFileHandle = -1 Then
MessageBox("Save to Log","Unable to open Product.Err file!")
Return 0
End If

/* Some databases accept userid and some expect logid. If you


take care of the checking, you can use this script in any
application, irrespective of the database connection.*/
If SQLCA.UserId <> "" Then
FileWrite( lFileHandle,"User: " + SQLCA.UserId)
Else
FileWrite( lFileHandle,"User: " + SQLCA.LogId)
End If
FileWrite( lFileHandle, "Time:" + String(String( Now(), &
"m-d-yy h:mm am/pm")))
FileWrite( lFileHandle, "Error No:" + String( &
dw_error_info.GetItemNumber( 1, "Error_No")))
FileWrite( lFileHandle, "Error Message:" + &
dw_error_info.GetItemString( 1, "Error_Message"))
FileWrite( lFileHandle, "Error Line No:" + &
String(dw_error_info.GetItemNumber( 1, "Error_Line_No")))
FileWrite( lFileHandle, "Error Window Menu:" + &
dw_error_info.GetItemString( 1, "Error_WindowMenu"))
FileWrite( lFileHandle, "Error Object: " + &
dw_error_info.GetItemString( 1, "Error_Object"))
FileWrite( lFileHandle, "Error Object Event: " + &
dw_error_info.GetItemString( 1, "Error_Object_Event"))
FileClose( lFileHandle )

The first section of code opens a log file 'product.err' and enables linemode,
which means each FileWrite() will put text on a new line. We also enable
writing and appending to enable us to put text into the log and also to
ensure that each line of text is appended to the file. TheLockWrite! option
ensures that when the file is open, nobody else can write to it.

The next six lines of code writes the UserId or LogId into the file depending
on whichever is relevant and then writes in the date and time.

GetItemString() returns the specified field value. Use this function if the field is
of string datatype. If the field is of  number type, use GetItemNumber().
Similarly for date fields, call GetItemDate(). All these functions take two
parameters, the row number and the field number/name.

Error Signaling
Test error handling script written to the 'SystemError' event by using
theSignalError() function. Simply assign some values for the 'error' object and
call the function. This causes an application level 'SystemError' event to be
triggered, allowing you to review and test your application's error handling.

To see how this works, write the following script in the 'rButtonDown' event
for one of the CommandButtons:

// Object: cb_query for window w_product_master


// Event: rbuttondown
//
// This is test code which enables you to 
// test the error information window 
//

error.object = "window"
error.text = "This is an error"
error.line = 10
SignalError()

This simply assigns some values to the error object and calls
theSignalError() function. When you run the application, right-click on this
button and the error Information window will be displayed with the values
assigned to the error object. Once you run this code and see the results,
remove the above code.

In version 6.0,   you can specify error number and error text as arguments to
theSignalError()function. PowerBuilder automatically populates other information
in the error object and signals 'SystemError' event. Arguments to SignalError()are
optional. If you don't specify arguments, you need to take care of populating all the values in the
'error' object, even though it is not mandatory to populate all the attributes in 'error' object.

A new function was introduced with 6.0, PopulateError(). It takes same arguments


as SignalError() takes, however, arguments to this function are mandatory. This function just
populates the 'error' object. It doesn't trigger the 'SystemError' event. This feature allows you to
populate the 'error' object at certain point of time and trigger the 'SystemError' event at another
place.

Events and Messages


In MS-Windows operating system, event notification to applications is done
by MS-Windows itself, by dispatching appropriate messages. Moving the
mouse would be a simple example; when you move the mouse, MS-Windows
sends WM_MOUSEMOVE message to the window in which the mouse pointer
is located. This message has three parameters, cursor horizontal position( x
co-ordinate ), vertical position ( y co-ordinate ) and a parameter that has
flags which say which mouse button is down etc. Application respond to
Windows by executing the code written for that event.
If the current window's application ( from the above example ) or infact any
application ( in some messages ) doesn't  respond to the Windows message,
MS-Windows takes default action depending on the message. In the above
example, if you just move the mouse in "Program Manager", nothing
happens. That is because, "Program Manager" which is a Windows
application don't want to do anything when you simply move the mouse. To
give you another example, MS-Word responds by displaying the toolbar help
( in yellow color ) when the mouse pointer is moved over the toolbar of MS-
Word.

Look at another example, under Windows NT , which is more robust than


MS-Windows, try shutting down the workstation when an application is
executing something in a loop; What would happen? Since the application is
busy executing code, it doesn't respond to operating system message "close
yourself", so, Windows NT OS prompts saying if you would want to end the
task. So, in the first example, Windows default action does nothing, where
as the latter prompts the user.

All messages under Windows can be broadly divided into three categories:
Informational, Notification and Action.

Message Type Description


Informational Informational messages return the current state of on object.
For example, whether an object or its foreground color is
visible.
Notification Notification messages inform objects that something has been
done to the object. For example, when you click on a
CommandButton, Windows tells the CommandButton 'You have
been clicked' by sending an appropriate message.
Action Action messages do something to an object. For example,
adding an entry in a ListBox or creating an object.

From MS-Windows application perspective, events in the application are


triggered by MS-Windows messages. Applications respond to the MS-
Windows message by executing the code written for that event. In simple
terms, each event ( not every event, will be explained later ) in PowerBuilder
is mapped onto one or other MS-Windows message. For
theWM_MOUSEMOVE example explained earlier, PowerBuilder Window
object has a "mousemove" event. This event is mapped to
the WM_MOUSEMOVEmessage. In PowerBuilder, message id mapping has an
extra layer. That is each Windows message is mapped to the same message
id in PowerBuilder by replacing "WM" ( Windows Message ) with "PBM"
( PowerBuilder Message ) and is called "Event ID". Windows
messageWM_MOUSEMOVE is mapped to "pbm_mousemove" PowerBuilder
Event ID. The event "mousemove" is in turn mapped to "pbm_mousemove".

 As said above, all most all Window messages are mapped to PowerBuilder
Event Ids. PowerBuilder pre-defined some event names and mapped them to
the event ids of each object. For example, a CommandButton has the
following pre-defined events.

Event Name Event Id


Clicked pbm_bnclicked
Constructor pbm_constructor
Destructor pbm_destructor
DragDrop pbm_bnDragDrop
DragEnter pbm_bn_DragEnter
DragLeave pbm_DragLeave
DragWithIn pbm_bnDragWithin
GetFocus pbm_bnGetFocus
LoseFocus pbm_bnKillFocus
Other pbm_Other
rButtonDown pbm_rButtonDown

By looking at the above table you can see that mousemove event is not pre-
defined for the CommandButton, but is pre-defined for the Window. Why
didn't PowerBuilder define all event names for each object ? PowerBuilder
pre-defined events that are most frequently used and required by the
object . Want to display MircroHelp whenever a CommandButton gets focus,
then  write script in the "GetFocus" ( PowerBuilder is case-insensitive ) as
follows:

/* w_frame window is assumed as an MDI frame with microhelp window */


w_frame.SetMicroHelp( This.Tag ) 
/* PowerScript is explained in the later section. */

You may want to display floating help for buttons in the application ( like the
one you see when you move the mouse pointer over the PowerBuilder
toolbar ). In that case, writing code in "GetFocus" event wouldn't help,
because, "GetFocus" event triggers only when the user tabs into the
specified CommandButton or by calling SetFocus() in the PowerScript .
What you really want is to display help whenever the mouse pointer moves
over the CommandButton.

Just for this, PowerSoft made provision for defining events and mapping
them to one of the available events. Events that you define are classified as
"User Defined Events." You need to select "Declare/User Events" from the
menu in the appropriate painter. The following picture displays the defining
of  "ue_mousemove" event for a CommandButton by mapping it to the
"pbm_mousemove" event id.

Provide a name under the "Event Name" and select one of the existing event
ids from the "Paste Event Id" List Box ( Selecting Event ID is not mandatory,
explained in a moment ).

An event id can be mapped to one event name at each object level. You
can't unmap pre-defined events. If you don't want  anything to happen when
an event occurs, then just don't write script for that event.
The following figure illustrates event classification and valid mappings.

We can divide PowerBuilder event ids into three categories.

Event Ids Description


Category
Regular These event ids are mapped to Windows event ids. At each
Window object level, some event ids are mapped to some event names.
events For example the Clicked event, which triggers automatically
whenever the user clicks on a CommandButton.
Custom There are 75 custom events with event ids pbm_custom01 to
events pbm_custom75. When an user-defined event is defined and
mapped to the custom event, the script doesn't execute it
automatically - you need to explicitly execute the script. We'll
look at them in detail latter in the chapter.
Visual Basic There are 50 Visual Basic events with event ids pbm_vbxevent01
events to pbm_vbxevent50. These events are mapped from Visual Basic
specific events.

Typically, VBXevents ( Visual Basic events ) are used for VBX user objects,
to capture VBX events. With version 4.0, PowerBuilder supports OCX. Even
Visual Basic v4.0 moved to OCXes. PowerBuilder automatically defines OCX
events In the OLE control. We think, in the future versions, VBX events
might not be supported, since every thing is achieved with OCXs. We will
teach about OCX and OLE in later sessions.
Parameterized Events
With version 5.0, you can parameterize events. For example, prior to version
5.0, to access the SQL statement that is being send to the database you
need to call 'GetSQLPreview()' function in the 'SQLPreview' event. From version
5.0 onwards, you no longer need to call that function ( which became
obsolete ), instead you can use 'SQLSyntax' parameter of  'SQLPreview'
event. In addition to that, PowerBuilder also sends few other parameters
including the row number for the SQL statement, the SQL statements being
SELECT, UPDATE, DELETE, INSERT. Which means that in the 'Clicked' event,
you don't need to call 'GetClickedRow()' function, instead you can use the 'row'
parameter for the 'Clicked' event.

Before jumping onto the advanced stuff, I would like you to do the following.
Open the w_product_master window and go to the script editor for
dw_product DataWindow and go to the 'SQLPreview' event. Click on the
'Paste Parameters' DropDownListBox, you will find all the parameters to the
'SQLPreview' event ( as explained before ). Invoke the PowerBuilder online
help and select 'Contents' tab. Click on 'Controls' help topic and double-click
on 'DataWindow'. Go to the events option and read the help for 'SQLPreview'
event.

Event parameterization makes programming flexible with less function calls.


You can see the new interface for 'Events' dialog box
with "arguments" button next to each event name. ( To see 'Events' dialog
box, select 'Declare/User Events'from the menu, when in script painter. ) To
see how the parameters are declared for SQLPreview event, click on
the 'Arguments' button next to the 'SQLPreview' event. You can neither
change nor add parameters for the system defined events. By system
defined events I mean PowerBuilder defined events including VBX events,
pb_customXX events. All custom events, such as pb_customXX events have
two pre-defined parameters, i.e., wparam and lparam. All VBX events are
defined with no parameters. You can't change parameter list for the event
ids listed in the "Paste Event ID" List Box.

With version 5.0, PowerBuilder allows you to define an event without


mapping it to any event id. These are the only events for which you can
define parameters. If you don't map event ids, how does PowerBuilder
execute the events? Well, for those events at run-time, PowerBuilder
generates an internal id number dynamically and puts them in the message
queue.
Let's say, you define an event with parameters without mapping it to any
event id and referred to this event in your code. Later, you change your
mind and map this event to a custom event id. As explained before, any
custom event id have two parameters, so you expect to see them in
the 'Events Declaration' dialog box after re-mapping the event to a custom
event id . PowerBuilder doesn't display "wparam" and "lparam"
parameters, instead it still displays the arguments previously defined. You
won't get any error messages while coming out of the 'Events' dialog box,
but, you will get compilation errors while saving the object, that is if you are
referring to this event in the same object. To come out of this mess, simply
delete the event and re-define it and make sure to change the code that
refers to this event, before you save the object.

You can pass arguments to an event in three different ways:

by Value
by Reference
as Read-only

Pass by Value: When an argument is passed by value, PowerBuilder makes a


copy of the argument and sends that copy to the event. Changes to the
argument in the called event script will not be reflected in the calling script,
since, the called event is only changing the copy. As soon as the called event
completes the execution, copy of the argument is no longer in the memory.

/* Script for the clicked event for the CommandButton */


int li_counter
li_counter = 100

MessageBox( "li_counter value before event execution", li_counter )


Parent.Event ue_test( li_counter )
MessageBox( "li_counter value after event execution", li_counter )
/* Script for the ue_test event for the w_practice window
Arguments: pArgument1 Int By value
*/
MessageBox( "Value before changing in the event", pArgument1 )
pArgument1 = 200
MessageBox( "Value after change in the event", pArgument1 )

Return 0

In the above example, after executing the event, li_counter value is still 100
even though 200 is assigned to it in the called event script 'ue_test'. I will
explain different ways of executing the event script in the next topic.

Pass by Reference: When an argument is passed by reference, PowerBuilder


passes a pointer to the argument. That means any changes to the argument
in the called event script will reflect in the calling script. To see it, change
the argument definition in the above example from 'Pass by value' to 'Pass
by reference' and run the window again. PowerBuilder will display 200 after
executing 'ue_test' event. If you just want to refer to the argument in an
event, send by reference. This will be more efficient, since, only pointer are
passed instead of making a separate copy of the argument.

Pass as Read-Only: The third way of passing an argument is 'read-only'. This


method was introduced in version 5.0. As the name suggests, the argument
is read-only, you can't change the value of the argument in the called event.
Do You think so ? Well, not exactly. The name "read-only" is misleading.
What they mean by "read-only" is, that you can change the value of the
argument, but, you can't re-assign another object to this object. Here you
can change the object's attributes. ( You are not limited to sending
conventional data types as arguments, you can also pass PowerBuilder
objects as parameters to the events. ) I don't think you can test this method
of argument passing with conventional data type arguments. In practice,
this method is applicable to cases where you pass PowerBuilder objects as
arguments to events.

For testing purposes, declare an user-defined event


"ue_read_only_arg_test" for the window 'w_practice'. Don't map any event-
id to the "ue_read_only_arg_test" event. Specify arguments as shown in the
following picture. Specify "Integer" as the return value.

Type the following script in the "ue_read_only_arg_test" event.

/* Argument Name data type Pass By */


/* pWindow Window ReadOnly */

Int li_xValue
Window lWindow
lWindow = CREATE w_practice

/* This statement has no problem because we are just referring to the attribute */
li_xValue = pWindow.x 

/* This statement also has no problems, because we are just changing one of its attribute
*/
pWindow.x = 100

/* This statement generates compilation error, since we are assigning another window to
it, that means, we are telling PowerBuilder to point to another window */
pWindow = lWindow

Return 0

If you compile the above script, PowerBuilder compiler generates the


following error:
By assigning another window to pWindow, you are asking pWindow to map to lWindow, i.e., you are
changing the pointer of pWindow, which is not allowed.

In short,

Events can return a value including traditional data types and PowerBuilder objects.
You can define an user-defined event without mapping it to any pre-defined event-id.
You can define arguments to events that are not mapped to any pre-defined event-id.
The event arguments may be traditional data types or PowerBuilder objects.
You can pass arguments to the events 'by value', 'by reference' and as 'read-only'.
When an argument is passed by value, changes to the argument does not reflect in the
calling script.
When an argument is passed by reference, changes to the argument will reflect in the
calling script.
When an argument is passed as read-only, changes to the argument will reflect in the
calling script. You can't reassign the argument in the called event script.

Events and Return Values


With version 5.0, an event can return value from the event script. All event
ids that are listed in the "Paste Event ID", i.e., the pre-defined events are
defined as "Long" return value. For these events it is not necessary to code
"Return" statement in the event script, even though the declaration says
"Long" as the return value. If you execute mapped events which have no
code, the return value would be a NULL. If the event has script but has no
return statement, a 0 is returned. Even if you have comments in the script
and have no code, the return value would still be a 0.
However, for an unmapped event, you must return some value with the
"Return" statement, otherwise, you get compilation errors. That is because
it has to return some value.

You can't define unmapped events in previous versions of PowerBuilder. That


means events have to be mapped to one or other event ids. When you
migrate to version 5.0, errors are not generated while executing these
events, instead they return 0 if the event has script, and returns NULL if the
event has no script.

Triggering an Event
Events that are mapped to regular event ids are triggered automatically. For
example, clicking on a CommandButton automatically executes the script
written for its "Clicked" event ( pbm_bnclicked event id for the
CommandButton ). Sometimes, you may want to trigger the event
programmatically. For example, you may want to trigger the 'Sort' event in
the DataWindow control, if the user selects the 'ue_sort' option from the
popup menu of a DataWindow. To trigger an event, you need to use
theTriggerEvent(), and the syntax is:

ObjectName.TriggerEvent( Event, { WordParm }, { LongParm } )

"WordParm" and "LongParm" arguments are optional. All pre-defined events


are defined as enumerated data types under "trigevent". For example, for
"close" event, there's an enumerated data type "close!", for "activate" event,
it's "activate!" and so on. To trigger pre-defined events, you need to use
enumerated data types. The following examples trigger "close" and
"activate" events for the "w_script_practice" window.

Int li_retstat
li_retstat = w_script_practice.TriggerEvent( Close! )
If li_retstat <> 1 Then
//Error handling ...
End If

li_retstat = w_script_practice.TriggerEvent( Activate! )


If li_retstat <> 1 Then
//Error handling ...
End If

If triggering an user-defined event, use the event name within quotations.


The following example triggers "ue_save" event in "w_script_practice"
window.

Int li_retstat
w_script_practice.TriggerEvent( "ue_save" )
If li_retstat <> 1 Then
//Error handling ...
End If

If the specified event's script executes successfully, TriggerEvent() returns 1.


If no script exists or the specified event is invalid ( may be you forgot
defining that event or misspelled the event name ), -1 will be returned. We
always recommend checking of return values.

TriggerEvent() function
executes synchronously, i.e., the next command after
this command will not be executed until this command is executed
completely.

As shown in the above syntax, you can also send parameters to the event in
the TriggerEvent(). When you send parameters, they are stored in the
Message object. Message Object is explained in detail in the "Inter Object
Communication" section. For the time being just note that, Message object is
a global object and is available by default in all PowerBuilder applications. In
simple terms, the main purpose of this object is to store information which
are accessed from other objects. Parameters passed to the event in
the TriggerEvent() are available
in Message.StringParm andMessage.LongParm members.

There are limitations in the number of parameters you can pass for an event
through this function. That being two. Another disadvantage with this
function is that, the return value of the event can't be trapped. The return
value of this function is the success/failure of the function call itself, and not
the return code returned in the event script.

With version 5.0, another syntax is available for executing events and
functions. PowerSoft says that the new syntax is only an enhancement, and
not a replacement for the old syntax, but I am afraid it is not so. Once you
start using the new syntax, there are chances that you will not go back to
the old syntax again. The much talked about syntax is as follows:

{ObjectName.}{Type} {CallType} {When} &


Function/Event Name ({ ArgumentList})
The same syntax allows you to execute either an event or a function, just
specify keyword Function or Event in place of 'Type'. If you do not specify
anything, Function will be taken by default. CallType indicates whether it is a
static or a dynamic event, which we will explain in a moment. Whenindicates
whether you want to trigger or post the event/function. Similar to calling a
function, you always need to specify parenthesis after the event or function
name irrespective of the parameters. The following script triggers "ue_save"
event at the window.

/* Either lines trigger ' ue_save'


event at the window. */
Parent.Event Trigger ue_save()
Parent.Event ue_save()

The return value for the TriggerEvent() is always an integer. However, the


return value for this new syntax depends on the return value type declared
at the called event/function. If the event is returning a string value, you
need to assign the return value to a string variable. Even though it is good
practice to check the return value, assigning return values is not mandatory.

String ls_status
ls_status = Parent.EVENT STATIC TRIGGER ue_SendToMainFrame()
ls_status = Parent.EVENT TRIGGER ue_SendToMainFrame()
Parent.EVENT STATIC TRIGGER ue_SendToMainFrame()
Parent.EVENT TRIGGER ue_SendToMainFrame()

All the above statements are correct. The only limitation on return value
being, that the return value expression shouldn't return an array. CallType is
"static" by default. That means, compiler checks the presence of the calling
event or function and its return value type at the compilation time. If the
event or function doesn't exist, or the assigned returned value type is
incorrect, error will be generated.

Calling ancestor events is explained in "Inheriting a Window" section.

Triggering Events Dynamically


Sometimes, events/functions do not exist at compile time. Take the example
of writing a generic function ( as shown below ) which saves DataWindows in
a given window. Before saving each DataWindow, this function executes
"ue_presave" event before and "ue_postsave" after saving the DataWindow.
We expect the DataWindow in the passed window to have these events at
run-time. In situations like these, we can use theDYNAMIC keyword, so that
compiler doesn't check for the existence of the event or function and their
arguments & return types.
//Window iWindow
datawindow l_dw
integer li_NoOfControls, li_Counter, li_RetStatus
li_NoOfControls = UpperBound(iWindow.Control[])
For li_Counter = 1 to li_NoOfControls
Choose Case iWindow.Control[ li_Counter ].TypeOf()
Case DataWindow!
l_dw = iWindow.Control[ li_Counter ]
If l_dw.ModifiedCount() + l_dw.DeletedCount() > 0 Then
li_RetStatus = l_dw.Event DYNAMIC TRIGGER ue_PreSave()
If li_RetStatus <> 0 Then Return -100
li_RetStatus = l_dw.Update( True )
// Error Handling
l_dw.Event DYNAMIC ue_PostSave()
If li_RetStatus <> 0 Then Return -100
End If
Case Else
// Other code
End Choose
Next
Return 0

Calling events dynamically is slower than calling static event/functions. That


is because, a check is to be done at run-time for event/function existence.
So, use DYNAMIC keyword only when necessary .

What happens if an event doesn't exist at run-time when


using DYNAMICkeyword ? In this matter it works silently. It won't generate
any errors that abort the application, instead it returns -1 as the return
value. So, make sure you check for the return values.

Cascaded Events and Functions


The event/function syntax allows you to make nested event/function calls.
The return value of the first event/function must be an object and it
becomes the object  upon which the second event/function acts.

// instance variables
// int ii_hours
// String ii_YarnType

NonVisualObject lnc_object
nc_MachineObject lnc_MachObj
Long li_Prod

lnc_MachObj = Create nc_MachineObject


lnc_object = lnc_MachObj.Function Trigger &
Dynamic of_GetObject ( ii_no )

If NOT IsValid( lnc_object ) Then Return -100


li_Prod =.lnc_Object.Function Trigger Dynamic of_GetProd &
( ii_hours, ii_YarnType )
If li_Prod = 0 Then
// Error handling
End If
Destroy lnc_MachObj

The above example calculates production for different type of machines;


machine from different  vendors and of different makes have different
formulas for production calculation. Function call of_GetObject() at custom
class object nc_MachineObject returns appropriate custom class object
depending on the vendor and the make of the machine. The second
function of_GetProd() returns production for that machine depending on the
number of hours that machine ran and the type of the product.

// instance variables
// int ii_hours
// String ii_YarnType

nc_MachineObject lnc_MachObj
Long li_Prod

lnc_MachObj = Create nc_MachineObject


li_Prod = lnc_MachObj.Function Trigger Dynamic of_GetObject &
( ii_no ).of_GetProd( ii_hours, ii_YarnType )
If li_Prod = 0 Then
// Error handling
End If
Destroy lnc_MachObj

The above code does the same thing as the earlier code listing, using nested
function calls. As you can see here, you can't check if the returned object is
a valid object or not. Make sure to check for valid objects and for error
handling in the called objects.

If you use DYNAMIC keyword for the first event/function from left, it would


apply for all nested event/function calls. Another suggestion would be that if
you want to post event/function calls,  do it only at the last event/function
call.

Does TriggerEvent really trigger an event?


What happens when you use a  TriggerEvent()? What happens is that
PowerBuilder executes script for the specified event. Does it mean we are
really triggering the event? No, it's not. What does that mean ? Without
triggering how does the script written for an event get executed? Good
question. Before explanation, let's see an example.

Let's take a simple example of window "close" event. If you trigger it, what
you expect to happen? We expect, the window to close. In reality, that
doesn't happen. When calling TriggerEvent() or PostEvent() ( explained in the
next topic ), PowerBuilder puts the message at the top of PowerBuilder's
internal object queue and then executes it. In other words, PowerBuilder
does not place the message in the MS-Windows message queue. To test the
above theory, place a CommandButton in the w_script_practice window and
name it 'cb_event_test' and for the clicked event
write Parent.TriggerEvent(Close!). Write MessageBox("Hello!","I am in Window Close
Event") to the window's close event. Then run the window and click on the
button. Do you see the window closing when the button is clicked. No!, it
simply displays the message box.

To really close the window, we need to send a MS-Window's "close"


message to MS-Windows. We need to call Send(). The format is as follows:

Send( Handle, MessageNo, LowWord, Long )

Handle is
the handle of the window to which you want to send the message.
You can get the handle of the window by calling Handle().MessageNo is the
Windows message number.

Replace the script for cb_event_test with the following code and run the
window again. You get the expected results. The following code sends MS-
Windows's close message and closes the parent window.

Send ( Handle( Parent ), 16, 0, 0 )

The above code triggers MS-Window's "close" event, which in turn triggers
PowerBuilder window's "CloseQuery". If "CloseQuery" event is executed
successfully, PowerBuilder executes the "Close" event script and then it
closes the window.

CloseQuery event is always fired before window's Close event is fired.

How to find out what message number (16 in the example ) to send. For
that, select Declare/User Events from the menu in the window painter and
see what message is mapped to Close event i.e., "pbm_close". Windows
message names are nothing but "pbm" replaced by "WM", i.e., WM_CLOSE
in this case. We found the window message name, now how to find out
message no?

All Windows messages are listed in "Window.H" file. If you have Visual C++,
you will find it in "INCLUDE\WINUSER.H" file. The entry for WM_CLOSE looks
like:
#define WM_CLOSE 0x0010

The number you see in the above definition is in hexadecimal. Converting


this number from hexadecimal to decimal gives you 16. You can use MS-
Window's calculator for conversion, in the scientific mode; type the above
number in hexadecimal mode and choose decimal mode, you see the
decimal equivalent of the typed number. Sometimes, you may want to see
what events are occurring, in that case, you can use Visual C++'s "Spy++"
or Watcom's "Wspy" utilities.

This command executes synchronously, like TriggerEvent(). To do things


asynchronously, use the Post() function which has format similar to Send()

Posting an Event
Sometimes, you may want to execute an event asynchronously, i.e., the
current script shouldn't wait for the completion of the posted event
execution. In those cases, you need to use the PostEvent() function. The
format is same as TriggerEvent().

An example of where you could use the PostEvent() is, to populate


DataWindow while the window opens. You can do this in two ways:

You can write script in the window's open event. This works fine, but, for the
user, it means a delay in opening the window, since (s)he can't see the
window until the execution of it's open event. As an alternate, you can use
the PostEvent() function.

When PowerBuilder encounters this command, it simply posts the message


in the PowerBuilder's internal object message queue and starts executing
the command after PostEvent() function call. In the message queue, whenever
messages before the posted message is executed, PowerBuilder executes
the event specified in the PostEvent(). Typically, posted events are executed
at the end of the current script, however, it is not guaranteed. It all depends
on the messages pending in the message queue. In short, the current script
doesn't wait for the results of the event script execution, specified in
the PostEvent() function call.
You can also post events or functions with the new syntax, explained in the
previous topic, by using POST keyword in place of WHEN.

{ObjectName.}{Type} {CallType} {When} Function/Event


Name ({ ArgumentList})

Again, using PostEvent() function or POST keyword do not actually make the


events happen, instead, they simply execute the script for the specified
event. Use Post() for this purpose as explained in the "Choosing between
Events and Functions" topic. The syntax for Post() is similar to Send().

Summary
In this session you have learned about connecting to the database and
manipulating a DataWindow using PowerScript. You have also learned more
about events and functions. For a quick summary of this session,
browse PowerScript-db-operations.ppt ( a PowerPoint presentation ). The
application built by you till now, is a single window application. In the next
session you will be learning to create MDI applications.

Questions & Answers


What is the difference between TriggerEvent() and PostEvent()?

PowerBuilder executes TriggerEvent() in synchronous mode and PostEvent() in asynchronous


mode.

What is the difference between TriggerEvent() and Send()?

TriggerEvent() just executes the script for the specified event, where as, Send() executes the script
as well as it makes the specified event to really happen.

Is it possible to post a function?


Yes, it is possible to post a function with the new syntax provided with v5.0.

What will happen if you trigger a non-existing event ?

Except for the return code being a -1, nothing happens.

Triggering an event which doesn't return a return code, will return ______ return code.

0 ( ZERO )

Triggering an event which doesn't have script, will return ______ return code.

-1

What is the difference between passing an argument "By Value" and "By Reference"?

In case of "By Value", the changed value ( in the called event/function ) of the variable reflects in
the calling function/event. In case of "By Reference", the changed value ( in the called
event/function ) doesn't reflect in the calling event/function.

What is the difference between passing an argument "By Reference" and "Read-Only"?

Both are same, except for one difference. Assigning another object to the argument object is not
allowed, if the object is passed as "Read Only".

If you trigger a non-existing function, what will happen?

Results in run-time error.

An event id can be mapped to multiple events of an object. True/False?

False.

An event can be defined at an object without mapping it to an event id. True/False?

True.
Write the code to trigger "Close" event of "w_script_practice'. Write it by using old and new
Syntax.

Old Syntax: w_script_practice.TriggerEvent( Close! )

In the New Syntax, it would be: w_script_practice Event STATIC


Trigger Close(). However, this wouldn't work, since there is a conflict
with Close() which takes window as a parameter and Close! event which
takes no param. There is no problem in calling other events.
Write the code to trigger "ue_close" event that is defined at "w_script_practice'. Write using old
and new Syntax.

Old Syntax: w_script_practice.TriggerEvent( "ue_Close" )

New Syntax: w_script_practice.Event STATIC Trigger ue_Close()


How do you signal an error ?

Using SignalError() function.

Which object contains error information ?.

"Error" Object.

Whenever an error occurs, _______________ event at ________________ object gets triggered


automatically

SystemError, Application.

Explain the "Retrieve As Needed" property of DataWindow control.

Setting on the "Retrieve As Needed" property makes PowerBuilder bring data, that a DataWindow
control can display at any moment of time.

Explain the difference between "Query Mode" and "Prompt for Criteria".

Query Mode allows the user to specify query criteria on all the columns that are being displayed in
the DataWindow control, and has a tab order greater than Zero. Prompt for Criteria allows the
user to specify query criteria on selected columns ( set either through PowerScript,
usingModify() function, or set in the DataWindow painter ).
________________ function sets the value of a column in the DataWindow control.

SetItem()

________________ function returns the value of a string data type column in the DataWindow
control.

GetItemString()

________________ function returns the value of a "Date" data type column in the DataWindow
control.

GetItemDate()

The following two statements do the same thing. True/False

w_script_practice.TriggerEvent( Close! )
w_script_practice.TriggerEvent( close! )
True, because identifiers are case insensitive in PowerBuilder.

Exercises
Please complete the following exercise. We advise you not to download the
solution until you complete the exercise.

# Problem Description
1. Under normal conditions, the script written for ue_delete would work fine.
However, when the user adds a new blank row and tries to delete it, this
script neither prompts the user nor does anything. We would like you to fix
that bug, i.e, the user should be able to delete a blank row.

Tip: IsNull() function

Solution: - ex-9-1.srm
Home

You might also like