PB v9.0 PFC User's Guide
PB v9.0 PFC User's Guide
PowerBuilder®
9
DOCUMENT ID: 37779-01-0900-01
To order additional documents, U.S. and Canadian customers should call Customer Fulfillment at (800) 685-8225, fax (617) 229-9845.
Customers in other countries with a U.S. license agreement may contact Customer Fulfillment via the above fax number. All other
international customers should contact their Sybase subsidiary or local distributor. Upgrades are provided only at regularly scheduled
software release dates. No part of this publication may be reproduced, transmitted, or translated in any form or by any means, electronic,
mechanical, manual, optical, or otherwise, without the prior written permission of Sybase, Inc.
Sybase, the Sybase logo, AccelaTrade, ADA Workbench, Adaptable Windowing Environment, Adaptive Component Architecture,
Adaptive Server, Adaptive Server Anywhere, Adaptive Server Enterprise, Adaptive Server Enterprise Monitor, Adaptive Server
Enterprise Replication, Adaptive Server Everywhere, Adaptive Server IQ, Adaptive Warehouse, Anywhere Studio, Application
Manager, AppModeler, APT Workbench, APT-Build, APT-Edit, APT-Execute, APT-FORMS, APT-Translator, APT-Library, Backup
Server, BizTracker, ClearConnect, Client-Library, Client Services, Convoy/DM, Copernicus, Data Pipeline, Data Workbench,
DataArchitect, Database Analyzer, DataExpress, DataServer, DataWindow, DB-Library, dbQueue, Developers Workbench, Direct
Connect Anywhere, DirectConnect, Distribution Director, e-ADK, E-Anywhere, e-Biz Integrator, E-Whatever, EC Gateway, ECMAP,
ECRTP, eFulfillment Accelerator, Embedded SQL, EMS, Enterprise Application Studio, Enterprise Client/Server, Enterprise Connect,
Enterprise Data Studio, Enterprise Manager, Enterprise SQL Server Manager, Enterprise Work Architecture, Enterprise Work Designer,
Enterprise Work Modeler, eProcurement Accelerator, EWA, Financial Fusion, Financial Fusion Server, Gateway Manager, GlobalFIX,
ImpactNow, Industry Warehouse Studio, InfoMaker, Information Anywhere, Information Everywhere, InformationConnect,
InternetBuilder, iScript, Jaguar CTS, jConnect for JDBC, MainframeConnect, Maintenance Express, MDI Access Server, MDI Database
Gateway, media.splash, MetaWorks, MySupport, Net-Gateway, Net-Library, New Era of Networks, ObjectConnect, ObjectCycle,
OmniConnect, OmniSQL Access Module, OmniSQL Toolkit, Open Biz, Open Client, Open ClientConnect, Open Client/Server, Open
Client/Server Interfaces, Open Gateway, Open Server, Open ServerConnect, Open Solutions, Optima++, PB-Gen, PC APT Execute, PC
Net Library, Power++, power.stop, PowerAMC, PowerBuilder, PowerBuilder Foundation Class Library, PowerDesigner,
PowerDimensions, PowerDynamo, PowerJ, PowerScript, PowerSite, PowerSocket, Powersoft, PowerStage, PowerStudio, PowerTips,
Powersoft Portfolio, Powersoft Professional, PowerWare Desktop, PowerWare Enterprise, ProcessAnalyst, Rapport, Report Workbench,
Report-Execute, Replication Agent, Replication Driver, Replication Server, Replication Server Manager, Replication Toolkit, Resource
Manager, RW-DisplayLib, S-Designor, SDF, Secure SQL Server, Secure SQL Toolset, Security Guardian, SKILS, smart.partners,
smart.parts, smart.script, SQL Advantage, SQL Anywhere, SQL Anywhere Studio, SQL Code Checker, SQL Debug, SQL Edit, SQL
Edit/TPU, SQL Everywhere, SQL Modeler, SQL Remote, SQL Server, SQL Server Manager, SQL SMART, SQL Toolset, SQL Server/
CFT, SQL Server/DBM, SQL Server SNMP SubAgent, SQL Station, SQLJ, STEP, SupportNow, S.W.I.F.T. Message Format Libraries,
Sybase Central, Sybase Client/Server Interfaces, Sybase Financial Server, Sybase Gateways, Sybase MPP, Sybase SQL Desktop, Sybase
SQL Lifecycle, Sybase SQL Workgroup, Sybase User Workbench, SybaseWare, Syber Financial, SyberAssist, SyBooks, System 10,
System 11, System XI (logo), SystemTools, Tabular Data Stream, TradeForce, Transact-SQL, Translation Toolkit, UltraLite.NET,
UNIBOM, Unilib, Uninull, Unisep, Unistring, URK Runtime Kit for UniCode, Viewer, Visual Components, VisualSpeller, VisualWriter,
VQL, WarehouseArchitect, Warehouse Control Center, Warehouse Studio, Warehouse WORKS, Watcom, Watcom SQL, Watcom SQL
Server, Web Deployment Kit, Web.PB, Web.SQL, WebSights, WebViewer, WorkGroup SQL Server, XA-Library, XA-Server and XP
Server are trademarks of Sybase, Inc. 11/02
Unicode and the Unicode Logo are registered trademarks of Unicode, Inc.
All other company and product names used herein may be trademarks or registered trademarks of their respective companies.
Use, duplication, or disclosure by the government is subject to the restrictions set forth in subparagraph (c)(1)(ii) of DFARS 52.227-
7013 for the DOD and as set forth in FAR 52.227-19(a)-(d) for civilian agencies.
iv PowerBuilder
Contents
vi PowerBuilder
Contents
Subject This book describes how to use the PowerBuilder Foundation Class
Library (PFC).
Audience This book assumes that you:
• Are comfortable using Microsoft Windows applications
• Are currently developing applications with PowerBuilder and
understand the concepts and techniques described in the Applications
Techniques book
• Understand SQL and how to use your site-specific DBMS
This book has four parts, each for a specific group of PFC users:
Part Title Audience
1 PFC Overview All PFC users
2 PFC Class Library Design Object administrators
3 PFC Programming Application developers
4 PFC Tutorial All PFC users
Other sources of Use the Sybase Technical Library CD and the Technical Library Product
information Manuals web site to learn more about your product:
• The Technical Library CD contains product manuals and is included
with your software. The DynaText reader (included on the Technical
Library CD) allows you to access technical information about your
product in an easy-to-use format.
Refer to the Technical Library Installation Guide in your
documentation package for instructions on installing and starting the
Technical Library.
x PowerBuilder
PART 1 PFC Overview
About this chapter This chapter introduces the PowerBuilder Foundation Class Library
(PFC). It includes PFC basics, prerequisite PowerBuilder concepts,
object-oriented concepts, and a list of PFC components.
Contents
Topic Page
Understanding PFC 3
Understanding PowerBuilder 4
How PFC uses object orientation 8
How PFC uses the extension level 11
The PFC components 15
Understanding PFC
The PowerBuilder Foundation Class Library (PFC) is a set of
PowerBuilder objects that you customize and use to develop class
libraries. You can use these objects to provide corporate, departmental, or
application consistency. PFC also includes objects that you use as is for
utility purposes, such as debugging.
PowerBuilder objects PFC is written in PowerBuilder and delivered as PowerBuilder objects
with supporting PowerScript source code. It uses advanced PowerBuilder
object-oriented coding techniques, and features a service-oriented
design—that ensures that your application uses the minimum amount of
computer resources.
What this book This book explains PFC concepts (what things are and why you use them) as
contains well as usage information (how to program using PFC).
For more information For detailed information on PFC objects, instance variables, events, and
functions, see the PFC Object Reference.
Understanding PowerBuilder
You use PFC to create advanced, object-oriented PowerBuilder class libraries.
To get the most out of PFC and its object-oriented features, you must
understand PowerBuilder and its object-oriented features. This section gives an
overview of the PowerBuilder concepts with which you should be familiar.
4 PowerBuilder
CHAPTER 1 About the PowerBuilder Foundation Class Library
Functions PowerBuilder supports global functions and object functions. PFC performs
much of its processing through user-object functions. A function is a collection
of PowerScript statements that perform some processing. You pass zero or
more arguments to a function, and it may return a value.
For complete information on PFC object functions, see the PFC Object
Reference.
Events and user Windows, user objects, and controls each have a predefined set of events. PFC
events extends this by defining user events for many PFC objects. Events can accept
arguments and may return a value.
There are three types of PFC events:
This type of event Executes when the user performs
Predefined PowerBuilder An action that causes the operating system to invoke the
events event
Predefined user event An action (such as selecting a menu item) that causes
PFC to trigger the user event
Empty user events (you An action (such as selecting a menu item) that causes
add PowerScript code) PFC to trigger the user event
You can also add code to call, trigger, or post predefined events and user events.
In this book
Unless otherwise qualified, this book uses the word event to refer to all three
types.
Functions and events Functions and events are similar in many ways: they may accept arguments and
compared return values; they both consist of PowerScript statements; they can be called,
triggered, and posted. But there are some differences between functions and
events:
Feature Functions Events
Call to nonexistent Invoking a nonexistent Invoking a nonexistent event
method function at runtime produces with TriggerEvent yields a
an error return value of -1
Processing of Functions override ancestor Events can extend or override
ancestor script processing (although they ancestor processing
can call ancestor functions
using the Super keyword)
6 PowerBuilder
CHAPTER 1 About the PowerBuilder Foundation Class Library
Object-oriented programming
Object-oriented programming tools support three fundamental principles:
inheritance, encapsulation, and polymorphism.
Inheritance Inheritance means that objects can be derived from existing objects, with
access to their visual component, data, and code. Inheritance saves coding
time, maximizes code reuse, and enhances consistency.
Encapsulation Encapsulation (also called information hiding) means that an object contains
its own data and code, allowing outside access as appropriate. PFC implements
encapsulation as follows:
• PFC defines object functions and instance variables as public or protected,
depending on the desired degree of outside access. PFC does not use the
private access level.
• For readable instance variables, PFC generally provides an
of_Getvariablename function.
• For Boolean instance variables, PFC generally provides an
of_Isvariablename function.
• For modifiable instance variables, PFC generally provides an
of_Setvariablename function.
• In certain cases, PFC defines an instance variable as public, allowing you
to access it directly.
Polymorphism Polymorphism means that functions with the same name behave differently
depending on the referenced object and the number of arguments. PFC
supports the following types of polymorphism:
8 PowerBuilder
CHAPTER 1 About the PowerBuilder Foundation Class Library
Services PFC uses windows, standard class user objects, and custom class user objects
to implement an object-oriented design by isolating related types of processing
(such as DataWindow caching, row selection, and window resizing). These
related groups of processing are called services. Most services are
implemented as custom class user objects. PFC service types include:
Service category Service
Application services Application preferences
DataWindow caching
Debug
Error message
Most recently used object
Security
Transaction registration
Window services Base
Preferences
Sheet manager
Status bar
DataWindow services Base
DataWindow resize
Drop-down search
Filter
Find
Linkage
Multitable update
Properties
Querymode
Report
Required column
Resize
Row manager
Row selection
Sort
DataStore services Base
Multitable update
Print preview
Report
10 PowerBuilder
CHAPTER 1 About the PowerBuilder Foundation Class Library
For more information on PFC service types and how to use them, see Chapter
4, “Using PFC Services”.
A separate extension PFC implements an extension level in all its inheritance hierarchies. All
level extension objects reside in separate PBLs, which are not affected when you
upgrade to the latest version:
Contents Ancestor level Extension level
Application and global services PFCAPSRV.PBL PFEAPSRV.PBL
DataWindow services PFCDWSRV.PBL PFEDWSRV.PBL
Visual and standard class user PFCMAIN.PBL PFEMAIN.PBL
objects
Utility services PFCUTIL.PBL PFEUTIL.PBL
Window services PFCWNSRV.PBL PFEWNSRV.PBL
Objects in the ancestor-level libraries contain all instance variables, events, and
functions; objects in the extension-level libraries are unmodified descendants
of corresponding objects in the ancestor library. But through inheritance they
have access to the ancestor’s instance variables, events, and functions.
To see the instance variables, events, and functions available to a descendent
object, use the PowerBuilder Browser.
Using an extension level has two major advantages:
• You can add site-, department-, and application-specific logic to extension
level objects
• The extension PBLs are not affected when upgrading to the latest version
Obsolete objects
The PFCOLD.PBL library contains obsolete objects. If you have an existing
PFC application, you may need to add this library to your application target
library list.
12 PowerBuilder
CHAPTER 1 About the PowerBuilder Foundation Class Library
What you do You customize your PFC application by modifying objects at the extension
level. You do not modify ancestor objects. Your application’s objects use
extension-level user objects and inherit from extension-level windows:
For example, the ancestor for the DataWindow selection service object is
pfc_n_cst_dwsrv; the extension-level descendant is n_cst_dwsrv.
Pfc_n_cst_dwsrv contains all code for the service; n_cst_dwsrv is an
unmodified descendant to which you may add application-specific instance
variables and code.
PFC-defined user events PFC-defined user events also use the pfc_ prefix.
This makes it easy for you to distinguish your application’s user events from
PFC’s user events.
Sample extension PFC’s object hierarchies allow you to add extension logic at each level.
scenario Because pfc_w_sheet inherits from w_master, for example, instance variables,
functions, and events you add to w_master are available to all descendent
windows:
Adding extension The extension layer provides for reusability within an application and
levels effectively insulates individual applications from PFC upgrades. But large
installations that have department-wide (and perhaps corporate-wide)
standards must extend this strategy further to implement additional levels
containing corporate and departmental standards and business rules.
If you are using PFC in an organization, you may want to create additional
extension levels to contain corporate or departmental variables, events, and
functions. Applications still use objects in PFC extension libraries but now
have access to additional ancestor instance variables, events, and functions:
14 PowerBuilder
CHAPTER 1 About the PowerBuilder Foundation Class Library
The PFC database PFC ships with the pfc.db local database. This database contains the following
tables:
Table Usage
Messages Error message service
Security_apps Security service
Security_groupings Security service
Table Usage
Security_info Security service
Security_template Security service
Security_users Security service
The PFC local database is intended for developer use only. If your application
uses the error message service or security service, you should copy these tables
to a server database, as described in “Deploying database tables” on page 229.
The PFC code Use the PFC code examples to view PFC objects and services in action and
examples learn how to code and implement most common PFC functionality. The PFC
code example interface provides extensive cross-reference and usage
information.
The PFC sample Use PEAT (the PFC sample application) to see an example of PFC used in a
application project estimation and tracking system.
16 PowerBuilder
PART 2 PFC Class Library Design
About this chapter This chapter explains how to use PFC as the basis for your own class
library.
Contents
Topic Page
Using PFC to design a class library 19
Choosing an extension strategy 20
Defining a new service 24
20 PowerBuilder
CHAPTER 2 Designing a Class Library
Naming standards
You should give objects in the intermediate extension level a standard prefix
that reflects their usage. For example, if the intermediate extension level
contains additional class library functionality, use classlib_ as the prefix; if the
intermediate extension level contains corporate extensions, use corp_ as the
prefix.
What you do You add, modify, and extend PFC through objects in the intermediate extension
level.
To implement an intermediate extension level, you can use the Library
Extender or create intermediate extension level objects manually.
22 PowerBuilder
CHAPTER 2 Designing a Class Library
Where to define it
If you are using the existing PFC extension level, define your new service in
one or more separate PBLs.
If you are creating an extension level, define your ancestor object in the
intermediate extension level (the corporate level in the example ahead) and
your extension level object in the PFC extension level.
24 PowerBuilder
CHAPTER 2 Designing a Class Library
2 Save this user object in the intermediate extension level. For example, if
you have an intermediate level for corporate objects, it might be named
corp_n_cst_dwsrv_autorowinsert.
3 Create a descendent user object in the extension level. For example,
n_cst_dwsrv_autorowinsert. Add no code to this object.
4 Add an instance variable to the main object in the intermediate extension
level. This variable should use the data type of the extension level object.
For example, update corp_u_dw by adding an inv_autorowinsert instance
variable of type n_cst_dwsrv_autorowinsert.
5 Add a function to the main object in the intermediate extension level. This
function should create or destroy an instance of your user object as
specified by a passed boolean argument. For example,
of_SetAutoRowInsert might create or destroy an instance of
n_cst_dwsrv_autorowinsert as follows:
// Function name: of_SetAutoRowInsert
// Arguments: ab_switch (boolean by value)
// Returns: 1 = Success
// 0 = Already instantiated
// -1 = Argument was NULL
IF IsNull(ab_switch) THEN
Return -1
END IF
IF ab_switch THEN
IF IsNull(inv_autorowinsert) OR &
NOT IsValid(inv_autorowinsert) THEN
inv_autorowinsert = CREATE n_cst_autorowinsert
// of_SetRequestor = defined in ancestor
inv_autorowinsert.of_SetRequestor(this)
Return 1
END IF
ELSE
IF IsValid(inv_autorowinsert) THEN
DESTROY inv_autorowinsert
Return 1
END IF
END IF
Return 0
6 Add code to the Destructor event of the main object in the intermediate
extension level. This code should destroy your user object:
this.of_SetAutoRowInsert(FALSE)
7 Add code as necessary to events in the main object. This code should call
events on the service object, if enabled. For example, the automatic row
insertion service might add the following code to the RowFocusChanging
event:
IF IsValid(inv_autorowinsert) THEN
inv_autorowinsert.Event corp_FocusChanging &
(currentrow, newrow)
END IF
26 PowerBuilder
PART 3 PFC Programming
About this chapter This chapter explains basic PFC programming practices and tells you how
to get started with a PFC application.
Assumptions
This chapter and all remaining chapters in this manual assume an
intermediate extension level strategy, which allows the developer to
modify and extend objects in the PFC extension level.
Contents
Topic Page
Setting up the application manager 29
Building applications 33
Using attribute objects 38
Using PFC constants 40
The message router 41
Transaction management with PFC 43
Calling ancestor functions and events 45
Adding online Help to an application 46
Installing PFC upgrades 47
PFCOLD.PBL
If your application uses obsolete PFC objects from a previous release of
PFC, include PFCOLD.PBL in the library list.
2 From the Application painter, display the Variable view and declare a
global variable, gnv_app, of type n_cst_appmanager:
n_cst_appmanager gnv_app
30 PowerBuilder
CHAPTER 3 PFC Programming Basics
10 Add code to the pfc_Open user event to open your application’s initial
window (typically the frame window), optionally including a call to the
of_Splash function, which displays a splash screen.
11 (Optional) Add code to the pfc_PreAbout, pfc_PreLogonDlg, and
pfc_PreSplash events to customize elements of the About box, logon
dialog box, and splash screen.
12 (Optional) Add code to the pfc_Idle, pfc_ConnectionBegin, and
pfc_ConnectionEnd events. If so:
• Call pfc_Idle from the application’s Idle event.
• Call pfc_ConnectionBegin from the application’s ConnectionBegin
event.
• Call pfc_ConnectionEnd from the application’s ConnectionEnd
event.
13 Save n_cst_appmanager.
ls_inifile = gnv_app.of_GetAppIniFile()
IF SQLCA.of_Init(ls_inifile,"Database") = -1 THEN
Return -1
END IF
// as_userid and as_password are arguments
// to the pfc_Logon event
SQLCA.of_SetUser(as_userid, as_password)
IF SQLCA.of_Connect() = -1 THEN
Return -1
ELSE
gnv_app.of_SetUserID(as_userid)
Return 1
END IF
32 PowerBuilder
CHAPTER 3 PFC Programming Basics
Building applications
Building MDI To build an MDI application with PFC, use the w_frame and w_sheet windows
applications as the ancestors for your frame and sheet windows. To define events, functions,
and instance variables for all your application’s sheets, add them to w_sheet.
You must also define menu items for all sheet windows in an ancestor sheet
menu (m_master, m_frame, or an application-specific sheet-menu ancestor,
depending on your menu strategy).
For information on the strategies you can use to implement menus under PFC,
see “Using menus with PFC” on page 201.
Message.StringParm = "w_products"
lnv_menu.of_SendMessage(this, "pfc_Open")
2 Add code to the w_frame pfc_Open event that accesses
Message.StringParm and opens the specified sheet window:
String ls_sheet
w_sheet lw_sheet
ls_sheet = Message.StringParm
OpenSheet(lw_sheet, ls_sheet, this, 0, Layered!)
Building SDI To build an SDI application with PFC, use the w_main window as the ancestor
applications for your main windows. To implement events, functions, and instance variables
so they are available in all windows, add them to w_main.
If your windows use menus, you must also define menus for each window.
For information on the strategies you can use to implement menus under PFC,
see “Using menus with PFC” on page 201.
34 PowerBuilder
CHAPTER 3 PFC Programming Basics
Autoinstantiated objects
Certain PFC objects use PowerBuilder’s autoinstantiate feature. These
objects have no Set functions; PowerBuilder instantiates them
automatically when you declare them as variables.
this.inv_sort.of_SetColumnNameSource &
(this.inv_sort.HEADER)
this.inv_sort.of_SetUseDisplay(TRUE)
this.inv_sort.of_SetColumnHeader(TRUE)
this.inv_sort.of_SetStyle &
(this.inv_sort.DRAGDROP)
Function overloading PFC uses function overloading to provide a rich,
flexible application programming interface. It implements function
overloading in two ways:
• Multiple syntaxes Multiple functions contain arguments that use
different data types or are in a different order. This allows PFC to handle
many types of data in function arguments
• Optional arguments Multiple functions contain an increasing number
of arguments with the same data types and in the same order. This allows
PFC to provide defaults for commonly used arguments
Programming using PFC includes precoded events and user events, which perform processing to
PFC events implement PFC services. It also includes empty user events, which allow you
to add application-specific code to perform application-specific tasks.
All events have public access and you can use dot notation to call them.
Using precoded PFC includes extensive precoded functionality. This means that by enabling a
events and user PFC service, PFC objects detect the enabled service and perform the
events
processing defined in the precoded events.
An example of a precoded event is the u_dw Clicked event, which calls certain
DataWindow service functions if they are enabled.
You can extend these events; do not override them.
For information on accessing the return value from an ancestor event, see
“Calling ancestor functions and events” on page 45.
36 PowerBuilder
CHAPTER 3 PFC Programming Basics
Using empty user PFC includes empty user events into which you can add application-specific
events code. Many of these events are triggered by menu items, using the message
router. Others are meant to be triggered by application-specific code.
An example of an empty user event is the u_dw pfc_Retrieve event, to which
you add logic that retrieves rows:
Return this.Retrieve()
For complete information on PFC user events, see the PFC Object Reference.
How PFC uses events When using events in the context of services, PFC typically behaves as
follows:
1 Within the event on the requestor object, call the corresponding event on
the service object, passing arguments as appropriate. For example, the
u_dw Clicked event calls the n_cst_dwsrv_sort pfc_Clicked event,
passing the x position, y position, row, and DW object (that is, the
arguments to the DataWindow Clicked event).
2 The event on the service object performs the required action, calling other
object functions as appropriate. For example, the n_cst_dwsrv_sort
pfc_Clicked event performs extensive processing, including calls to
n_cst_dwsrv_sort functions.
Using PFC pre-event PFC includes many pre-event processes, to which you add code that
processes customizes or extends the functionality of the associated event. For example,
you add code to the pfc_PreRMBMenu event to control the items that appear
in a pop-up menu. Other events that feature pre-event processing include:
pfc_PreAbout
pfc_PreClose
pfc_PreLogonDlg
pfc_PreOpen
pfc_PrePageSetupDlg
pfc_PrePrintDlg
pfc_PreRestoreRow
pfc_PreSplash
pfc_PreToolbar
pfc_PreUpdate
38 PowerBuilder
CHAPTER 3 PFC Programming Basics
40 PowerBuilder
CHAPTER 3 PFC Programming Basics
Coding conventions
The PFC convention is to code constants in all caps.
Built-in debugging The message router includes built-in debugging messages to provide error
messages information.
How When the user selects a menu item, the item’s Clicked event script calls the
of_SendMessage menu’s of_SendMessage function, passing the name of the user event to be
works
called. Of_SendMessage calls the n_cst_menu of_SendMessage function,
which calls the window’s pfc_MessageRouter event, which in turn calls the
specified user event.
Of_SendMessage calls the pfc_MessageRouter user event differently
depending on whether the application is MDI or SDI:
How pfc_ The pfc_MessageRouter user event calls the passed user event in the window,
MessageRouter works the active control, and the last active DataWindow:
42 PowerBuilder
CHAPTER 3 PFC Programming Basics
v To use n_tr:
1 If you are using a Transaction object other than SQLCA, create it.
This example assumes an itr_security instance variable of type n_tr.
itr_security = CREATE n_tr
2 Initialize the ib_autorollback instance variable, which specifies what to do
if the application closes (or the object is otherwise destroyed) while the
transaction is still connected:
itr_security.of_SetAutoRollback(FALSE)
ls_inifile = gnv_app.of_GetAppIniFile()
IF SQLCA.of_Init(ls_inifile,"Database") = -1 THEN
MessageBox("Database", &
"Error initializing from " + ls_inifile)
HALT CLOSE
END IF
4 Connect to the database by calling the of_Connect function:
IF SQLCA.of_Connect() = -1 THEN
MessageBox("Database", &
"Unable to connect using " + ls_inifile)
HALT CLOSE
44 PowerBuilder
CHAPTER 3 PFC Programming Basics
ELSE
gnv_app.of_GetFrame().SetMicroHelp &
("Connection complete")
END IF
5 Call n_tr functions as needed.
Use the following syntax to call an ancestor event, passing arguments and
receiving a return code:result = Super::Event eventname ( arguments ... )
Use the following syntax to call an ancestor function, passing arguments and
receiving a return code:result = Super::Function functionname ( arguments ... )
This example overrides the u_dw pfc_Update event, writing to an update log if
the ancestor event processes successfully:
Integer li_return
46 PowerBuilder
CHAPTER 3 PFC Programming Basics
2 Determine your current version. You can find the current version at the top
of the current PFC readme.txt file or in instance variables defined in
pfc_n_cst_debug. The version is in the format
majorrevision.minorrevision.fixesrevision.
3 Run the install procedure, placing the PFC PBLs in the current PFC
directory and overwriting the current PFC ancestor PBLs.
4 Merge existing extension objects with new extension objects. Review the
newly installed readme.txt file to see a list of new extension objects. There
are two methods of merging existing extension objects with new extension
objects:
• Copy new objects to customized extension PBLs Copy each
new object from the newly installed PFC extension level PBL to your
customized extension PBL. Then copy the customized extension
PBLs back to their original directory, overwriting the newly installed
PFC extension PBLs.
• Copy existing objects to the new PFC extension PBL Copy all
objects from the customized extension PBLs to the appropriate newly
installed PFC extension PBL.
5 Start PowerBuilder.
6 Adjust the application target library list if necessary.
7 Perform a full rebuild of the target.
48 PowerBuilder
CH A PTE R 4 Using PFC Services
About this chapter This chapter explains PFC services and how to use them.
Contents
Topic Page
Application services 49
DataWindow services 63
Window services 89
Menu service 95
Resize service 96
Conversion service 98
Date/Time service 99
File service 101
INI file service 102
Numerical service 103
Platform service 105
Selection service 106
SQL parsing service 108
String-handling service 109
Metaclass service 111
Logical unit of work service 111
List service 114
Timing service 126
Application services
PFC provides the following application services:
DataWindow caching
Debugging
Error
Application preference
Most recently used object
Security
Transaction registration
You control application services through n_cst_appmanager, the application
manager. Use application manager functions to enable and disable application
services. Because they are scoped to the application manager, which you define
as a global variable, application services are available from anywhere within
your application.
50 PowerBuilder
CHAPTER 4 Using PFC Services
Debugging service
Overview The debugging service automatically displays messages when PFC encounters
conditions that indicate an error.
The PFC message router uses the debugging service to control the display of
error messages when a passed event does not exist.
Usage Use the debugging service to help you solve problems in the PFC development
environment.
52 PowerBuilder
CHAPTER 4 Using PFC Services
54 PowerBuilder
CHAPTER 4 Using PFC Services
You must write To use the MRU service, you must extend the following window events in all
processing code windows that are to display on the file menu as MRU objects:
• Pfc_MRUProcess Add code that uses the passed MRU information to
open the specified window
• Pfc_PreMRUSave Add code that saves MRU information
• Pfc_MRURestore Add code that restores MRU information
Use IDs to identify You specify IDs to identify windows or groups of windows that appear together
groups of windows on the file menu. By using IDs you can restrict and customize MRU display.
For example, when displaying a particular sheet, you might want to restrict
MRU display to instances of that sheet only. In other applications, you might
want all sheets to display the same MRU items.
Integration with PFC The PFC m_master menu includes five MRU items at the end of the File menu.
menus You can add more MRU items if necessary.
If your application uses non-PFC menus, use m_master as a model in creating
your own MRU menu items.
// Check parameters.
IF IsNull(ai_row) THEN
Return -1
END IF
IF NOT IsValid(gnv_app.inv_mru) THEN
Return -1
END IF
// Retrieve row from DataStore.
gnv_app.inv_mru.of_GetItem &
(ai_row, lnv_mruattrib)
// Get the MDI frame, if necessary.
lnv_menu.of_GetMDIFrame(this.menuid, lw_frame)
OpenSheet(lw_window, &
lnv_mruattrib.is_classname, lw_frame)
Return 1
5 Extend the pfc_PreMRUSave event in each window that uses the MRU
service. In this event, populate the n_cst_mruattrib object with the ID,
classname, key, item text, and MicroHelp to be saved:
anv_mruattrib.is_id = "myapp"
anv_mruattrib.is_classname = this.ClassName()
anv_mruattrib.is_menuitemname = this.Title
anv_mruattrib.is_menuitemkey = this.ClassName()
56 PowerBuilder
CHAPTER 4 Using PFC Services
anv_mruattrib.is_menuitemmhelp = &
"Opens " + this.Title
Return 1
6 Extend the pfc_MRURestore event in each window that uses the MRU
service. In this event, set the ID of the information you want to display on
the menu:
If IsValid(gnv_app.inv_mru) Then
Return gnv_app.inv_mru.of_Restore("myapp", This)
End If
7 Call the pfc_MRUSave event to save MRU information. You can call this
event when the window opens, when information is saved, or when the
window closes (this example is from the pfc_PreOpen event):
this.Event pfc_MRUSave()
If you use the w_message dialog box, you have additional options:
• User input and print buttons The user can print messages and can
optionally add comments (this is especially useful when logging messages
and when using the automatic e-mail notification feature)
• Automatic close The w_message dialog box will close automatically
after a specified number of seconds
W_message bitmaps
If you use the w_message dialog box, the bitmaps it uses must be available at
execution time.
Usage Use the error service to handle all of your application’s message and error
handling. If you are keeping messages in a database, you can either use the
messages tables in PFC.DB or pipe it to your application’s database.
58 PowerBuilder
CHAPTER 4 Using PFC Services
3 (Optional) Specify the name of the log file (to disable logging, call
of_SetLogFile passing an empty string):
this.inv_error.of_SetLogFile &
("c:\workingdir\errlog.txt")
4 (Optional) Specify the user ID (used in message logging):
this.inv_error.of_SetUser &
(this.of_GetUserID())
5 (Optional) Specify the types of messages for which the error service will
provide automatic notification and logging:
this.inv_error.of_SetNotifySeverity(5)
this.inv_error.of_SetLogSeverity(4)
6 (Optional) If your application uses the error service’s automatic
notification feature, specify the current user’s e-mail ID and password.
Also specify the e-mail IDs of the users to be notified automatically. This
example assumes a mechanism for storing e-mail IDs and user passwords:
this.inv_error.of_SetNotifyConnection &
(ims_mailsess)
this.inv_error.of_SetNotifyWho(is_autonotify)
N_cst_appmanager pfc_Open
The steps listed above can all be coded in the n_cst_appmanager pfc_Open
event.
ls_parms[1] = "logfile.txt"
ls_parms[2] = "c:\windows\system"
3 Call of_Message, passing the array:
gnv_app.inv_error.of_Message("EIS1030", ls_parms)
PFC displays the message, replacing the first % with the first element in
the ls_parms array and the second % with the second element in the
ls_parms array.
Security service
Overview PFC’s security feature can handle many of your application’s security needs. It
includes administrative components and a runtime security object,
n_cst_security.
Usage To use the PFC security system, you must first define users and groups,
associate them with windows, menus, user objects, and controls, and then add
code to your application.
60 PowerBuilder
CHAPTER 4 Using PFC Services
N_cst_appmanager pfc_Open
The steps listed above can all be coded in the n_cst_appmanager pfc_Open
event.
6 Disconnect from the database and destroy the Transaction object when the
application closes. This example might be coded in the n_cst_appmanager
pfc_Close event:
DISCONNECT using itr_sec;
Destroy itr_sec
7 In the Open or pfc_PreOpen events of windows for which you want to
apply security, call the of_SetSecurity function:
IF NOT &
gnv_app.inv_security.of_SetSecurity(this) THEN
MessageBox("Security", &
"Unable to set security")
Close(this)
END IF
v To register a transaction:
• Call the n_cst_trregistration of_Register function:
gnv_app.inv_trregistration.of_Register(SQLCA)
62 PowerBuilder
CHAPTER 4 Using PFC Services
li_max = &
this.inv_trregistration.of_GetRegistered &
(ltr_trans)
2 Loop through the n_tr array, committing and destroying transactions as
appropriate:
FOR li_count = 1 to li_max
COMMIT using ltr_trans[li_count];
DESTROY ltr_trans[li_count]
NEXT
DataWindow services
Most production-strength PowerBuilder applications make intense use of
DataWindow controls. PFC provides a wide variety of DataWindow services
that you can use to add production-strength features to an application. Many of
these services require little or no coding on your part.
PFC implements DataWindow services through a set of custom class user
objects that descend from a common ancestor. The ancestor object contains
functions, events, and instance variables that are required by multiple services.
Each DataWindow service contains additional functions, events, and instance
variables.
Accessing To access DataWindow services, you create DataWindow objects that are
DataWindow services based on the u_dw user object. U_dw contains:
• Functions to enable and disable DataWindow services
• Instance variables that allow you to reference each service’s functions,
events, and instance variables (this type of instance variable is called a
reference variable)
• Precoded events and user events that call the DataWindow service’s
functions and events
• Empty user events to which you add code to perform application-specific
processing
Enabling DataWindow Each DataWindow control enables only the required DataWindow services.
services This minimizes application overhead.
The following table lists DataWindow services and how they are implemented:
DataWindow service Implementation
Basic DataWindow service (ancestor for n_cst_dwsrv
all other services)
Drop-down search service n_cst_dwsrv_dropdownsearch
Filter service n_cst_dwsrv_filter
Find and replace service n_cst_dwsrv_find
Linkage service n_cst_dwsrv_linkage
Multitable update service n_cst_dwsrv_multitable
Print preview service n_cst_dwsrv_printpreview
DataWindow property service n_cst_dwsrv_property
Querymode service n_cst_dwsrv_querymode
Reporting service n_cst_dwsrv_report
Required column service n_cst_dwsrv_reqcolumn
DataWindow resize service n_cst_dwsrv_resize
Row management service n_cst_dwsrv_rowmanager
Row selection service n_cst_dwsrv_rowselection
Sort service n_cst_dwsrv_sort
64 PowerBuilder
CHAPTER 4 Using PFC Services
DataStore services
This service is available to the n_ds DataStore via the n_cst_dssrv user object.
li_return = &
dw_emplist.inv_base.of_PopulateDDDWs()
gnv_app.of_GetFrame().SetMicroHelp &
(String(li_return) + " DDDW columns
refreshed")
66 PowerBuilder
CHAPTER 4 Using PFC Services
Filter service
Overview The PFC filter service allows you to provide easy-to-use filter capabilities in a
DataWindow.
Use this service to add filter capabilities to your application.
PFC enables the filter service through the n_cst_dwsrv_filter user object.
Usage The filter service displays Filter dialog boxes automatically. All you do is
enable the service and specify the filter style you want. You can choose among
three styles of filter dialog boxes:
• Default PowerBuilder Filter dialog box:
68 PowerBuilder
CHAPTER 4 Using PFC Services
70 PowerBuilder
CHAPTER 4 Using PFC Services
Linkage service
Overview The PFC linkage service helps you to create master/detail windows and other
types of windows that require coordinated processing.
The linkage service contains the following features:
• Linkage style Controls whether detail DataWindows retrieve rows,
filter rows, or scroll to the appropriate row
• Update style Controls how the linkage service updates DataWindows
(top-down, bottom-up, top-down then bottom-up, bottom-up then top-
down, or a developer-specified custom update)
• Confirm on row change When the master changes rows, this option
displays a confirmation dialog if modifications made to detail
DataWindows will be lost
• Confirm on delete Displays a confirmation dialog when the user deletes
rows
• Cascading key changes The linkage service automatically updates
detail DataWindows when you change a key value on the master
• Delete style When you delete a master row, this option specifies
whether the linkage service deletes detail rows, discards detail rows, or
leaves them alone
• Extended update Allows you to integrate other controls (such as
ListViews, TreeViews, and DataStores) into the default save process
The linkage service is completed integrated with n_cst_luw and with the
w_master pfc_Save process.
PFC enables the linkage service through the n_cst_dwsrv_linkage user object.
Usage You can use the linkage service to coordinate any type of processing among
DataWindows. However, the most common use is for master/detail processing.
72 PowerBuilder
CHAPTER 4 Using PFC Services
ELSE
dw_master.SetFocus( )
END IF
Retrieving rows
If the linkage service refreshes detail rows via retrieval, you only need to code
a Retrieve function for the master DataWindow. With the filter and scroll
options, you must also code Retrieve functions in detail DataWindows.
DataStore services
This service is available to the n_ds DataStore via the n_cst_dssrv_multitable
user object.
Usage Use this service when you need to update rows for a DataWindow that contains
data from more than one table. When you call the w_master pfc_Save event,
PFC updates all specified tables in all DataWindows on the window.
74 PowerBuilder
CHAPTER 4 Using PFC Services
dw_project.inv_multitable.of_Register &
("project", ls_projcols)
dw_project.inv_multitable.of_Register &
("task", ls_taskcols)
DataStore services
This service is available to the n_ds DataStore via the
n_cst_dssrv_printpreview user object.
Usage Use this service to provide print preview capabilities in your applications.
Users enter print preview mode by selecting File>Print Preview from the menu
bar.
76 PowerBuilder
CHAPTER 4 Using PFC Services
ls_cols[1] = "emp_dept_id"
ls_cols[2] = "emp_id"
dw_emplist.inv_querymode.of_SetQueryCols(ls_cols)
When you call of_SetEnabled, the query mode service protects ineligible
columns.
Reporting service
Overview The PFC reporting service allows you to provide enhanced viewing and
printing capabilities in an application’s DataWindows.
Many of this service’s functions provide the option of either executing the
DataWindow Modify function or returning Modify syntax for use as input to
your own Modify function. If you code more than two consecutive report
service functions, consider returning the Modify syntax, concatenating the
strings and issuing the Modify function from within your own code.
78 PowerBuilder
CHAPTER 4 Using PFC Services
DataStore services
This service is available to the n_ds DataStore via the n_cst_dssrv_report user
object.
String ls_return
Integer li_return
Boolean lb_vertical
Border lbo_border[ ]
lb_vertical = TRUE
ls_dws[1] = "d_employee"
ls_dws[2] = "d_benefits"
ls_trailfooter[1] = "No"
ls_trailfooter[2] = "Yes"
ls_slide[1] = "AllAbove"
ls_slide[2] = "AllAbove"
lbo_border[1] = Lowered!
lbo_border[2] = Lowered!
li_Return = &
dw_composite.inv_report.of_CreateComposite &
(ls_dws, lb_vertical, ls_trailfooter, &
ls_slide, lbo_border)
IF li_Return = 1 THEN
dw_composite.SetTransObject(SQLCA)
dw_composite.Event pfc_Retrieve( )
END IF
2 Print or display the composite DataWindow as appropriate.
dw_composite.inv_report.of_PrintReport &
(TRUE, FALSE)
v To print a DataWindow:
• Call the of_PrintReport function.
80 PowerBuilder
CHAPTER 4 Using PFC Services
The service allows you to specify columns for which PowerBuilder should still
perform required fields processing.
82 PowerBuilder
CHAPTER 4 Using PFC Services
ll_return = &
dw_emplist.inv_rowmanager.Event pfc_AddRow()
IF ll_return = -1 THEN
MessageBox("Error", "Error adding empty row")
END IF
PFC calls this event automatically when the user selects Add from the
m_dw pop-up menu.
v To delete rows:
• Call the pfc_DeleteRow event.
This example deletes the current row or all selected rows:
Long ll_return
ll_return = &
dw_emplist.inv_rowmanager.pfc_DeleteRow()
IF ll_return = -1 THEN
MessageBox("Error", "Deletion error")
END IF
PFC calls this event automatically when the user selects Delete from the
m_dw pop-up menu.
To allow users to select multiple rows, use the row selection service.
84 PowerBuilder
CHAPTER 4 Using PFC Services
Presentation styles
You cannot use the DataWindow resize service with DataWindow objects that
have the Composite or RichTextEdit presentation style.
86 PowerBuilder
CHAPTER 4 Using PFC Services
Sort service
Overview The PFC sort service allows you to provide easy-to-use sort capabilities in a
DataWindow.
Use this service to add sort capabilities to your application. For example, you
might add a menu item that calls the pfc_SortDlg event.
PFC enables the sort service through the n_cst_dwsrv_sort user object.
Usage The sort service displays Sort dialog boxes automatically. All you do is enable
the service and specify the sort style you want. You can choose among four
styles of sort dialog boxes:
• Default PowerBuilder Sort dialog box:
Additionally, you can allow the user to sort by clicking on column headings
(for column header sorting, the column header object must be in the primary
header band of the DataWindow)
88 PowerBuilder
CHAPTER 4 Using PFC Services
v To specify whether PFC sort dialog boxes sort on display values or data
values:
• Call the of_SetUseDisplay function:
dw_emp.inv_sort.of_SetUseDisplay(TRUE)
Window services
PFC implements window services through:
• Functions, events, and instance variables coded in w_master and its
descendants
• Custom class user objects
To access window services, you create windows that descend from one of
PFC’s w_master descendants:
w_child
w_frame
w_main
w_popup
w_response
w_sheet
W_master contains:
• Functions to enable and disable window services implemented as custom
class user objects
• Instance variables that allow you to reference each custom class user
object’s functions, events, and instance variables (this type of instance
variable is called a reference variable)
• Precoded events and user events that perform window services and call
custom class user object functions
• Empty user events to which you add code to perform application-specific
processing
The following table lists window services and how they are implemented:
Window service Implementation
Basic window service Implemented in n_cst_winsrv and as well as functions
and user events in PFC windows
Preference service n_cst_winsrv_preference
Sheet management n_cst_winsrv_sheetmanager
service
Status bar service n_cst_winsrv_statusbar
90 PowerBuilder
CHAPTER 4 Using PFC Services
92 PowerBuilder
CHAPTER 4 Using PFC Services
Preference service
Overview The PFC preference service provides functionality that automatically saves
and restores a user’s window settings using either the registry or an INI file.
The preference services saves:
• Size
• Position
• Toolbar settings
PFC enables the preference service through the n_cst_winsrv_preference user
object.
Usage Use this service to save and restore window settings.
Automatic resetting
If you enable the preference service, windows descended from w_master save
and restore settings automatically.
94 PowerBuilder
CHAPTER 4 Using PFC Services
PFC enables the status bar service through the n_cst_winsrv_statusbar user
object. Status bar information displays in the w_statusbar pop-up window.
You call n_cst_winsrv_statusbar functions to control the items displayed.
Usage Use this service to display status bar information in an MDI frame window.
If necessary, you can call w_statusbar functions to modify status bar
information via PowerScript code.
Menu service
Overview The PFC menu service provides functions that help you communicate between
a menu and a window. It also provides functions that return information on an
MDI frame and toolbar items. You use the menu service functions within menu
item scripts.
PFC enables the menu service through the n_cst_menu user object.
Usage Use this service in non-PFC menus to access the frame window and to
communicate with windows.
Message.StringParm = "w_emplist"
lnv_menu.of_SendMessage(this, "pfc_Open")
Resize service
Overview The PFC resize service provides functions that automatically move and resize
controls when the user resizes a window, tab, or tab page. This service allows
you to control how and whether controls resize when the window, tab, or tab
page resizes.
PFC enables the resize service through the n_cst_resize user object.
You use n_cst_dwsrv_resize, the DataWindow resize service to move and
resize columns within a DataWindow.
96 PowerBuilder
CHAPTER 4 Using PFC Services
Usage Use this service to control window resizing. It provides two resizing options:
• For simple resizing Call the of_Register function passing n_cst_resize
constants, such as FIXEDBOTTOM
• For total control over resizing Implement weighted resize by calling
the of_Register function with explicit specifications for moving and
scaling
Conversion service
Overview The PFC conversion service provides functions that you can call to convert
values from one data type to another. For example, you can call the of_Boolean
function to convert an integer or a string into a boolean value.
PFC enables the conversion service through the n_cst_conversion user object.
N_cst_conversion uses the PowerBuilder autoinstantiate option, which
eliminates the need for CREATE and DESTROY statements.
Usage You can use conversion service functions to convert:
From To
Integer or String Boolean
Boolean, ToolbarAlignment, or SQLPreviewType String
Boolean Integer
String ToolbarAlignment
Button String
Icon String
String SQLPreviewType
98 PowerBuilder
CHAPTER 4 Using PFC Services
Date/Time service
Overview The PFC date/time service provides functions that you can call to perform
calculations with dates. For example, you can call the of_SecondsAfter
function to determine the number of seconds between two date/time values.
PFC enables the date/time service through the n_cst_datetime user object.
N_cst_datetime uses the PowerBuilder autoinstantiate option, which
eliminates the need for CREATE and DESTROY statements.
Usage You can use the date/time service to perform many date and time calculations.
Functions you can perform with the date/time service include:
• Convert a Julian date to a Gregorian date (Gregorian dates use the Date
datatype)
• Convert seconds to hours
• Convert seconds to days
• Convert a Gregorian date to a Julian date
• Determine the number of years between two date/time values
• Determine the number of months between two date/time values
ll_seconds = Long(sle_seconds.Text)
ll_days = inv_datetime.of_Days(ll_seconds)
MessageBox("Date/Time", &
String(ll_seconds) + " seconds is equal to " + &
String(ll_days) + " days.")
100 PowerBuilder
CHAPTER 4 Using PFC Services
File service
Overview The PFC file service provides functions that you can call to add file-
management functionality to an application. For example, you can call the
of_FileRename function to rename a file.
The file service includes support for many platform-specific types of
operations, automatically calling the appropriate external function.
PFC enables the file service through the n_cst_filesrv user object and its
platform-specific descendants.
Usage Actions you can perform with the file service include:
• Assembling a concatenated filename
• Creating and deleting directories
• Reading, writing, renaming, and copying files, including files larger than
32,765 bytes
• Accessing file information, including date and time
• Creating and sorting a list of all files in a directory
Define n_cst_filesrv as a global, instance, or local variable, as appropriate for
your application:
Usage of file service functions Variable type
Throughout your application Global variable or as an instance variable on
n_cst_appmanager
Within a single object Instance variable for the object
Within a single script Local variable
102 PowerBuilder
CHAPTER 4 Using PFC Services
Numerical service
Overview The PFC numerical service provides functions that you can call to access
binary data. For example, you can call the of_GetBit function to determine if a
specified bit is on or off.
PFC enables the numerical service through the n_cst_numerical user object.
ll_base10 = Long(sle_base10.text)
ls_binary = inv_numerical.of_Binary(ll_base10)
MessageBox("Numerical", &
String(ll_base10) + " base 10 is equal to " &
+ ls_binary + " in binary.")
104 PowerBuilder
CHAPTER 4 Using PFC Services
Platform service
Overview The PFC platform service provides functions that you can call to add platform-
specific functionality to an application. You can use this service’s functions on
multiple platforms without recoding or adding conditional logic that checks for
the current platform. For example, you can call the of_GetFreeMemory
function to determine the amount of remaining memory; the platform service
automatically calls the appropriate external function for the current platform.
PFC enables platform services through the n_cst_platform user object and its
platform-specific descendants.
Usage Functions you can perform with the platform service include:
• Determining the amount of free memory
• Determining the amount of free system resources
• Determining the height and width, in PBUs, given a text string
Define n_cst_platform as a global, instance, or local variable, as appropriate
for your application:
Usage of platform functions Variable type
Throughout your application Global variable or as an instance variable on
n_cst_appmanager
Within a single object Instance variable for the object
Within a single script Local variable
ll_free_memory = &
inv_platform.of_GetFreeMemory()
gnv_app.of_GetFrame().SetMicroHelp &
("Free memory: " + String(ll_free_memory) )
Selection service
Overview The PFC selection service provides a function that displays the w_selection
dialog box, which allows users to select a row. When the user clicks OK, the
function returns the values in one or more columns for the selected row.
PFC enables the selection service through the n_cst_selection user object.
Usage You use the selection service’s of_Open function to display a dialog box
allowing users to choose an item that your application then processes.
There are three basic versions of the of_Open function. Each displays different
information in w_selection:
• W_selection retrieves and displays all rows for a specified DataWindow
object
• W_selection displays a passed set of rows
• W_selection displays rows that have been saved as part of the passed
DataWindow object
106 PowerBuilder
CHAPTER 4 Using PFC Services
lnv_sqlattrib[1].s_verb = sle_verb.text
lnv_sqlattrib[1].s_tables = sle_tables.text
lnv_sqlattrib[1].s_columns = sle_columns.text
lnv_sqlattrib[1].s_values = sle_values.text
lnv_sqlattrib[1].s_where = sle_where.text
lnv_sqlattrib[1].s_order = sle_order.text
lnv_sqlattrib[1].s_group = sle_group.text
lnv_sqlattrib[1].s_having = sle_having.text
108 PowerBuilder
CHAPTER 4 Using PFC Services
ls_sql = inv_sql.of_Assemble(lstr_sql)
MessageBox("SQL", ls_sql)
String-handling service
Overview The PFC string-handling service provides functions that you can call to operate
on strings.
PFC enables the string-handling service through the n_cst_string user object.
Usage You can use the string-handling service to perform many string operations,
including:
• Separating a delimited string into an array
• Converting an array into a delimited string
• Determining if a string is lowercase, uppercase, alphabetic, or
alphanumeric.
• Global replacing
110 PowerBuilder
CHAPTER 4 Using PFC Services
Metaclass service
Overview The metaclass service contains functions that provide information on the
functions, events, and variables defined within another object.
PFC enables the string-handling service through the n_cst_metaclass user
object.
Usage The most common use of the metaclass service is to determine whether an
object function or event exists before calling it.
The functions that make up the complete self-updating object API are:
Function Purpose
of_AcceptText Calls the pfc_AcceptText event, which calls AcceptText
functions as appropriate
of_UpdatesPending Calls the pfc_UpdatesPending event, which determines
whether the object has been updated
of_Validation Calls the pfc_Validation event, which validates data for the
object
of_UpdatePrep Calls the pfc_UpdatePrep event, which prepares the object
for update as appropriate
of_Update Calls the pfc_Update event, which updates the database
of_PostUpdate Calls the pfc_PostUpdate event, which performs post-
update processing as appropriate
Use the Browser for information on the signatures of these functions and
events.
112 PowerBuilder
CHAPTER 4 Using PFC Services
Writing your own self- To write a self-updating object, implement the functions listed above and
updating objects ensure that a reference to the object is in the array passed to the corresponding
n_cst_luw functions.
Extending the save By default, the w_master pfc_Save process updates all modified DataWindows
process within the window. You can extend this process as follows:
• Other self-updating objects You can define other self-updating objects
as updatable by calling the of_SetUpdateable function in the object’s
Constructor event. This example is from a u_lvs-based ListView:
this.of_SetUpdateable(TRUE)
Now the logical unit of work service will call functions to update the u_lvs
data source as part of a default save process.
• DataStores You can add one or more DataStores to the list of objects to
be updated by calling the w_master of_SetUpdateObjects function:
PowerObject lpo_objs[ ]
Integer li_count
lpo_objs = this.control
li_count = UpperBound(lpo_objs)
li_count++
lpo_objs[li_count] = ids_data
this.of_SetUpdateObjects(lpo_objs)
• Additional windows You can add one or more windows to the list of
objects to be updated by calling the w_master of_SetUpdateObjects
function:
PowerObject lpo_objs[ ]
Integer li_count
lpo_objs = this.control
li_count = UpperBound(lpo_objs)
li_count++
// Update w_other as well as this window
lpo_objs[li_count] = w_other
this.of_SetUpdateObjects(lpo_objs)
List service
Overview Many applications need to maintain information in linked lists. The PFC list
service provides objects and functions you use to create and manipulate linked
lists. It supports these types of lists:
• Basic linked list (sorted or unsorted)
• Stack (LIFO)
• Queue (FIFO)
• Tree (balanced binary tree)
A list is made up of A linked list is made up of nodes. Each node contains:
nodes
• A reference to the previous item in the list
• A reference to the next item in the list
• A key
• Data
• Balance information (tree lists only)
When adding a node to a linked list, you provide the key and data; the service
objects maintain references to the previous and next items.
About sorted lists A tree list is sorted automatically. You can also use the n_cst_list object to
maintain a sorted linked list.
114 PowerBuilder
CHAPTER 4 Using PFC Services
116 PowerBuilder
CHAPTER 4 Using PFC Services
Accessing the entire You can use the of_Get function to retrieve all nodes in the list.
list at once
5 Remove the node from the list by calling the of_Remove function:
inv_list.of_Remove(lnv_node)
6 Destroy the temporary node:
DESTROY lnv_temp
Destroying a list When you no longer need the list, destroy the list and all of its nodes.
ll_count = inv_list.of_Destroy()
MessageBox("Destroy List", &
String(ll_count) + " nodes destroyed")
Using a stack
A stack maintains a last-in first-out (LIFO) list. When you add a new node to
the stack, the stack object places it at the beginning; when you get a node from
the stack, the stack object accesses it from the beginning of the list, removing
it in the process.
PFC enables stack processing through the n_cst_stack user object.
Creating a stack When you create a stack, you create and populate instances of
n_cst_linkedlistnode and push them onto the stack.
v To create a stack:
1 Declare an instance variable of type n_cst_stack:
n_cst_stack inv_stack
Because PFC defines this object with the autoinstantiate option, you don’t
need to code CREATE or DESTROY statements.
2 Add nodes to the stack. To do this, create an instance of the node, specify
a key and data by calling the n_cst_linkedlistnode of_SetKey and
of_SetData functions, then add the node to the stack by calling of_Push
(this example creates a stack using a SingleLineEdit as the source):
n_cst_linkedlistnode lnv_node
Integer li_return
118 PowerBuilder
CHAPTER 4 Using PFC Services
IF IsValid(lnv_node) THEN
lnv_node.of_GetKey(la_key)
MessageBox("Stack", &
"Key is " + String(la_key))
ELSE
MessageBox("Stack", "List is empty")
END IF
Destroying a stack When you no longer need the stack, destroy the stack and all of its nodes.
v To destroy a stack:
• Destroy all nodes in the stack by calling of_Destroy:
Long ll_count
ll_count = inv_stack.of_Destroy()
MessageBox("Destroy", &
String(ll_count) + " nodes destroyed")
Using a queue
A queue maintains a first-in, first-out (FIFO) list. When you add a new node to
the queue, the queue object places it at the end; when you get a node from the
queue, the queue object accesses it from the beginning of the list, removing it
in the process.
PFC enables queue processing through the n_cst_queue user object.
Creating a queue When you create a queue, you create and populate instances of
n_cst_linkedlistnode and add them to the queue.
v To create a queue:
1 Declare an instance variable of type n_cst_queue:
n_cst_queue inv_queue
Because PFC defines this object with the autoinstantiate option, you don’t
need to code CREATE or DESTROY statements.
2 Add nodes to the queue. To do this, create an instance of the node, specify
a key and data by calling the n_cst_linkedlistnode of_SetKey and
of_SetData functions, then add the node to the queue by calling of_Put.
This example creates a queue using a SingleLineEdit as the source:
n_cst_linkedlistnode lnv_node
Integer li_return
120 PowerBuilder
CHAPTER 4 Using PFC Services
3 Access the key and data as necessary by calling the n_cst_node of_GetKey
and of_GetData functions:
Any la_key
IF IsValid(lnv_node) THEN
lnv_node.of_GetKey(la_key)
MessageBox("Queue", &
"Key is " + String(la_key))
ELSE
MessageBox("Queue", "List is empty")
END IF
Destroying a queue When you no longer need the queue, destroy the list and all of its nodes.
v To destroy a queue:
• Destroy all nodes in the queue by calling of_Destroy:
Long ll_count
ll_count = inv_queue.of_Destroy()
MessageBox("Destroy All", &
String(ll_count) + " nodes destroyed")
Using a tree
The PFC tree list object maintains a balanced binary tree of nodes in ascending
order, by key value. This object provides all the functionality of a sorted list
with no duplicates allowed. It differs from a stack and a queue in that nodes
are not removed as they are accessed.
The balanced binary tree maintained by the PFC tree list object is never more
than one level out of balance. Because the tree structure reduces the number of
nodes that must be searched during find operations, it provides better
performance than a sorted list.
You can customize sort processing by extending the n_cst_treenodecompare
of_Compare function. See “Creating a comparison object” on page 124.
PFC enables tree processing through the n_cst_tree user object.
Creating a tree When you create a tree, you create and populate instances of n_cst_treenode
and add them to the tree.
v To create a tree:
1 Declare an instance variable of type n_cst_tree:
n_cst_tree inv_tree
Because PFC defines this object with the autoinstantiate option, you don’t
need to code CREATE or DESTROY statements.
2 (Optional) Specify a customized node comparison object. This example
assumes an inv_customcompare instance variable of type
n_cst_customcompare:
inv_customecompare = CREATE n_cst_customcompare
inv_tree.of_SetCompare(inv_customcompare)
3 Add nodes to the tree. To do this, create an instance of the node by calling
of_Create, specify a key and data by calling the n_cst_treenode of_SetKey
and of_SetData functions, then add the node to the tree by calling the
of_Add function. This example creates a tree using a SingleLineEdit as the
source:
n_cst_treenode lnv_node
Integer li_return
inv_tree.of_Create(lnv_node)
lnv_node.of_SetKey(sle_1.text)
lnv_node.of_SetData(sle_1.text)
li_return = inv_tree.of_Add(lnv_node)
Finding nodes in a You find nodes in a balanced binary tree. They aren’t removed from the list as
tree they are accessed.
inv_tree.of_Create(lnv_temp)
2 Populate the empty node with the key of the node you want to find:
lnv_temp.of_SetKey(li_key)
3 Call the of_Find function to access the requested node. This function’s
first argument returns a reference to the requested node:
inv_tree.of_Find(lnv_node, lnv_temp)
4 Access the key and data of the found node by calling the n_cst_node
of_GetKey and of_GetData functions.
122 PowerBuilder
CHAPTER 4 Using PFC Services
Removing nodes from You must explicitly remove nodes from a tree list (they are not removed
a tree automatically, as in a stack or a queue).
inv_tree.of_Create(lnv_temp)
2 Populate the empty node with the key of the node you want to delete:
lnv_temp.of_SetKey(li_key)
3 Call the of_Find function to access the requested node. This function
returns a reference to the requested node (the first argument):
inv_tree.of_Find(lnv_node, lnv_temp)
4 Remove the node from the tree list by calling the of_Remove function:
inv_tree.of_Remove(lnv_node)
5 Destroy the temporary node:
DESTROY lnv_temp
Destroying a tree When you no longer need the tree list, destroy the list and all of its nodes.
ll_count = inv_tree.of_Destroy()
MessageBox("Destroy All", &
String(ll_count) + " nodes destroyed")
anv_node1.of_GetKey(la_key1)
IF IsNull(la_key1) THEN Return -4
124 PowerBuilder
CHAPTER 4 Using PFC Services
anv_node2.of_GetKey(la_key2)
IF IsNull(la_key2) THEN Return -4
ls_keytype1 = ClassName(la_key1)
ls_keytype2 = ClassName(la_key2)
inv_sortedlist.of_SetCompare(inv_customcompare)
3 Initialize objects before adding them to the list. In the example ahead, you
create an array of n_cst_empinfo objects and initialize them with last
name, first name, and state.
4 Create nodes, set node values, and add them to the list as necessary:
n_cst_node lnv_node
Integer li_i
Timing service
Overview The timing service works with PFC’s n_tmg Timing object to provide single
and multiple timers. These timers are especially useful with standard class and
custom class user objects.
PFC enables the timing service through n_tmg, n_cst_tmgsingle, and
n_cst_tmgmultiple.
Using single timers Use n_cst_tmgsingle to maintain a single timer. You establish the timer by
calling the of_Register function, specifying the object to be notified, the event
to be notified, and the timer interval.
126 PowerBuilder
CHAPTER 4 Using PFC Services
4 Register the object and event to be notified (the object is a window in this
example):
itmg_timer.inv_single.of_Register &
(this, "ue_showtimer", 15)
5 Code the event to receive notification from n_cst_tmgsingle
(ue_showtimer in this example).
Using multiple timers Use n_cst_tmgmultiple to maintain multiple timers. You establish each timer
by calling the of_Register function, specifying the object to be notified, the
event to be notified, and the timer interval.
128 PowerBuilder
CH A PTE R 5 Using PFC Visual Controls
About this chapter This chapter explains how to use PFC standard visual user objects and
custom visual user objects.
Contents
Topic Page
About PFC visual controls 129
Using standard visual user objects 130
Using custom visual user objects 169
130 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
When you use the PFC standard visual user objects as window controls, editing
functions are enabled automatically when you use a menu that descends from
the PFC m_master menu. M_master includes an Edit menu that has menu items
for all editing functions. These Edit menu items use the message router to call
the appropriate user event in the current control. You can also add code to
command buttons and other controls to call these user events.
Menu Used by
m_edit U_ddlb
U_ddplb
U_em
U_mle
U_rte
U_sle
m_dw U_dw
m_lvs U_lvs
m_oc U_oc
m_tvs U_tvs
These pop-up menus all include standard text editing functions. However, text
editing functions are not enabled or visible in all pop-up menus by default.
Customizing menu All controls that provide right-mouse button support include a
display pfc_PreRMBMenu event for customizing the items that appear on a pop-up
menu. PFC calls this event after the menu is created but before it is displayed.
132 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
v To enable autoscroll:
• After placing the user object in a window, add code to the Constructor
event to set the ib_search instance variable to TRUE:
this.ib_search = TRUE
Using autoselect
These editable controls feature automatic selection:
U_ddlb
U_ddplb
U_em
U_mle
U_sle
When autoselect is enabled, PFC automatically selects all text in the control
when it receives focus.
By default, autoselect is disabled.
v To enable autoselect:
• After placing the user object in a window, add code to the Constructor
event to set the ib_autoselect instance variable to TRUE:
this.ib_autoselect = TRUE
134 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
2 Define tag values for each of the sheet’s controls. Use the following
format:
MicroHelp=tagtext
PFC uses the specified tag text to update MicroHelp automatically when
the control gets focus. If there are multiple items in the tag, separate them
with semicolons.
Enabling DataWindow PFC provides a variety of DataWindow services that you can use to add
services production-strength features to an application. Many of these services require
little or no coding on your part.
Disabling services
The u_dw Destructor event destroys enabled services automatically. In
most cases you don’t destroy a service explicitly.
136 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Retrieving rows Because many DataWindow services rely on the u_dw pfc_Retrieve event to
retrieve data, it’s best to code the PowerScript Retrieve function in the u_dw
pfc_Retrieve event. To retrieve rows, your code then calls the u_dw
of_Retrieve function, which calls either the pfc_Retrieve event or the
n_cst_dwsrv_linkage of_Retrieve function as appropriate.
ll_return = this.of_Retrieve()
2 Add code to the pfc_Retrieve event that calls the PowerScript Retrieve
function, returning the return code:
Return this.Retrieve()
138 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
For more information on using pfc_Save, see “Using the pfc_Save process” on
page 195.
Declaring nonupdatable DataWindows You can declare a DataWindow as
nonupdatable, thus removing it from the pfc_Save update sequence and the
PFC default CloseQuery processing.
Shared DataWindows
If your window includes DataWindows that share data, only one DataWindow
control should be updatable. All others that share data should be nonupdatable.
140 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Displaying database You use the ListView data source service to associate a ListView with a data
data in a ListView source (not to be confused with an ODBC data source). A data source can be:
• DataWindow object (using either data retrieved from the database or data
stored with the DataWindow object)
• SQL statement
• DataWindow control
• DataStore control
142 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
9 Extend the pfc_Retrieve event, adding code that calls the of_Retrieve
function, which allows you to specify retrieval arguments:
Any la_args[20]
v To remove items from the ListView, allowing them to remain in the u_lvs
DataStore and the database:
1 Enable the ListView’s Delete Items property.
2 Call the PowerScript DeleteItem function:
Integer li_index
li_index = lv_list.SelectedIndex()
lv_list.DeleteItem(li_index)
Inserting items into You can use a ListView to insert items into the database. But because the
the ListView ListView control allows updates to the label column only, you cannot add
information into all the columns displayed in Report view. To get around this,
you need another mechanism (such as a dialog box) to acquire enough
information to update the DataWindow, the ListView, and the database.
144 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Basic use You use the TreeView level source service to associate each TreeView level
with a data source (not to be confused with an ODBC data source). A data
source can be:
• DataWindow object (using either data retrieved from the database or data
stored with the DataWindow object)
• SQL statement
• DataWindow control
• DataStore control
• Rows from an array
• A file
The TreeView level source service (implemented through the
n_cst_tvsrv_levelsource custom class user object) maintains each TreeView
level’s data source in a DataStore and uses it to populate the TreeView level.
Establishing the level’s data source You establish a level’s data source by
calling the n_cst_tvsrv_levelsource of_Register function. This function
includes an argument that specifies how a level relates to the levels above it.
This argument must be in the format :scope.level.column where:
• Scope specifies one of the following literals:
• Level
• Parent
146 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
v To display a TreeView:
1 Add a u_tvs user object to the window.
2 Enable the level source service using the u_tvs of_SetLevelSource
function:
this.of_SetLevelSource(TRUE)
3 Define a data source for each TreeView level by calling the of_Register
function, once for each level:
this.inv_levelsource.of_Register(1, &
"dept_name", "", "d_deptlist", SQLCA, "")
IF IsValid(inv_levelsource) THEN
li_level = this.of_GetNextLevel(al_parent)
this.inv_levelsource.of_GetArgs(al_parent, &
li_level, la_args)
END IF
v To remove items from the TreeView (allowing them to remain in the data
source and the database):
1 Enable the TreeView’s Delete Items property.
2 Call the PowerScript DeleteItem function:
Long ll_tvi
ll_tvi = this.FindItem(CurrentTreeItem!, 0)
148 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
ll_handle = tv_1.FindItem(CurrentTreeItem! , 0)
ll_return = tv_1.of_InsertItem &
(ll_handle, ids_data, 1, "Sorted", 0)
Using recursion to The u_tvs TreeView control allows you to display multiple levels from a single
populate a TreeView table that has a recursive relationship. In the employee table, for example, there
might be a recursive relationship between managers and employees, with each
employee row containing a column that points to its manager’s employee ID.
You indicate a recursive relationship through an argument to the
n_cst_tvsrv_levelsource of_Register function. A recursive level is always the
lowest level specified.
150 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Using pictures A TreeView consists of items that are associated with one or more pictures,
which are used in different ways:
Picture Usage
Default Represents a TreeView item in its normal mode
Selected Represents a selected TreeView item
State Appears to the left of the TreeView item indicating that the item
is not in its normal mode, for example changed or unavailable
Overlay Appears on top of a TreeView item
For more on how you specify pictures, see “Using pictures” on page 144.
this.inv_levelsource.of_SetSelectedPictureColumn &
(1, 'picture_overlay')
this.inv_levelsource.of_Register(2, &
"states_state_name", &
":parent.1.sales_regions_region", &
"d_regionstate", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(2, "2")
this.inv_levelsource.of_SetSelectedPictureColumn &
(2, "7")
152 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
this.inv_levelsource.of_Register(3, &
"customer_company_name", &
":parent.2.sales_regions_region, &
:parent.1.states_state_id", &
"d_regionstatecust", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(3, "3")
this.inv_levelsource.of_SetSelectedPictureColumn &
(3, "7")
this.inv_levelsource.of_Register(4, &
"employee_emp_lname", ":parent.1.customer_id", &
"d_regionstatecustrep", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(4, "4")
this.inv_levelsource.of_SetSelectedPictureColumn &
(4, "7")
this.inv_levelsource.of_Register(5, &
"order_id_string", ":parent.2.customer_id, &
:parent.1.employee_emp_id", &
"d_regionstatecustrepord", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(5, "5")
this.inv_levelsource.of_SetSelectedPictureColumn &
(5, "7")
6 Call the pfc_Populate event:
this.Event pfc_Populate(0)
7 Extend the pfc_Retrieve event:
Any la_args[20]
Integer li_level
IF IsValid(inv_levelsource) THEN
li_level = of_GetNextLevel(al_parent)
inv_levelsource.of_GetArgs(al_parent, &
li_level, la_args)
END IF
Return of_Retrieve(al_parent, la_args, ads_data)
8 Extend the TreeView’s SelectionChanged event to call the ListView’s
pfc_Populate event:
lv_1.Event pfc_Populate()
li_level = ltvi_selecteditem.Level + 1
// Normal registration
ls_dataobject = &
tv_1.inv_levelsource.of_GetDataObject(li_level)
ls_labelcolumn = &
tv_1.inv_levelsource.of_GetLabelColumn(li_level)
ls_picturecolumn = &
tv_1.inv_levelsource.of_GetPictureColumn &
(li_level)
tv_1.inv_levelsource.of_GetTransObject(li_level, &
ltr_obj)
// Level 3 registration.
tv_1.inv_levelsource.of_GetLevelAttributes &
(li_level, lnv_tvattrib)
154 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Case 2
li_RC = lv_1.inv_datasource.of_Register &
(ls_labelcolumn, ls_dataobject, ltr_obj)
li_RC = &
lv_1.inv_datasource.of_SetPictureColumn &
(ls_picturecolumn)
Case 3
li_RC = lv_1.inv_datasource.of_Register &
(lnv_tvattrib.is_labelcolumn, &
lnv_tvattrib.is_dataobject, &
lnv_tvattrib.itr_obj)
li_RC = &
lv_1.inv_datasource.of_SetPictureColumn &
(lnv_tvattrib.is_picturecolumn)
Case 4
li_RC = lv_1.inv_datasource.of_Register &
(ls_labelcolumn, ls_dataobject, ltr_obj)
li_RC = &
lv_1.inv_datasource.of_SetPictureColumn &
(ls_picturecolumn)
Case 5 // Not in the tree so register normally
li_RC = lv_1.inv_datasource.of_Register &
("product_description", &
"d_regionstatecustreporditm", SQLCA)
li_RC = &
lv_1.inv_datasource.of_SetPictureColumn &
("product_picture_name")
End Choose
// Add all the visible columns of the datasource
// to the report view.
lv_1.inv_datasource.of_RegisterReportColumn()
ll_handle = tv_1.FindItem(CurrentTreeItem!, 0)
tv_1.GetItem(ll_handle, ltvi_item)
Else
la_Args[1] = Integer(ltvi_item.Label)
End If
156 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
this.inv_levelsource.of_Register(2, &
"states_state_name", &
":parent.1.sales_regions_region", &
"d_regionstate", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(2, "2")
this.inv_levelsource.of_SetSelectedPictureColumn &
(2, "7")
this.inv_levelsource.of_Register(3, &
"customer_company_name", &
":parent.2.sales_regions_region, &
:parent.1.states_state_id", &
"d_regionstatecust", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(3, "3")
this.inv_levelsource.of_SetSelectedPictureColumn &
(3, "7")
this.inv_levelsource.of_Register(4, &
"employee_emp_lname", ":parent.1.customer_id", &
"d_regionstatecustrep", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(4, "4")
this.inv_levelsource.of_SetSelectedPictureColumn &
(4, "7")
this.inv_levelsource.of_Register(5, &
"order_id_string", ":parent.2.customer_id, &
:parent.1.employee_emp_id", &
"d_regionstatecustrepord", SQLCA, "")
this.inv_levelsource.of_SetPictureColumn(5, "5")
this.inv_levelsource.of_SetSelectedPictureColumn &
(5, "7")
6 Call the pfc_Populate event:
this.Event pfc_Populate(0)
7 Extend the pfc_Retrieve event:
Any la_args[20]
Integer li_level
IF IsValid(inv_levelsource) THEN
li_level = of_GetNextLevel(al_parent)
inv_levelsource.of_GetArgs(al_parent, &
li_level, la_args)
END IF
Return of_Retrieve(al_parent, la_args, ads_data)
8 Extend the TreeView’s SelectionChanging event to reset the DataWindow
control’s DataObject property and populate it with the selected TreeView
item:
n_ds lds_datastore
TreeViewItemltvi_new
Long ll_dsrow
158 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
v To print a TreeView:
1 Enable the TreeView print service:
tv_deptemp.of_SetPrint(TRUE)
2 Call the of_PrintTree function:
tv_deptemp.inv_print.of_PrintTree()
• Print documents
• Add Find and Replace capabilities to a RichTextEdit control
• Control text properties
For complete information on the PowerBuilder RichTextEdit control, see the
PowerBuilder User’s Guide and Application Techniques.
Displaying rich text U_rte provides events that allow the user to specify the rich text document to
documents open:
• pfc_Open Replaces the current document with the selected document,
prompting the user before discarding the current document
• pfc_InsertFile Inserts the selected document into the current document.
The RichTextEdit control replaces the current selection when the file is
inserted
You can also populate the RichTextEdit control by calling the PowerScript
InsertDocument function.
Inserting pictures U_rte provides an event that displays a dialog box for the user to choose a
bitmap to insert at the current cursor position. The RichTextEdit control
replaces the current selection when the bitmap is inserted.
160 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Printing rich text U_rte provides events that allow you to print the data in RichTextEdit controls.
documents You can:
• Display a Print dialog box, allowing you to choose options before printing
PFC uses the s_printdlgattrib structure to pass properties to the
n_cst_platform of_PrintDlg function. You can use the pfc_PrePrintDlg
event to further customize the contents of the Print dialog box by
modifying elements in the s_printdlgattrib structure.
The values in the s_printdlgattrib structure reflect selected RichTextEdit
Print properties (such as collate, page numbers, and number of copies).
• Print a RichTextEdit control without displaying the Print dialog box
U_rte also provides functions that allow you to control the printing of page
numbers.
2 Identify the name of the field into which PFC places the page number (this
example assumes an input field named PAGENUM):
rte_doc.of_SetPageInputField("PAGENUM")
ids_empdata.DataObject = "d_sharerte"
ids_empdata.of_SetTransObject(SQLCA)
IF ids_empdata.Retrieve() = -1 THEN
MessageBox("Retrieve", "Retrieve error")
END IF
rte_doc.DataSource(ids_empdata)
2 Call the of_SetContinuousPages function:
rte_doc.of_SetContinuousPages(TRUE)
3 Print the document:
rte_doc.Event pfc_Print( )
For more information on sharing data between a RichTextEdit control and
a DataWindow or DataStore, see Application Techniques.
Using the RTE find U_rte features a find and replace service that you can use to enhance a
service RichTextEdit control. Once the service is enabled, PFC displays Find and
Replace dialog boxes when the user selects Edit>Find or Edit>Replace from
the menu bar of a menu that descends from the PFC m_master menu and the
RichTextEdit control has focus.
You can also display Find and Replace dialog boxes programmatically.
162 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
rte_doc.of_SetTextStyleBold(cbx_bold.Checked)
rte_doc.of_SetTextStyleItalic(cbx_italic.Checked)
rte_doc.of_SetTextStyleUnderline &
(cbx_underline.Checked)
rte_doc.of_SetTextStyleStrikeout &
(cbx_strikeout.Checked)
rte_doc.of_SetTextStyleSubscript &
(cbx_subscript.Checked)
rte_doc.of_SetTextStyleSuperscript &
(cbx_superscript.Checked)
SetRedraw(TRUE)
rte_doc.of_GetTextStyle &
(lnv_style)
cbx_bold.Checked = lnv_style.ib_bold
cbx_italic.Checked = lnv_style.ib_italic
cbx_underline.Checked = &
lnv_style.ib_underlined
cbx_strikeout.Checked = lnv_style.ib_strikeout
cbx_subscript.Checked = lnv_style.ib_subscript
cbx_superscript.Checked = &
lnv_style.ib_superscript
164 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Updating the linked When you update a linked object, PowerBuilder attempts to find a file linked
object to an OLE container. If the linked file is not found, a dialog displays and lets
the user bring up a second dialog for finding the file or changing the link.
1 Create a window that has an OLE control based on u_oc.
2 Call the pfc_UpdateLinks event:
ole_1.Event pfc_UpdateLinks()
Using the u_tab Tab control and the u_tabpg user object
Many current applications use Tab controls and tab pages to enhance their user
interface. The u_tab Tab control and the u_tabpg user object provide basic PFC
functionality. And they both implement the resize service, which you enable
differently depending on how the tab is defined.
About Tab controls Tab control A Tab control is a control that you place in a window or user
and tab pages object that contains tab pages. Part of the area in the Tab control is for the tabs
associated with the tab pages. Any space left is occupied by the tab pages
themselves.
PFC provides the u_tab Tab control, which you can use as an ancestor for Tab
controls.
Tab page A tab page contains other controls and is one of several pages
within a Tab control. All tab pages in a Tab control occupy the same area of the
control, and only one is visible at a time. The active tab page covers the other
tab pages. There are different ways to approach tab page definition. You can
define:
• An embedded tab page In the Window or User Object painter, Select
Insert>TabPage from the Tab control’s pop-up menu and add controls to
those pages. An embedded tab page is of class UserObject but is not
reusable.
• A tab page user object In the User Object painter, create a custom
visual user object and add the controls that will display on the tab page. To
add a tab page user object to a Tab control, Select Insert>User Object from
the Tab control’s pop-up menu. A tab page defined as an independent user
object is reusable.
PFC provides the u_tabpg custom visual user object, which you can use as
the ancestor for tab pages.
You can mix and match the two methods—one Tab control can contain both
embedded tab pages and tab page user objects. But non-PFC tab pages do not
have support for PFC features, such as resizing and the message router.
For more information on programming with Tab controls and tab pages, see
Application Techniques.
Using u_tab When using u_tab, you always:
• Work with a descendant of u_tab
• Create the complete Tab control (including tab pages) in the User Object
painter
166 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Using the resize You can use the resize service to add dynamic resize capabilities to tab pages.
service with u_tab
descendants How you enable the resize service differs depending on whether the Tab
control contains embedded tab pages or tab page user objects based on
u_tabpg. If a Tab control contains both embedded tab pages and tab page user
objects, you can combine the first two procedures that follow.
When using the Create on Demand option for tab page user objects, you must
also perform the third procedure to ensure that controls display properly.
v To enable the resize service for a Tab control when using embedded tab
pages:
1 Use the User Object painter to create a Tab control based on u_tab.
2 Define embedded tab pages.
3 Enable the resize service for the Tab control (this example is from the
Constructor event):
this.of_SetResize(TRUE)
4 Register controls within the tab pages:
this.inv_resize.of_Register &
(this.tabpage_1.mle_1, &
this.inv_resize.SCALETOBOTTOM)
this.inv_resize.of_Register &
(this.tabpage_2.dw_1, &
this.inv_resize.SCALETOBOTTOM)
5 Add the user object to a window.
6 Enable the resize service for the window and register affected controls
(this example is from the window’s Constructor event):
this.of_SetResize(TRUE)
this.inv_resize.of_Register(tab_1, "Scale")
this.inv_resize.of_Register &
(cb_cancel, &
this.inv_resize.FIXEDTOBOTTOM)
this.inv_resize.of_Register &
(cb_ok, this.inv_resize.FIXEDTOBOTTOM)
this.inv_resize.of_SetMinSize &
(this.width - 100, this.height - 100)
v To enable the resize service for a Tab control when using tab page user
objects based on u_tabpg:
1 Use the User Object painter to create a tab page based on u_tabpg.
2 Enable the resize service for the tab page (this example is from the
Constructor event):
this.of_SetResize(TRUE)
3 Register controls within the tab page:
this.inv_resize.of_Register &
(this.dw_1, 0, 0, 100, 100))
4 Add the tab page user object to a Tab control.
v To use the resize service with tab page user objects that have the Create
on Demand property:
1 In the User Object painter, display the Position tab of the object’s property
sheet to determine what the size will be at creation time.
2 Specify the original size by calling the of_SetOrigSize function (this
example is from the tab page’s Constructor event):
this.inv_resize.of_SetOrigSize(1637, 457)
168 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
170 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Argument Result
DDLB Of_Register converts all registered columns to the
DropDownListBox edit style. The calculator displays
when the user clicks the down arrow, which disappears
when the calculator displays
DDLB_WITHARROW Of_Register converts all registered columns to the
DropDownListBox edit style. The calculator displays
when the user clicks the down arrow, which remains
when the calculator displays
172 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Using a standalone You can create a standalone calculator by placing u_calculator directly on a
calculator window or user object.
174 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Controlling the visual cue To control the visual cue that displays in a
DataWindow column for which the drop-down calendar is enabled, you supply
an argument to the of_Register function:
Argument Result
NONE If the column uses the:
• DropDownListBox edit style, the calendar displays
automatically when the column gets the focus
• Edit or EditMask edit style, the calendar displays
when you call the pf_DDCalendar event
DDLB Of_Register converts all registered columns to the
DropDownListBox edit style. The calendar displays
when the user clicks the down arrow, which disappears
when the calendar displays
DDLB_WITHARROW Of_Register converts all registered columns to the
DropDownListBox edit style. The calendar displays
when the user clicks the down arrow, which remains
when the calendar displays
5 (Optional) Establish the font style and color for weekend days:
this.iuo_calendar.of_SetSaturdayBold(TRUE)
this.iuo_calendar.of_SetSaturdayColor &
(RGB(0, 255, 0))
this.iuo_calendar.of_SetSundayBold(TRUE)
this.iuo_calendar.of_SetSundayColor &
(RGB(0, 255, 0))
6 (Optional) Establish a list of holidays with their font style and color (this
example shows holidays for one year only):
Date ld_holidays[11]
ld_holidays[1] = 1997-01-01
ld_holidays[2] = 1997-02-17
ld_holidays[3] = 1997-04-21
ld_holidays[4] = 1997-05-26
ld_holidays[5] = 1997-07-04
ld_holidays[6] = 1997-09-01
ld_holidays[7] = 1997-10-13
ld_holidays[8] = 1997-11-27
ld_holidays[9] = 1997-11-28
ld_holidays[10] = 1997-12-25
ld_holidays[11] = 1997-12-26
...
this.iuo_calendar.of_SetHoliday(ld_holidays)
this.iuo_calendar.of_SetHolidayBold(TRUE)
this.iuo_calendar.of_SetHolidayColor &
(RGB(0, 255, 0))
7 (Optional) Establish a list of marked days with their font style and color:
Date ld_holidays[11], ld_marked_days[12]
ld_marked_days[1] = 1996-06-13
ld_marked_days[2] = 1996-03-16
ld_marked_days[3] = 1996-09-23
ld_marked_days[4] = 1996-09-14
ld_marked_days[5] = 1997-06-13
ld_marked_days[6] = 1997-03-16
ld_marked_days[7] = 1997-09-23
ld_marked_days[8] = 1997-09-14
ld_marked_days[9] = 1998-06-13
ld_marked_days[10] = 1998-03-16
ld_marked_days[11] = 1998-09-23
ld_marked_days[12] = 1998-09-14
...
176 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
this.iuo_calendar.of_SetMarkedDay(ld_marked_days)
this.iuo_calendar.of_SetMarkedDayBold(TRUE)
this.iuo_calendar.of_SetMarkedDayColor &
(RGB(255, 0, 0))
Ensuring consistency
To ensure that all users see the same calendar display, define display
characteristics, holidays, and marked days in the u_calendar (extension-
level object) Constructor event.
ld_holidays[1] = 1997-01-01
ld_holidays[2] = 1997-02-17
ld_holidays[3] = 1997-04-21
ld_holidays[4] = 1997-05-26
ld_holidays[5] = 1997-07-04
ld_holidays[6] = 1997-09-01
ld_holidays[7] = 1997-10-13
ld_holidays[8] = 1997-11-27
ld_holidays[9] = 1997-11-28
ld_holidays[10] = 1997-12-25
ld_holidays[11] = 1997-12-26
...
this.iuo_calendar.of_SetHoliday(ld_holidays)
this.iuo_calendar.of_SetHolidayBold(TRUE)
this.iuo_calendar.of_SetHolidayColor &
(RGB(0, 255, 0))
5 (Optional) Establish a list of marked days with their font style and color:
Date ld_holidays[11], ld_marked_days[12]
ld_marked_days[1] = 1996-06-13
ld_marked_days[2] = 1996-03-16
ld_marked_days[3] = 1996-09-23
ld_marked_days[4] = 1996-09-14
ld_marked_days[5] = 1997-06-13
178 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
ld_marked_days[6] = 1997-03-16
ld_marked_days[7] = 1997-09-23
ld_marked_days[8] = 1997-09-14
ld_marked_days[9] = 1998-06-13
ld_marked_days[10] = 1998-03-16
ld_marked_days[11] = 1998-09-23
ld_marked_days[12] = 1998-09-14
...
this.iuo_calendar.of_SetMarkedDay(ld_marked_days)
this.iuo_calendar.of_SetMarkedDayBold(TRUE)
this.iuo_calendar.of_SetMarkedDayColor &
(RGB(255, 0, 0))
6 (Optional) Call additional functions as necessary to customize calendar
behavior:
this.iuo_calendar.of_SetAlwaysRedraw(TRUE)
this.iuo_calendar.of_SetInitialValue(TRUE)
7 Define a user event or visual control (such as a picture button) that displays
the drop-down calendar by calling the u_em pfc_DDCalendar event:
em_1.Event pfc_DDCalendar( )
Establishing weekend The PFC calendar control allows you to specify distinct colors and/or bold for
display options Saturdays and Sundays.
Establishing holidays The PFC calendar control allows you to establish a set of holidays and a set of
and marked days marked days.
You can specify distinct colors and/or bold for holidays and marked days.
ld_holidays[1] = 1997-01-01
ld_holidays[2] = 1997-02-17
ld_holidays[3] = 1997-04-21
ld_holidays[4] = 1997-05-26
ld_holidays[5] = 1997-07-04
ld_holidays[6] = 1997-09-01
ld_holidays[7] = 1997-10-13
ld_holidays[8] = 1997-11-27
ld_holidays[9] = 1997-11-28
ld_holidays[10] = 1997-12-25
ld_holidays[11] = 1997-12-26
ld_marked_days[1] = 1996-06-13
ld_marked_days[2] = 1996-03-16
ld_marked_days[3] = 1996-09-23
ld_marked_days[4] = 1996-09-14
ld_marked_days[5] = 1997-06-13
ld_marked_days[6] = 1997-03-16
ld_marked_days[7] = 1997-09-23
ld_marked_days[8] = 1997-09-14
ld_marked_days[9] = 1998-06-13
ld_marked_days[10] = 1998-03-16
ld_marked_days[11] = 1998-09-23
ld_marked_days[12] = 1998-09-14
2 After enabling the calendar for the DataWindow or EditMask control,
establish the list of holidays by calling the of_SetHoliday function:
this.iuo_calendar.of_SetHoliday(ld_holidays)
3 Establish holiday display options as necessary:
this.iuo_calendar.of_SetHolidayBold(TRUE)
180 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
this.iuo_calendar.of_SetHolidayColor &
(RGB(0, 255, 0))
4 Establish the list of marked days by calling the of_SetMarkedDay
function:
this.iuo_calendar.of_SetMarkedDay(ld_marked_days)
5 Establish marked day options as necessary:
this.iuo_calendar.of_SetMarkedDayBold(TRUE)
this.iuo_calendar.of_SetMarkedDayColor &
(RGB(255, 0, 0))
Setting calendar The PFC calendar control provides options that you can set to control calendar
options behavior:
• Close on click Controls whether the drop-down calendar closes when
the user clicks a date:
this.of_SetDropDownCalendar(TRUE)
...
this.iuo_calendar.of_SetCloseOnDClick(TRUE)
• Close on double-click Controls whether the drop-down calendar closes
when the user double-clicks a date:
this.of_SetDropDownCalendar(TRUE)
...
this.iuo_calendar.of_SetCloseOnDClick(TRUE)
• Date format Controls the format of the date returned by the calendar:
this.of_SetDropDownCalendar(TRUE)
...
this.iuo_calendar.of_SetDateFormat("mm/dd/yy")
• Initialize date Controls whether the calendar initializes blank fields with
the current date when the calendar displays:
this.of_SetDropDownCalendar(TRUE)
...
this.iuo_calendar.of_SetInitialValue(TRUE)
182 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
Setting splitbar The PFC splitbar control provides options that you can set to control splitbar
options display. You can control:
• Bar color To specify bar color, call the of_SetBarColor function:
this.of_SetBarColor(RGB(192,192,192))
• The bar color that displays when the bar is moved To specify bar
move color, call the of_SetBarMoveColor function:
this.of_SetBarMoveColor(RGB(128, 128, 128))
• Horizontal pointer To specify the name of the pointer that displays
when the cursor is over a horizontal splitbar, call the
of_SetHorizontalPointer function:
this.of_SetHorizontalPointer("SizeNS!")
• Vertical pointer To specify the name of the pointer that displays when
the cursor is over a vertical splitbar, call the of_SetVerticalPointer
function:
this.of_SetVerticalPointer("SizeNS!")
• Minimum object size To specify the minimum size for objects resized
by the splitbar, call the of_SetMinObjectSize function:
this.of_SetMinObjectSize(100)
You set these options in the u_st_splitbar instance’s Constructor event.
How PFC calculates You call the of_SetMaximum function to specify the value that must be
percent complete reached to equal 100%—for example, the number of rows to be retrieved from
the database. Then your code updates the current progress by calling the
of_Increment function regularly—for example, once for every ten rows.
Percent complete is equal to (current progress / maximum) * 100—for
example, (number of rows retrieved / maximum number of rows) * 100.
Using the progress You can either place the progress object directly onto a window or create a
bar in a window pop-up window that displays the progress bar, perhaps including a Cancel
button.
184 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
4 Establish the value that must be reached to equal 100%, such as the
number of rows displayed in a DataWindow or the number of bytes in the
file to be copied. This example sets the maximum as the number of
elements in the array containing DataWindow objects to be printed:
DataStore lds_data
Long ll_return
Integer li_count, li_max
String ls_dataobject[] = &
{"d_empall", "d_empbydept", "d_dept"}
lw_frame = gnv_app.of_GetFrame()
lw_frame.inv_statusbar.of_SetBarPosition(0)
6 At various points in your process (or at regular points in repetitive logic),
call the of_BarIncrement function to update the progress bar:
FOR li_count = 1 TO li_max
lds_data.DataObject = ls_dataobject[li_count]
lds_data.SetTransObject(SQLCA)
ll_return = lds_data.Retrieve()
IF ll_return <> -1 THEN
lw_frame.inv_statusbar.of_BarIncrement(1)
lds_data.Print()
END IF
NEXT
Progress bar options The PFC progress bar control provides options that you can set to control
progress bar behavior. With the exception of of_Maximum and of_Minimum,
you typically call these functions in the Constructor event of the u_progressbar
instance (u_progressbar) or the pfc_PreOpen event of the Frame window
(n_cst_winsrv_statusbar).
Progress bar options include:
• Maximum and minimum values Control the values that determine 0%
and 100%. You call different functions, depending on whether the progress
bar is in a window or in the status bar:
186 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
lw_frame = gnv_app.of_GetFrame()
SELECT COUNT(emp_id)
INTO :il_max
FROM Employee
USING SQLCA;
IF il_max > 0 THEN
lw_frame.inv_statusbar.of_SetBarMaximum &
(il_max)
lw_frame.inv_statusbar.of_SetBarMinimum(0)
END IF
• Display style Controls the text that displays in the progress bar:
• No text (bar only)
• Percent complete
• Current increment value
• User-specified text
You call different functions depending on whether the progress bar is in a
window or in the status bar:
• U_progressbar Call the of_SetDisplayStyle function, passing
either an integer or a u_progressbar constant to specify the
information displayed on the progress bar:
this.of_SetDisplayStyle(PCTCOMPLETE)
188 PowerBuilder
CHAPTER 5 Using PFC Visual Controls
• Text color Controls the color of text displayed in the progress bar. You
call different functions depending on whether the progress bar is in a
window or in the status bar:
• U_progressbar Call the of_SetTextColor function, passing the
color used for text:
this.of_SetTextColor(RGB(255, 0, 0))
• N_cst_winsrv_statusbar Call the of_SetBarTextColor function,
passing the color used for text:
this.inv_statusbar.of_SetBarTextColor &
(RGB(255, 0, 0))
• Autoreset Controls whether a completed progress bar remains filled
when it reaches 100%. You call different functions depending on whether
the progress bar is in a window or in the status bar:
• U_progressbar Call the of_SetAutoReset function:
this.of_SetAutoReset(TRUE)
• n_cst_winsrv_statusbar Call the of_SetBarAutoClear function:
this.inv_statusbar.of_SetBarAutoReset(TRUE)
• Default step value Controls the default increment value. This is the
value used when you call of_Increment (or of_BarIncrement) with no
arguments. The initial default step value is 10. You call different functions
depending on whether the progress bar is in a window or in the status bar:
• U_progressbar Call the of_SetStep function, specifying the
increment value to be used when calling of_Increment with no
arguments:
this.of_SetStep(5)
• N_cst_winsrv_statusbar Call the of_SetBarStep function,
specifying the increment value to be used when calling
of_BarIncrement with no arguments:
this.inv_statusbar.of_SetBarStep(5)
• Font options Controls the font and other display characteristics for the
progress bar text. You can call one or more of the following functions:
this.of_SetFontBold(TRUE)
this.of_SetFontFace("Monotype Corsiva")
this.of_SetFontFamily(Script!)
this.of_SetFontCharSet(1)
this.of_SetFontItalic(TRUE)
this.of_SetFontSize(10)
this.of_SetFontPitch(Variable!)
this.of_SetFontUnderline(TRUE)
190 PowerBuilder
CH A PTE R 6 Using PFC Windows and Menus
About this chapter This chapter explains how to use PFC windows and menus.
Contents
Topic Page
Using PFC windows 191
Using menus with PFC 201
192 PowerBuilder
CHAPTER 6 Using PFC Windows and Menus
this.inv_resize.of_Register &
(cb_ok, 0, 100, 0, 0)
this.inv_resize.of_Register &
(cb_cancel, 0, 100, 0, 0)
For specific usage information on individual window services, see “Window
services” on page 89.
Opening PFC In many applications, users open windows by selecting menu items. You can
windows use the PFC message router to help implement this process in a flexible and
consistent manner.
See “The message router” on page 41.
Message.StringParm = "w_emplist"
lnv_menu.of_SendMessage(this, "pfc_Open")
2 In the frame window’s pfc_Open event, add code to access the message
object and open the requested window:
String ls_window
w_sheet lw_sheet
ls_window = Message.StringParm
OpenSheet(lw_sheet, ls_window, this, 4, Original!)
Other options
There are other ways to open PFC windows. These include opening windows
directly from the menu item, extending the message object to contain passed
arguments, and defining additional frame window user events for opening
windows.
W_response includes three user events to which you add code that processes
the user action:
Event Use it to More information
pfc_Apply Process the window Many current applications contain
contents, leaving the an Apply CommandButton that
window open performs this functionality
pfc_Cancel Ignore the window You call this event from the
contents and close the CommandButton to which you
window assign the Cancel property
pfc_Default Process the window You call this event from the
contents and close the CommandButton to which you
window assign the Default property
3 Add code to support these controls. For example, add code to the
window’s pfc_PreOpen event to access values in an INI file for display in
SingleLineEdit controls.
194 PowerBuilder
CHAPTER 6 Using PFC Windows and Menus
ls_temp = trim(sle_base.Text)
SetProfileString("eisapp.ini", &
"Files", "base", ls_temp)
ls_temp = trim(sle_x1.Text)
SetProfileString("eisapp.ini", &
"Files", "extra1", ls_temp)
ls_temp = trim(sle_x2.Text)
SetProfileString("eisapp.ini", &
"Files", "extra2", ls_temp)
Close(this)
5 Add CommandButtons to trigger the corresponding event. For example,
an OK CommandButton should call the pfc_Default event:
parent.Event pfc_Default()
Using pfc_Apply
To maximize reusability, place processing in pfc_Apply and call
pfc_Apply from pfc_Default.
Although there are many ways to save data, it’s best to use the pfc_Save event
to save changes. In addition to simply calling the w_master pfc_Save event and
checking the return value, you can have complete control over update
processing by customizing and extending events called by the pfc_Save
process. You can:
• Save changes for other self-updating objects (including the n_ds
DataStore, the u_tvs TreeView, and the u_lvs Listview)
• Save changes for other controls
• Control which objects are updated and the order in which they are updated
• Save changes for objects on other windows
Self-updating objects
PFC integrates update functionality into certain objects called self-updating
objects. When you call the w_master pfc_Save event, it automatically updates
all self-updating objects on the window. All DataWindows are self-updating.
You must explicitly enable self-updating functionality for n_ds, u_lvs, u_tab,
and u_tvs. And you can add self-updating functionality to any visual or
nonvisual control.
For more on self-updating objects, see “Logical unit of work service” on page
111.
196 PowerBuilder
CHAPTER 6 Using PFC Windows and Menus
198 PowerBuilder
CHAPTER 6 Using PFC Windows and Menus
Adding code to extend You can customize and extend the pfc_Save process. For example, you can:
pfc_Save events
• Add code to the pfc_EndTran event to commit and roll back transactions
• Create and code a ue_Validation user event in non-PFC DataWindows to
perform validation
• Extend the pfc_Save process to include other types of window controls
IF ai_update_results = 1 THEN
li_return = SQLCA.of_Commit()
ELSE
li_return = SQLCA.of_Rollback()
END IF
IF li_return = 0 THEN
Return 1
ELSE
Return -1
END IF
Enabling self-updating By default, DataWindows are the only self-updating objects that are updatable.
objects All others (n_ds, u_lvs, u_tvs, u_tab, and any user-defined custom visual user
objects) are nonupdatable and must be specifically enabled.
// this = window
lpo_objs = this.control
li_count = UpperBound(lpo_objs)
lpo_objs[li_count + 1] = ids_data
this.of_SetUpdateObjects(lpo_objs)
200 PowerBuilder
CHAPTER 6 Using PFC Windows and Menus
Enabling a one-time PFC allows you to identify a specified group of controls and update them.
update
lpo_objs[1] = lv_1
lpo_objs[2] = dw_1
lv_1.of_SetUpdateable(TRUE)
2 Perform the one-time save by calling the pfc_SaveObjects event:
// this = window
li_return = this.Event pfc_SaveObjects(lpo_objs)
// Check for return codes 1 to -8
...
202 PowerBuilder
CHAPTER 6 Using PFC Windows and Menus
Creating menus Use the Menu painter to create your menus. Add just the items required for
your application, defining shortcut keys, accelerators, and toolbar bitmaps as
needed.
Communicating with Depending on your needs, you can use either your own menu-window
windows communication method or the PFC message router. When using the message
router, it’s best to use the menu service of_SendMessage function to call events
on the window. Each menu item calls of_SendMessage, passing the name of
the event to call. For example, the Clicked event for the Edit>Cut menu item
calls of_SendMessage as follows:
n_cst_menu lnv_menu
lnv_menu.of_SendMessage(this, "pfc_Cut")
There are two menu items that require special attention:
• File>Exit Call the application manager pfc_Exit event:
gnv_app.Event pfc_Exit()
• MRU menu items (File menu) Copy the menu item text to
Message.StringParm before calling of_SendMessage:
n_cst_menu lnv_menu
Message.StringParm = this.Text
lnv_menu.of_SendMessage(this, "pfc_MRUClicked")
Enabling items on the When the window sheet manager service is enabled, PFC menus automatically
Window menu enable and disable Window menu items as appropriate. If you are using the
sheet manager service and want that functionality in your menus, copy the code
from the pfc_m_master Window menu item Selected event.
Edit menu
Menu item Event triggered Object(s) containing user event
Undo pfc_Undo U_dw, u_em, u_mle, u_rte, and u_sle
Cut pfc_Cut U_ddlb, u_ddplb, u_dw, u_em,
u_mle, u_oc, u_rte, and u_sle
Copy pfc_Copy U_ddlb, u_ddplb, u_dw, u_em,
u_mle, u_oc, u_rte, and u_sle
Paste pfc_Paste U_ddlb, u_ddplb, u_dw, u_em,
u_mle, u_oc, u_rte, and u_sle
Paste Special pfc_PasteSpecial U_oc
Clear pfc_Clear U_ddlb, u_ddplb, u_dw, u_em,
u_mle, u_oc, u_rte, and u_sle
204 PowerBuilder
CHAPTER 6 Using PFC Windows and Menus
View menu
Menu item Action Object containing user event
Ruler pfc_Ruler U_dw and u_rte
Large Icons Empty menu item. Add logic to u_lvs to switch to large
icon view
Small Icons Empty menu item Add logic to u_lvs to switch to small
icon view; call from this menu item
List Empty menu item Add logic to u_lvs to switch to list
view; call from this menu item
Details Empty menu item Add logic to u_lvs to switch to detail
view; call from this menu item
Arrange Empty menu item Add logic to u_lvs to arrange icons by
Icons>By some common property; call from
this menu item
Arrange Empty menu item Add logic to u_lvs to arrange icons;
Icons>Auto call from this menu item
Arrange
First pfc_FirstPage U_dw and u_rte
Next pfc_NextPage U_dw and u_rte
Prior pfc_PreviousPage U_dw and u_rte
Last pfc_LastPage U_dw and u_rte
Sort pfc_SortDlg U_dw
Filter pfc_FilterDlg U_dw
Zoom pfc_Zoom U_dw
Insert menu
Menu item Event triggered Object(s) containing user event
File pfc_InsertFile U_rte
Picture pfc_InsertPicture U_rte
Object pfc_InsertObject U_oc
Tools menu
Menu item Event triggered Object(s) containing user event
Customize pfc_Toolbars W_frame
Toolbars
Window menu
Menu item Action Object containing user event
Cascade pfc_Cascade W_frame
Tile Horizontal pfc_TileHorizontal W_frame
Tile Vertical pfc_TileVertical W_frame
Layer pfc_Layer W_frame
Minimize All pfc_MinimizeAll W_frame
Windows
Undo pfc_UndoArrange W_frame
Help menu
Menu item Event triggered Object(s) containing user event
Help Topics pfc_Help W_master
About of_About N_cst_appmanager
206 PowerBuilder
CH A PTE R 7 PFC Utilities
About this chapter This chapter describes the PFC utilities and how to use them.
Contents
Topic Page
DataWindow Properties window 207
SQL Spy 210
Security 213
Library Extender 225
Migration Assistant 226
• Buffers Click the right mouse button to display a pop-up menu that
allows you to manipulate rows:
208 PowerBuilder
CHAPTER 7 PFC Utilities
Service dialog box Each service displays its own set of tabs that display its properties. This
tabs example shows the tabs for the sort service:
• General Displays information about the selected service:
• Syntax Displays the PFC syntax used for the selected service:
Usage Use the DataWindow Properties window to debug and test your application
and its use of DataWindow services.
SQL Spy
The SQL Spy utility traps and saves SQL automatically for DataWindows and
EXEC IMMEDIATE SQL statements. You can also use SQL Spy to display
and optionally modify DataWindow SQL statements, and to log native SQL.
Modifying SQL
If you are using an ODBC data source, you must set DisableBind to 1 in the
connect string.
210 PowerBuilder
CHAPTER 7 PFC Utilities
SQL Spy logs SQL to a file, which you can optionally display in a pop-up
window.
Usage To use SQL Spy, you call functions to enable the utility, to specify the log file,
and to control display of the w_sqlspy window. You can also call a function to
log native SQL.
You typically initialize SQL Spy from the application manager pfc_Open
event, although you can call SQL Spy functions from anywhere within an
application.
The w_sqlspy pop-up window displays the most recent entries in the log
file:
The w_sqlspyinspect dialog box allows you view and optionally modify SQL
before the DataWindow submits it to the database.
212 PowerBuilder
CHAPTER 7 PFC Utilities
Security
PFC provides a database-driven security system that requires minimal coding
in your applications. It allows you to populate a security database with
information, including:
• Window controls
• DataWindow columns
• User objects
• Menu items
You then create a matrix of users and groups, controlling access to these items.
At execution time, PFC selectively enables, disables, or hides secured items, as
specified in the security database.
Security by exception The PFC security capability provides security by exception. By default, the
security system uses the object’s current settings. This means that PFC
modifies settings only where specified explicitly in the security database.
The process The security administration utility is a PowerBuilder application you run in
order to:
• Define users and groups
• Run the security scanner
• Define security for objects and controls
• Associate users and groups with objects and controls
In your applications, you add code to implement security:
In this object Add this code
Application manager Call the n_cst_appmanager of_SetSecurity function to
enable the security service, n_cst_security
Application manager or Establish a Transaction object, connect to the security
frame window database, and call the n_cst_security of_InitSecurity
function
The of_InitSecurity function allows you to set a default
group for the user. The security system uses this group if
there are no other group settings for the user
Windows that require Call the of_SetSecurity function in the window Open
security event
214 PowerBuilder
CHAPTER 7 PFC Utilities
v To define users:
1 Add an Existing Application target to your PowerBuilder workspace
(select File>New from the PowerBuilder menu bar, click the Target tab,
click the Existing Application target icon, and click OK).
2 On the Choose Library and Application page of the target wizard, select
the pfcsecurity_admin application in the PFCSECAD.PBL library in the
PFC\Security directory and click Next.
3 On the Set Library Search Path page of the target wizard, add all the PFC
libraries to the library list and click Next.
4 On the Specify Target File page of the target wizard, click Finish.
The default target filename has the same name as the security application
you selected with a PBT extension.
5 Select Run>Select And Run from the PowerBuilder menu bar, select the
security_admin target, and click OK.
8 Type a user name and description. The user name must correspond to a
user ID that your application can access at runtime.
9 Click OK.
10 Continue adding users as necessary.
11 Select File>Save from the menu bar.
v To define groups:
1 Right-click in the Groups column and select Add Group.
216 PowerBuilder
CHAPTER 7 PFC Utilities
2 Type a group name, description, and priority. Zero is the highest priority;
however, user specifications override group specifications.
3 Click OK.
4 Continue adding groups as necessary.
5 Select File>Save from the menu bar.
218 PowerBuilder
CHAPTER 7 PFC Utilities
Selecting objects
To minimize the size of the security database, do not select objects for
which you will never assign security.
5 Click Scan.
220 PowerBuilder
CHAPTER 7 PFC Utilities
3 Click the Users drop-down list and select a user for whom to set security.
4 Double-click the application containing the objects to be secured.
5 Select the All radio button (if it’s not already selected).
You are now ready to secure items.
6 For items to be secured, use the Status drop-down list to specify Enabled,
Disabled, or Invisible (Not Set makes no change to the object’s settings).
7 When you are finished, select File>Save from the menu bar.
222 PowerBuilder
CHAPTER 7 PFC Utilities
8 Continue with the object until you are finished with all users and groups.
9 Continue with other objects.
gnv_app.itr_security.of_Connect()
li_return = &
gnv_app.inv_security.of_InitSecurity &
(gnv_app.itr_security, "EISAPP", &
gnv_app.of_GetUserID(), "Default")
224 PowerBuilder
CHAPTER 7 PFC Utilities
Usage To enable security for all of your application’s users, move the PFC security
tables to a server database.
Library Extender
You use the PFC Library Extender to automatically create and populate an
intermediate extension level between two existing levels, redefining the
inheritance hierarchy.
By supplying the Library Extender with the names of the upper and lower
levels, the Library Extender:
• Creates a new PBL
• Creates objects in the new PBL that descend from objects in the upper
level
• Recreates objects in the lower level such that they descend from objects in
the new PBL
Typically you would use the Library Extender to add an intermediate level (or
levels) between the PFC ancestor level and the PFC extension level. Adding
corporate and departmental extensions to intermediate extension levels allows
the application programmer to make full use of the extension level.
Usage The Library Extender is available on the Tool tab in the New dialog box.
For complete usage information, see the Library Extender online Help.
Migration Assistant
The Migration Assistant scans PowerBuilder libraries (PBLs) and highlights
usage of obsolete functions and events. Obsolete functions and events still
work in the current version of PowerBuilder but may not work in future
versions. If you plan on maintaining an application in the future, it's best to use
current syntax and events.
Usage The Migration Assistant is available on the Tool tab in the New dialog box.
For complete usage information, see the Migration Assistant online Help.
226 PowerBuilder
CH A PTE R 8 Deploying a PFC Application
About this chapter This chapter explains considerations related to PFC application
deployment.
Contents
Topic Page
Choosing a deployment strategy 227
Using PBR files 229
Deploying database tables 229
Deploying PFC dialog box Help 230
Four deployment A PFC application has the same four deployment options as any other
options PowerBuilder application. Each of these options has relative advantages and
disadvantages that you need to consider before choosing a deployment
strategy:
Deployment
option Advantages Disadvantages
Pcode Single file Large (minimum 3M)
executable Simple deployment To update, you must regenerate the
entire application
Compiled Single file Very large (minimum 8M)
executable Simple deployment To update, you must regenerate the
Compiled code entire application
Pcode PBDs Smaller EXE Multiple files
To update, you can Needs separate set of physical files
replace a single PBD
Compiled Smaller EXE Multiple files
DLLs Compiled code Needs separate set of physical files
To update, you can
replace a single DLL
228 PowerBuilder
CHAPTER 8 Deploying a PFC Application
What to do To minimize the number of database connections held by your application, it’s
usually best to move these tables to the application database.
In any case, your application deployment strategy must provide for user access
to all database tables required by the application. This includes installing client
software, updating INI files, updating registry entries, and all other database
deployment considerations outlined in the database deployment discussion in
Application Techniques.
230 PowerBuilder
PART 4 PFC Tutorial
2 Type PFC Tutorial in the File Name box and click OK.
An icon for the new workspace displays in the System Tree. If the System
Tree is not displayed, select the System Tree tool in the toolbar or select
the System Tree menu item in the Window menu.
234 PowerBuilder
Lesson 1 Generate a PFC Application
4 Click Next twice until you see the Specify New Application And Library
page.
Type my_pfc_app in the Application Name box.
The wizard resets default filenames for the application library and target.
8 Click the ellipsis button next to the Library Search Path list box.
A standard library selection dialog box displays.
9 Navigate to the PFC directory (one level above the PFC Tutorial
directory).
Use CTRL+click or SHIFT+click to select these libraries from the main
layer and the extension layer:
10 Click Open.
The Library Search Path list box redisplays with PFC libraries added to the
list.
11 Click Next twice until you see the Ready To Create Application page.
PowerBuilder summarizes your wizard selections in a list box. The
Generate To-Do List check box is selected.
12 Click Finish.
236 PowerBuilder
Lesson 1 Generate a PFC Application
When you use the Template Application wizard to create a PFC application, it
redirects Application object processing to a PFC application manager. This
strategy provides many benefits, including extensibility and reuse.
You implement the application manager through the n_cst_appmanager
custom class user object or a customized descendant. This tutorial implements
the application manager by creating a descendant of n_cst_appmanager. You
then initialize application-wide variables in the new application manager.
For more information on implementing the application manager, see Chapter
3, “PFC Programming Basics”.
4 Make sure Untitled displays as the name of the user object in the first
drop-down list of the Script view.
Make sure the Constructor event displays as the selected event in the
second drop-down list of the Script view.
The purple icon in front of the Constructor event name indicates that a
script is coded for this event in an ancestor object. In PowerBuilder, events
(unlike functions) are triggered first in the ancestor object, then in the
descendent object.
Property Value
is_appinifile drive:\pathname\pfc\tutorial\pfctutor.ini
is_helpfile drive:\pathname\pfc\tutorial\pfctutor.hlp
is_version PFC 9.0
is_logo drive:\pathname\pfc\tutorial\tutsport.bmp
is_copyright PFC tutorial application
238 PowerBuilder
Lesson 1 Generate a PFC Application
The first two properties establish an INI file and online Help file for use
with the application. The other properties establish information that will
be used in the application’s About dialog box and splash screen.
9 Click OK.
PowerBuilder saves the user object and redisplays it in the User Object
painter workspace. The n_cst_tutappmanager name now displays in the
painter title bar, in the Non-Visual Object List view, and in the first
drop-down list of the Script view.
240 PowerBuilder
Lesson 1 Generate a PFC Application
When you generate a PFC application using the Template Application wizard,
all the events of the Application object call corresponding events in the
application manager (n_cst_appmanager or a descendant of
n_cst_appmanager). For example, the Open event calls the application
manager’s pfc_Open event, the Close event calls pfc_Close, and so on.
PFC uses the gnv_app global variable to access the application manager at
runtime. Now you will modify this variable to use the customized application
manager and you will review the events of the Application object that are
redirected to the application manager.
2 Click OK.
The Application painter displays the my_pfc_app Application object.
3 Make sure the Script view displays the Open event for the my_pfc_app
Application object.
The first line of code is an assignment statement that creates an instance of
the application manager and assigns it to the global variable gnv_app. The
next line of code calls the pfc_Open event of the application manager.
242 PowerBuilder
Lesson 1 Generate a PFC Application
Now you will look at the definition for the default Transaction object. In
standard PowerBuilder applications, SQLCA (SQL Communications Area) is
defined as the default Transaction object. In PFC applications, the default
Transaction object is assigned by the PFC transaction object service.
The n_tr user object is a Transaction object defined in pfemain.pbl. It inherits
from the pfc_n_tr object in the pfcmain.pbl library. In this exercise, you will
see how the SQLCA Transaction object is registered with the PFC transaction
registration service (the registration was set automatically by the Template
Application wizard).
244 PowerBuilder
Lesson 1 Generate a PFC Application
246 PowerBuilder
LE S S O N 2 Create the Frame Window
Now you will create a frame window by inheriting from w_frame. Then you
will define a script for the pfc_Open script for the new frame window. PFC
calls this event when the user selects File>Open from the menu bar. You can
call it from other parts of the application as necessary to open sheet windows.
3 Type PFC Tutorial Frame in the Title box in the Properties view.
Click the Toolbar tab in the Properties view.
Clear the ToolbarVisible check box.
You will not use a toolbar in the frame window, only in the sheet windows.
248 PowerBuilder
Lesson 2 Create the Frame Window
ls_sheet = Message.StringParm
OpenSheet(lw_sheet, ls_sheet, this, 0, Layered!)
This script will open an instance of the sheet window specified in the
passed StringParm. You will initialize the StringParm value for two sheet
windows later in this tutorial.
Now you will define two scripts: one for the pfc_PreOpen event to enable the
sheet manager and status bar services, and one for the pfc_PostOpen event to
connect to the database.
1 Select pfc_PreOpen from the second drop-down list in the Script view
and type these lines:
this.of_SetSheetManager(TRUE)
this.of_SetStatusBar(TRUE)
this.inv_statusbar.of_SetTimer(TRUE)
This script enables the sheet management service, which provides the
ability to minimize all sheets and undo the last sheet arrange command. It
also enables the status bar service, displaying date and time information in
the bottom-right corner of the frame.
2 Select pfc_PostOpen from the second drop-down list in the Script view
and type these lines:
Integer li_return
String ls_inifile
ls_inifile = gnv_app.of_GetAppIniFile()
IF SQLCA.of_Init(ls_inifile,"Database") = -1 THEN
MessageBox("Database", &
"Error initializing from " + ls_inifile)
HALT CLOSE
END IF
IF SQLCA.of_Connect() = -1 THEN
MessageBox("Database", &
"Unable to connect using " + ls_inifile)
HALT CLOSE
ELSE
this.SetMicroHelp ("Connection complete")
END IF
250 PowerBuilder
Lesson 2 Create the Frame Window
5 Click OK.
Select File>Close from the menu bar.
PowerBuilder saves the window and you close the Window painter.
Now you will add code to the application manager pfc_Open event to open the
frame window.
2 Click OK.
The User Object painter workspace displays.
252 PowerBuilder
Lesson 2 Create the Frame Window
1 Click the Run or the Select And Run button in the PowerBar.
Make sure the my_pfc_app target is selected and click OK.
The splash window displays and the database connection is established.
The splash window uses information you entered for instance variables of
the n_cst_tutappmanager user object:
The MDI frame window displays behind the splash window and remains
open after the splash window closes.
254 PowerBuilder
LE S S O N 3 Create Menus
Menu usage
This tutorial uses one approach to menu implementation. PFC allows you
to implement other approaches, include modifying m_master directly and
defining menus from scratch.
Now you will create a master menu for the tutorial by inheriting from the
m_master menu.
5 Click OK.
PowerBuilder saves the menu.
256 PowerBuilder
Lesson 3 Create Menus
Now you will add and modify menu items on m_tut_master. You will use the
Script, WYSIWYG, and Properties views of the Menu painter to make these
changes.
2 Select the Clicked event in the second drop-down list in the Script
view.
The purple icon in front of the event name indicates that the Clicked event
in an ancestor menu is scripted. By default, events are extended: script is
processed first from ancestor objects, then from descendent objects.
258 PowerBuilder
Lesson 3 Create Menus
7 Type Product list for the MicroHelp box in the Properties view.
Double-click Product List in the WYSIWYG view.
The Script view displays m_file.m_open.m_productlist in the first
drop-down list. When you created the Product List menu item,
PowerBuilder added it to the list.
8 Make sure the Clicked event is selected in the second drop-down list
in the Script view.
Type these lines:
Message.StringParm = "w_products"
of_SendMessage("pfc_Open")
These lines initialize the StringParm value and call the of_SendMessage
menu function, which then calls the pfc_Open event on the frame window.
Menu service
You can also call the n_cst_menu of_SendMessage function to perform
this functionality.
10 Type Product &Sales Report for the new menu item and click ENTER.
Type Product sales report in the MicroHelp in the Properties view.
Double-click Product Sales Report in the WYSIWYG view.
The Script view displays m_file.m_open.m_productsalesreport in the first
drop-down list.
11 Make sure the Clicked event is selected in the second drop-down list.
Type the following lines:
Message.StringParm = "w_product_report"
of_SendMessage("pfc_Open")
These lines initialize the StringParm value and call the of_SendMessage
menu function, which then calls the pfc_Open event on the frame window.
13 Clear the Visible check box on the General page of the Properties view.
Select the Toolbar tab of the Properties view.
Clear the ToolbarItemVisible check box on the Toolbar page.
Since you will not be adding code to the File>New menu Clicked event in
the tutorial application, you make the menu item and its toolbar picture
invisible at runtime.
In the previous lesson you made a selection to prevent the display of a
toolbar for the application frame window. But the user can still opt to
display a frame menu toolbar from an application that uses PFC window
services. Now you ensure that even if the user makes this selection, the
File>New toolbar picture will not be displayed.
260 PowerBuilder
Lesson 3 Create Menus
Now you will create a frame menu by inheriting from the m_tut_master menu.
The main portion of this exercise is hiding menus and menu items that don’t
apply when only the frame is displayed.
5 Using the WYSIWYG view and the Properties view, hide the following
menu bar items: Edit menu, View menu, and Tools menu.
The frame menu bar for the tutorial application will only show the File,
Window, and Help menus.
262 PowerBuilder
Lesson 3 Create Menus
Now you will associate the frame window with m_tut_frame, the frame menu
you just created.
3 Click the ellipsis button next to the MenuName box in the Properties
view.
The Select Object dialog box displays:
264 PowerBuilder
Lesson 3 Create Menus
Now you will create a sheet menu by inheriting from m_tut_master, the PFC
tutorial master menu.
266 PowerBuilder
Lesson 3 Create Menus
Now you will create a sheet menu for w_product_report by inheriting from
m_tut_master (the PFC tutorial master menu).
268 PowerBuilder
LE S S O N 4 Build the First Sheet Window
You will now add a library to the application target library list. The library you
will add contains DataWindow objects created for this tutorial.
3 Click OK.
270 PowerBuilder
Lesson 4 Build the First Sheet Window
Now you will create a sheet window by inheriting from the w_sheet window.
Now you will add a DataWindow control to the w_products window. This
DataWindow control is based on PFC’s u_dw DataWindow user object.
1 Select and click the UserObj button in PainterBar1 (not the PowerBar).
or
Select Insert>Control>UserObject from the menu bar.
272 PowerBuilder
Lesson 4 Build the First Sheet Window
4 Select the text dw_1 in the Name box of the Properties view.
Type dw_list in the Name box.
5 Click the ellipsis button next to the DataObject box in the Properties
view.
The Select Object dialog box displays.
7 Make the control almost as big as the window in the Layout view,
maximizing the Layout view if necessary:
274 PowerBuilder
Lesson 4 Build the First Sheet Window
Now you will use the Script view of the Window painter to add PowerScript
code to the DataWindow control. The script you will add calls functions to
enable PFC DataWindow sort, row selection, and row management services.
1 Select dw_list from the first drop-down list in the Script view.
Select the Constructor event from the second drop-down list.
The third drop-down list in the Script view displays the parent window
name, w_products. There is no code yet for the user object Constructor
event, either in the current object or in the u_dw and pfc_u_dw ancestor
objects.
3 Add the following script after the lines you just typed:
this.inv_rowselect.of_SetStyle &
(dw_list.inv_rowselect.EXTENDED)
this.inv_sort.of_SetStyle &
(dw_list.inv_sort.DRAGDROP)
this.inv_sort.of_SetColumnHeader(TRUE)
These lines initialize the row selection and sort services.
The row selection service of_SetStyle function enables extended row
selection with the CTRL and SHIFT keys. The sort service of_SetStyle
function instructs PFC to display a drag-and-drop sort dialog box when the
user selects View>Sort from the menu bar.
The sort service of_SetColumnHeader function enables sorting by
clicking on column headers, a feature found in many current applications.
4 Add the following script after the lines you just typed:
IF this.of_Retrieve() = -1 THEN
SQLCA.of_Rollback()
MessageBox("Error","Retrieve error")
ELSE
SQLCA.of_Commit()
this.SetFocus()
END IF
These lines call the of_Retrieve function for the user object. Since this
function is not coded in the u_dw control, PowerBuilder will parse the
code for the same function in the pfc_u_dw ancestor.
276 PowerBuilder
Lesson 4 Build the First Sheet Window
Retrieve rows
Where you are
Add a library to the library list
Create a descendent window
Add a DataWindow control
Enable DataWindow services
> Retrieve rows
Run the application
Now you will add PowerScript code that retrieves rows from the database. In
the last exercise, the call you made to the of_Retrieve function triggers the
pfc_Retrieve event when the PFC Linkage service is not running. (You do not
start the Linkage service in the tutorial application.)
Since events are extended by default, PowerBuilder parses the event script in
both the pfc_u_dw ancestor, and then in the current u_dw control.
1 Select pfc_Retrieve from the second drop-down list in the Script view.
There is already script for this event in the pfc_u_dw ancestor control.
Now you will add code to extend the ancestor script.
278 PowerBuilder
Lesson 4 Build the First Sheet Window
Now you will make sure the sheet window opens properly by running the PFC
tutorial application.
3 Select multiple rows by holding the CTRL or SHIFT key down while
clicking before the first column in the rows you want to select.
Sort rows by clicking in the column headers.
Click the same column header twice to change the order of the sort.
You test the PFC selection and sort services.
4 Click the right mouse button over one of the columns in the
DataWindow.
280 PowerBuilder
Lesson 4 Build the First Sheet Window
The Calculator Properties dialog box displays. The 2 columns that have
numeric data types (id and unit_price) are listed on the General page of the
Calculator Properties dialog box.
9 Click OK twice.
You can now use a drop-down calculator in the Unit Price column to
change column values.
282 PowerBuilder
You can try enabling other DataWindow services and changing their
properties.
284 PowerBuilder
LE S S O N 5 Build the Second Sheet Window
You inherit from PFC’s w_sheet window to create a second MDI sheet
window.
In this lesson you will:
• Create a descendent window
• Add a DataWindow control
• Enable report and print preview services
• Run the application
Now you will create a sheet window by inheriting from the w_sheet window.
3 Type Product Sales Report in the Title box in the Properties view.
This defines a title for the new sheet window.
4 Click the ellipsis button next to the MenuName box in the Properties
view.
The Select Object dialog box displays.
286 PowerBuilder
Lesson 5 Build the Second Sheet Window
Now you will create a DataWindow control using PFC’s u_dw DataWindow
user object.
1 Select and click the UserObj button in PainterBar1 (not the PowerBar).
or
Select Insert>Control>UserObject from the menu bar.
The Select User Object dialog box displays.
3 Select the text dw_1 in the Name box in the Properties view.
Type dw_report in the Name box.
Select the HScrollBar check box.
You add a horizontal scroll bar to the DataWindow that will be visible at
runtime.
6 Make the control almost as big as the window in the Layout view,
maximizing the Layout view if necessary:
288 PowerBuilder
Lesson 5 Build the Second Sheet Window
Now you will add PowerScript code to call functions that enable the PFC
DataWindow report service and print preview service. You will also add code
that retrieves rows from the database.
1 Select dw_report from the first drop-down list in the Script view.
Select the Constructor event from the second drop-down list.
Type the following script for the Constructor event:
this.of_SetReport(TRUE)
this.of_SetPrintPreview(TRUE)
this.of_SetTransObject(SQLCA)
this.of_SetUpdateable(FALSE)
These lines enable the report and print preview services, set SQLCA as the
Transaction object and register the DataWindow as nonupdatable. In a
nonupdatable DataWindow, PFC disregards default CloseQuery
processing.
2 Add the following script after the lines you just typed:
IF this.of_Retrieve() = -1 THEN
SQLCA.of_Rollback()
MessageBox("Error","Retrieve error")
ELSE
SQLCA.of_Commit( )
END IF
These lines call the u_dw of_Retrieve event for the DataWindow.
Precoded report service events and functions handle all other processing.
3 Select pfc_Retrieve from the second drop-down list in the Script view.
PowerBuilder compiles the script for the Constructor event.
290 PowerBuilder
Lesson 5 Build the Second Sheet Window
The print preview shows the printable area inside a blue box. You may
need to scroll or zoom the preview window to see the entire report.
5 Change the Zoom dialog box setting to display the entire report and
click OK.
Print the report if wanted.
292 PowerBuilder
Index
A buffers
DataWindow caching service 50
aggregate relationship 11
DataWindow properties service 208
ancestor level
contents 12, 15
interdependencies 20
ancestor override (tutorial example) 257 C
application manager
caching DataWindow objects, application service 50
customizing descendant 237
calculator control 169
gnv_app global variable 241
calendar control 174
logon dialog box 32
class user objects, custom 5
services 31, 49
components 15
setting up 29
composite DataWindow 80
splash screen 31
conversion service 98
Application object
copy 131
creation 233
custom class user objects 5
redirecting events from 241
custom visual user objects 5, 129
using separate physical files 20
cut 131
application services
application preference 53
DataWindow caching 50
debugging 52 D
error message 57
list 49 database
most recently used object 54 connecting 250
security 60 retrieving 137
transaction registration 62 security 224
associative relationship 11 updating 92
autorollback 44, 62 DataWindow caching, application service 50
autoscroll, enabling 133 DataWindow control
autoselect, enabling 133 creating (tutorial) 272, 287
retrieving 137
SQL Spy 210
using u_dw 135
B DataWindow object
accessing object information 65
base-10, converting to binary 104
caching 50
binary, converting to base-10 104
DataWindow Properties window 207
bits, accessing 104
294 PowerBuilder
Index
H menu services 95
menus
Help
creating your own 202
dialog box Help 230
extending 202
enabling, for an application 46
inheritance strategies 202
modifying 255
pop-up 131, 206
I services overview 201
standard menu items 204
inclusional polymorphism 8 message logging 57, 211
inheritance 7 message router
INI file service 102 of_pfc_MessageRouter event 42
INI files of_SendMessage function 42
INI file service 102 overview 41
window settings 93 using 91
Message.StringParm (tutorial example) 259
metaclass service 111
MicroHelp, automatic update 134
L Migration Assistant 226
libraries most recently used object service 54
adding to search path 29, 270 multirow selection, row selection service 84
PFC 15, 235 multitable update service 74
Library Extender 226
linkage service 71
list service 114
ListView 141 N
logical unit of work service n_cst_appmanager
usage 111 defining gnv_app 241
w_master pfc_Save process 195 setting up 29
logon dialog box 32, 242 n_cst_apppreference 53
n_cst_debug 52
n_cst_dwcache 50
n_cst_dwsrv 64
M n_cst_dwsrv_dropdownsearch 67
m_dw pop-up menu 131 n_cst_dwsrv_filter 67
m_edit pop-up menu 131 n_cst_dwsrv_find 70
m_lvs pop-up menu 131 n_cst_dwsrv_linkage 71
m_master, inheriting from 256 n_cst_dwsrv_multitable 74
m_oc pop-up menu 131 n_cst_dwsrv_printpreview
m_tvs pop-up menu 131 tutorial usage 289
master/detail processing 71 usage 75
MDI applications n_cst_dwsrv_property
building 33 tutorial usage 275
frame menu (tutorial) 262 usage 76
frame window (tutorial) 247 n_cst_dwsrv_querymode 77
sheet management service 94
status bar service 95
296 PowerBuilder
Index
T
Tab control
S resize service 96
SDI applications, building 34 usage 165
security service timing service 126
database 224 toolbars, controlling 92
implementing security in an application 223 transaction management 43
usage 60 Transaction object
security utility initializing 44
administration utility 215 registration 62
assigning to users and groups 221 using n_tr as 244
overview 213
298 PowerBuilder
Z
zoom
absolute 75
relative 81