PFC Users Guide PDF
PFC Users Guide PDF
PowerBuilder
8
DOCUMENT ID: 37779-01-0800-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, 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, AnswerBase, Anywhere Studio, Application Manager,
AppModeler, APT Workbench, APT-Build, APT-Edit, APT-Execute, APT-FORMS, APT-Translator, APT-Library, Backup Server,
ClearConnect, Client-Library, Client Services, Data Pipeline, Data Workbench, DataArchitect, Database Analyzer, DataExpress,
DataServer, DataWindow, DB-Library, dbQueue, Developers Workbench, Direct Connect Anywhere, DirectConnect, Distribution
Director, E-Anywhere, E-Whatever, 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, EWA, Financial Fusion, Financial Fusion Server, Gateway Manager, ImpactNow, InfoMaker, Information
Anywhere, Information Everywhere, InformationConnect, InternetBuilder, iScript, Jaguar CTS, jConnect for JDBC, KnowledgeBase,
MainframeConnect, Maintenance Express, MAP, MDI Access Server, MDI Database Gateway, media.splash, MetaWorks, MySupport,
Net-Gateway, Net-Library, ObjectConnect, ObjectCycle, OmniConnect, OmniSQL Access Module, OmniSQL Toolkit, 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 DB-Net, 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, Report Workbench, Report-Execute, Replication Agent, Replication Driver, Replication Server,
Replication Server Manager, Replication Toolkit, Resource Manager, RW-DisplayLib, RW-Library, 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, 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, Transact-SQL, Translation Toolkit,
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. 3/01
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.
iii
Contents
iv
Contents
v
Contents
vi
Contents
vii
About This Book
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
ix
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 4
Understanding PowerBuilder 5
How PFC uses object orientation 10
How PFC uses the extension level 13
The PFC components 16
3
Understanding PFC
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.
4
Chapter 1 About the PowerBuilder Foundation Class Library
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.
5
Understanding PowerBuilder
Visual user objects A visual user object is a reusable visual control or set of
visual controls with a predefined behavior. PFC includes two types of visual
user objects:
• Standard visual user objects PFC provides a full set of standard visual
user objects. Each PFC standard visual user object corresponds to a
PowerBuilder window control. These objects include predefined
behaviors that provide complete integration with PFC services. In
particular, the u_dw DataWindow user object, offers extensive
functionality and integration with PFC services.
• Custom visual user objects PFC also use custom visual user objects.
Custom visual user objects contain a group of window controls. These
objects provide advanced functionality for use in specific situations.
PFC does not use external visual user objects. For complete information on
visual user objects, see the PowerBuilder User’s Guide.
Class user objects A class user object is a reusable nonvisual control you
use to implement processing with no visual component. PFC includes two
types of class user objects:
• Standard class user objects Inherit their definitions from built-in
PowerBuilder system objects. PFC provides standard class user objects for
transaction, error, and all other extendable system objects.
• Custom class user objects Inherit their definitions from the
PowerBuilder NonVisualObject class. Custom class user objects
encapsulate data and code. This type of class user object allows you to
define an object class from scratch.
PFC uses custom class user objects to implement many of its services and
provides functions to enable instances of these service objects.
It also provides reference variables, which are pointers to an instantiated
object. You use a reference variable to access an object’s instance
variables, functions, and events.
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.
6
Chapter 1 About the PowerBuilder Foundation Class Library
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)
Access Object functions can be Events always have public
public, private, or protected access
Overloading Functions of the same name Events cannot be overloaded
can take different arguments
Object-oriented programming
Object-oriented programming tools support three fundamental principles:
inheritance, encapsulation, and polymorphism.
7
Understanding PowerBuilder
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:
• With operational polymorphism, separate unrelated objects define a
function with the same name:
8
Chapter 1 About the PowerBuilder Foundation Class Library
9
How PFC uses object orientation
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
Dropdown search
Filter
Find
Linkage
Multitable update
Properties
Querymode
Report
Required column
10
Chapter 1 About the PowerBuilder Foundation Class Library
11
How PFC uses object orientation
For more information on PFC service types and how to use them, see Chapter
4, "Using PFC Services".
12
Chapter 1 About the PowerBuilder Foundation Class Library
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.
13
How PFC uses the extension level
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.
14
Chapter 1 About the PowerBuilder Foundation Class Library
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:
15
The PFC components
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
16
Chapter 1 About the PowerBuilder Foundation Class Library
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 253.
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.
17
The PFC components
18
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 22
Choosing an extension strategy 23
Defining a new service 28
21
Using PFC to design a class library
22
Chapter 2 Designing a Class Library
23
Choosing an extension strategy
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.
24
Chapter 2 Designing a Class Library
25
Choosing an extension strategy
26
Chapter 2 Designing a Class Library
27
Defining a new service
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.
28
Chapter 2 Designing a Class Library
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
29
Defining a new service
30
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 34
Building applications 38
Using attribute objects 44
Using PFC constants 47
The message router 48
Transaction management with PFC 51
Calling ancestor functions and events 53
Adding online Help to an application 54
Installing PFC upgrades 55
33
Setting up the application manager
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
34
Chapter 3 PFC Programming Basics
4 Add code to your application’s Close event to call the pfc_Close event and
destroy n_cst_appmanager:
gnv_app.Event pfc_Close( )
DESTROY gnv_app
5 Add code to your application’s SystemError event to call the
pfc_SystemError event:
gnv_app.Event pfc_SystemError( )
6 Close the Application painter and save the changes.
7 Display the User Object painter and open n_cst_appmanager, found in
PFEAPSRV.PBL. (Optionally, use an application-specific descendant of
n_cst_appmanager.)
8 Call n_cst_appmanager functions in the Constructor event to initialize
instance variables for version, company, and INI file.
9 Call n_cst_appmanager functions in the pfc_Open event to enable the
application services you want:
To enable this service Call this function
Application preference of_SetAppPreference
DataWindow caching of_SetDWCache
Error of_SetError
Most recently used object of_SetMRU
Transaction registration of_SetTrRegistration
Security of_SetSecurity
Debug of_SetDebug
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.
35
Setting up the application manager
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)
36
Chapter 3 PFC Programming Basics
IF SQLCA.of_Connect() = -1 THEN
Return -1
ELSE
gnv_app.of_SetUserID(as_userid)
Return 1
END IF
37
Building applications
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 220.
38
Chapter 3 PFC Programming Basics
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 220.
39
Building applications
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.
40
Chapter 3 PFC Programming Basics
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 53.
41
Building applications
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 popup 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
42
Chapter 3 PFC Programming Basics
43
Using attribute objects
44
Chapter 3 PFC Programming Basics
45
Using attribute objects
46
Chapter 3 PFC Programming Basics
Coding conventions
The PFC convention is to code constants in all caps.
47
The message router
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.
48
Chapter 3 PFC Programming Basics
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:
49
The message router
50
Chapter 3 PFC Programming Basics
v To use n_tr:
1 If you are using a Transaction object other than SQLCA, create it.
51
Transaction management with PFC
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
ELSE
gnv_app.of_GetFrame().SetMicroHelp &
("Connection complete")
END IF
5 Call n_tr functions as needed.
52
Chapter 3 PFC Programming Basics
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
53
Adding online Help to an application
54
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:
55
Installing PFC upgrades
56
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 58
DataWindow services 72
Window services 98
Menu service 105
Resize service 106
Conversion service 108
Date/Time service 110
File service 112
INI file service 114
Numerical service 116
Platform service 118
Selection service 120
SQL parsing service 122
String-handling service 124
Metaclass service 126
Logical unit of work service 127
List service 130
Timing service 143
57
Application services
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.
58
Chapter 4 Using PFC Services
59
Application 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.
60
Chapter 4 Using PFC Services
61
Application services
• INI file Call the of_SetUserINIFile function, specifying the INI file that
contains application preference information.
62
Chapter 4 Using PFC Services
63
Application services
// 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()
64
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()
65
Application services
• 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.
66
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.
67
Application services
gnv_app.inv_error.of_Message &
("EIS0210")
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.
68
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
69
Application services
Usage Use this service to keep track of transactions when your application uses more
than one transaction.
When your application closes, this object automatically destroys all open
registered transactions. Set the n_tr ib_autorollback instance variable to TRUE
to cause closing transactions to COMMIT; set ib_autorollback to FALSE to
cause a ROLLBACK. You set this instance variable with the n_tr
of_SetAutoRollback function.
v To register a transaction:
• Call the n_cst_trregistration of_Register function:
gnv_app.inv_trregistration.of_Register(SQLCA)
70
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
71
DataWindow services
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)
Dropdown 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
72
Chapter 4 Using PFC Services
DataStore services
This service is available to the n_ds DataStore via the n_cst_dssrv user object.
73
DataWindow services
li_return = &
dw_emplist.inv_base.of_PopulateDDDWs()
gnv_app.of_GetFrame().SetMicroHelp &
(String(li_return) + " DDDW columns
refreshed")
74
Chapter 4 Using PFC Services
75
DataWindow 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:
76
Chapter 4 Using PFC Services
77
DataWindow services
78
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
79
DataWindow services
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.
80
Chapter 4 Using PFC Services
dw_detail.inv_linkage.of_SetUpdateStyle &
(dw_detail.inv_linkage.BOTTOMUP)
6 Establish the action taken by the detail when a row changes in the master
by calling the of_SetStyle function.
This example specifies that the detail DataWindow retrieves a row
whenever the master changes:
dw_detail.inv_linkage.of_SetStyle &
(dw_detail.inv_linkage.RETRIEVE)
7 Call the master DataWindow’s of_Retrieve function:
IF dw_master.of_Retrieve( ) = -1 THEN
MessageBox("Error","Retrieve error")
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.
81
DataWindow services
82
Chapter 4 Using PFC Services
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.
dw_project.inv_multitable.of_Register &
("project", ls_projcols)
dw_project.inv_multitable.of_Register &
("task", ls_taskcols)
83
DataWindow services
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.
84
Chapter 4 Using PFC Services
Statistics
Properties of all objects on the DataWindow object
See "DataWindow Properties window" on page 228.
Usage Use this service to enable display of the DataWindow Properties window.
85
DataWindow 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.
86
Chapter 4 Using PFC Services
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.
DataStore services
This service is available to the n_ds DataStore via the n_cst_dssrv_report user
object.
87
DataWindow services
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.
88
Chapter 4 Using PFC Services
89
DataWindow services
The service allows you to specify columns for which PowerBuilder should still
perform required fields processing.
90
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 popup 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
91
DataWindow services
PFC calls this event automatically when the user selects Delete from the
m_dw popup menu.
To allow users to select multiple rows, use the row selection service.
92
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.
93
DataWindow services
94
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:
95
DataWindow services
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)
v To specify whether PFC sort dialog boxes sort on display values or data
values:
• Call the of_SetUseDisplay function:
96
Chapter 4 Using PFC Services
dw_emp.inv_sort.of_SetUseDisplay(TRUE)
97
Window services
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
98
Chapter 4 Using PFC Services
99
Window services
of_SendMessage("pfc_CheckStatus")
The of_SendMessage function passes the request to n_cst_menu
of_SendMessage function, which calls the current window’s
pfc_MessageRouter user event, which calls the specified user event
automatically.
100
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.
101
Window services
102
Chapter 4 Using PFC Services
of_GetSheetCount
of_GetSheets
of_GetSheetsByClass
of_GetSheetsByTitle
PFC destroys the service automatically when the frame window closes.
103
Window services
104
Chapter 4 Using PFC Services
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")
105
Resize service
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.
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
106
Chapter 4 Using PFC Services
107
Conversion service
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
108
Chapter 4 Using PFC Services
String ls_checked
109
Date/Time service
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
• Determine the number of weeks between two date/time values
• Determine the number of seconds between two date/time values
• Determine the number of milliseconds between two date/time values
• Determine if a date is valid
• Determine if a date falls on a weekday
• Determine if a date falls on a weekend
• Halt processing until a specified date/time
Define n_cst_datetime as a global, instance, or local variable, as appropriate
for your application.
Usage of date/time 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
110
Chapter 4 Using PFC Services
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.")
111
File service
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
112
Chapter 4 Using PFC Services
113
INI file service
114
Chapter 4 Using PFC Services
NEXT
115
Numerical service
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.
Usage You can use numerical service functions to:
• Determine whether a specified bit is on or off
• Convert a base 10 number to binary
• Convert a binary number to base 10
ll_base10 = Long(sle_base10.text)
116
Chapter 4 Using PFC Services
ls_binary = inv_numerical.of_Binary(ll_base10)
MessageBox("Numerical", &
String(ll_base10) + " base 10 is equal to " &
+ ls_binary + " in binary.")
117
Platform service
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
118
Chapter 4 Using PFC Services
ll_free_memory = &
inv_platform.of_GetFreeMemory()
gnv_app.of_GetFrame().SetMicroHelp &
("Free memory: " + String(ll_free_memory) )
119
Selection service
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
Define n_cst_selection as a global, instance, or local variable, as appropriate
for your application:
Usage of selection 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
120
Chapter 4 Using PFC Services
ls_columns[1] = "emp_id"
ls_columns[2] = "emp_lname"
ls_columns[3] = "emp_fname"
3 Display the w_selection window by calling the of_Open function (this
version of of_Open causes w_selection to retrieve all rows in the specified
DataWindow object):
lnv_selection.of_Open &
("d_empall", la_selected, SQLCA, ls_columns)
4 Access the returned column values as appropriate (this example displays
returned values in a ListBox):
FOR li_count = 1 to UpperBound(la_selected)
lb_selected.AddItem &
(String(la_selected[li_count]))
NEXT
121
SQL parsing service
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
122
Chapter 4 Using PFC Services
ls_sql = inv_sql.of_Assemble(lstr_sql)
MessageBox("SQL", ls_sql)
123
String-handling service
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
• Counting the number of occurrences of a specified string
• Removing spaces and nonprintable characters from the beginning or end
of a string
• Determining if a string is a comparison or arithmetic operator
• Converting all the words in a string to initial cap
Define n_cst_string as a global, instance, or local variable, as appropriate for
your application:
Usage of string-handling 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
124
Chapter 4 Using PFC Services
125
Metaclass service
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.
126
Chapter 4 Using PFC Services
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
127
Logical unit of work service
Function Purpose
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.
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
128
Chapter 4 Using PFC Services
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)
129
List service
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.
130
Chapter 4 Using PFC Services
131
List service
Accessing the entire You can use the of_Get function to retrieve all nodes in the list.
list at once
132
Chapter 4 Using PFC Services
133
List service
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
134
Chapter 4 Using PFC Services
Removing nodes from You can only access a node from the beginning of the stack (the last node
a stack added). You pop a stack to access a node.
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.
135
List service
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
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
136
Chapter 4 Using PFC Services
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 139.
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)
137
List service
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.
5 Destroy the temporary node:
DESTROY lnv_temp
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).
138
Chapter 4 Using PFC Services
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")
139
List service
• Returns values that the sorted list and tree list objects use to maintain an
ascending sorted list
If your sorted list requires different comparison logic, you must inherit from
n_cst_nodecompare and override the of_Compare function.
Custom comparison If your sorted list requires different comparison logic, you need to create a
objects descendant of n_cst_nodecompare with an overridden of_Compare function
and enable that object at execution time.
anv_node1.of_GetKey(la_key1)
IF IsNull(la_key1) THEN Return -4
anv_node2.of_GetKey(la_key2)
IF IsNull(la_key2) THEN Return -4
ls_keytype1 = ClassName(la_key1)
ls_keytype2 = ClassName(la_key2)
140
Chapter 4 Using PFC Services
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
141
List service
NEXT
142
Chapter 4 Using PFC Services
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.
143
Timing service
144
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 146
Using standard visual user objects 147
Using custom visual user objects 186
145
About PFC visual controls
146
Chapter 5 Using PFC Visual Controls
147
Using standard visual user objects
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.
148
Chapter 5 Using PFC Visual Controls
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 popup menus all include standard text editing functions. However, text
editing functions are not enabled or visible in all popup 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 popup
menu. PFC calls this event after the menu is created but before it is displayed.
149
Using standard visual user objects
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.
150
Chapter 5 Using PFC Visual Controls
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
151
Using standard visual user objects
152
Chapter 5 Using PFC Visual Controls
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.
153
Using standard visual user objects
Disabling services
The u_dw Destructor event destroys enabled services automatically. In
most cases you don’t destroy a service explicitly.
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()
154
Chapter 5 Using PFC Visual Controls
155
Using standard visual user objects
For more information on using pfc_Save, see "Using the pfc_Save process" on
page 214.
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.
156
Chapter 5 Using PFC Visual Controls
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.
157
Using standard visual user objects
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:
158
Chapter 5 Using PFC Visual Controls
• 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 ListView data source service (implemented through the
n_cst_lvsrv_datasource custom class user object) maintains the ListView’s
data source in a DataStore and uses it to populate the ListView. You can also
specify which columns from the DataWindow object should display when the
ListView is in Report view.
159
Using standard visual user objects
this.of_SetUpdateable(TRUE)
7 (Optional) Specify whether PFC asks the user to confirm deletions:
this.inv_datasource.of_SetConfirmOnDelete(TRUE)
8 Retrieve data from the database and add rows to the ListView:
this.Event pfc_Populate()
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)
160
Chapter 5 Using PFC Visual Controls
161
Using standard visual user objects
• A string specifying the name of a bitmap file that the ListView uses
when displaying the corresponding row
• An integer specifying the picture index the ListView uses when
displaying the corresponding row
Using a DataWindow column allows you to customize ListView item
display.
For more on ListViews, see Application Techniques.
162
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
163
Using standard visual user objects
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, "")
this.inv_levelsource.of_Register(2, "emp_lname", &
164
Chapter 5 Using PFC Visual Controls
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)
165
Using standard visual user objects
ll_handle = tv_1.FindItem(CurrentTreeItem! , 0)
ll_return = tv_1.of_InsertItem &
166
Chapter 5 Using PFC Visual Controls
167
Using standard visual user objects
For more on how you specify pictures, see "Using pictures" on page 161.
168
Chapter 5 Using PFC Visual Controls
this.inv_levelsource.of_SetPictureColumn &
(1, ’picture_name’)
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, "")
169
Using standard visual user objects
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 SelectionChanged event to call the ListView’s
pfc_Populate event:
lv_1.Event pfc_Populate()
170
Chapter 5 Using PFC Visual Controls
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)
171
Using standard visual user objects
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)
172
Chapter 5 Using PFC Visual Controls
la_Args[1] = Integer(ltvi_item.Label)
End If
173
Using standard visual user objects
// doubleclicked.
tv_1.GetItem(ll_selectedtreehandle, &
ltvi_newtreeitem)
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")
174
Chapter 5 Using PFC Visual Controls
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
175
Using standard visual user objects
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()
176
Chapter 5 Using PFC Visual Controls
• 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.
177
Using standard visual user objects
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.
178
Chapter 5 Using PFC Visual Controls
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.
179
Using standard visual user objects
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
180
Chapter 5 Using PFC Visual Controls
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
181
Using standard visual user objects
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 popup 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 popup 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.
182
Chapter 5 Using PFC Visual Controls
183
Using standard visual user objects
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 &
184
Chapter 5 Using PFC Visual Controls
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)
3 Register tab page controls:
this.inv_resize.of_Register &
(this.dw_1, 0, 0, 100, 100))
4 Trigger the Resize event on the UserObject (this example is from the Tab
control’s Constructor event):
// The Resize event moves registered
// objects, as appropriate.
this.tabpage_1.TriggerEvent(Resize!)
185
Using custom visual user objects
186
Chapter 5 Using PFC Visual Controls
Users make calculations using the dropdown calculator. To enter numbers they
either click the calculator’s buttons or use the numeric keypad with NumLock
turned on. The calculator automatically enters calculation results into the
associated field.
The PFC calculator control includes functions that allow you to control certain
aspects of calculator behavior. For example, you call the of_SetCloseOnClick
function to control whether the dropdown calculator closes when the user
clicks the equal sign.
Using a dropdown The PFC calculator control works with DataWindow columns that have a
calculator with a numeric or decimal data type and are registered with u_calculator.
DataWindow control
Depending on the registration option, the calculator displays when a registered
column gets focus, when the user clicks the dropdown arrow, or when your
code calls the pfc_DDCalculator event.
Controlling the visual cue To control the visual cue that displays in a
DataWindow column for which the dropdown calculator is enabled, you
supply an argument to the of_Register function:
Argument Result
NONE If the column uses the:
• DropDownListBox edit style, the calculator displays
automatically when the column gets the focus
• Edit or EditMask edit style, the calculator displays
when you call the pf_DDCalculator event
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
187
Using custom visual user objects
188
Chapter 5 Using PFC Visual Controls
4 Define a user event or visual control (such as a command button) that sets
focus in the DataWindow control and calls the u_dw pfc_DDCalculator
event:
IF dw_1.SetColumn("salary") = 1 THEN
dw_1.Event pfc_DDCalculator( )
END IF
Using a dropdown You can use a dropdown calculator with EditMask controls that use the
calculator with an numeric or decimal option type.
EditMask control
189
Using custom visual user objects
this.of_SetDropDownCalculator(TRUE)
...
this.iuo_calculator.of_SetCloseOnClick(TRUE)
• Initial value Controls whether the calculator initializes blank fields with
a zero when it first displays:
this.of_SetDropDownCalculator(TRUE)
...
this.iuo_calculator.of_SetInitialValue(TRUE)
190
Chapter 5 Using PFC Visual Controls
191
Using custom visual user objects
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)
192
Chapter 5 Using PFC Visual Controls
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
...
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.
193
Using custom visual user objects
this.of_SetDropDownCalendar(TRUE)
3 Register columns to be displayed programmatically by calling the
of_Register function. Of_Register includes an argument specifying the
dropdown style. Programmatic display works best with the NONE style
but can be used with any dropdown style:
this.iuo_calendar.of_Register("start_date" &
this.iuo_calendar.NONE)
4 Define a user event or visual control (such as a command button) that sets
focus in the DataWindow control and calls the u_dw pfc_DDCalendar
event:
IF dw_1.SetColumn("start_date") = 1 THEN
dw_1.Event pfc_DDCalendar( )
END IF
Using a dropdown You can use a dropdown calculator with EditMask controls that use the date
calendar with an option type.
EditMask control
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
194
Chapter 5 Using PFC Visual Controls
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
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 dropdown 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.
195
Using custom visual user objects
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
196
Chapter 5 Using PFC Visual Controls
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)
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 dropdown 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 dropdown calendar closes
when the user double-clicks a date:
this.of_SetDropDownCalendar(TRUE)
...
this.iuo_calendar.of_SetCloseOnDClick(TRUE)
197
Using custom visual user objects
• 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)
198
Chapter 5 Using PFC Visual Controls
2 Move and resize the splitbar object and the surrounding objects until they
relate appropriately. For example, a vertical splitbar between two objects
should have the same height as the surrounding objects.
199
Using custom visual user objects
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 popup window that displays the progress bar, perhaps including a Cancel
button.
200
Chapter 5 Using PFC Visual Controls
201
Using custom visual user objects
Using the progress N_cst_winsrv_statusbar (the PFC status bar object) includes much of the
bar in the status bar functionality provided by u_progressbar. This allows you to display progress
in the status bar instead of using space in the window or opening a separate
progress window.
Status bar service functions that apply to the progress bar are equivalent to
progress bar control functions except that the function names include the word
bar. For example, of_SetBarAutoReset is equivalent to of_SetAutoReset.
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
202
Chapter 5 Using PFC Visual Controls
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:
• U_progressbar Call the of_SetMaximum and of_SetMinimum
functions:
SELECT COUNT(emp_id)
INTO :il_max
FROM Employee
USING SQLCA;
IF il_max > 0 THEN
uo_progress.of_SetMaximum(il_max)
uo_progress.of_SetMinimum(0)
END IF
• N_cst_winsrv_statusbar Call the of_SetBarMaximum and
of_SetBarMinimum functions:
w_frame lw_frame
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
203
Using custom visual user objects
• 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)
• N_cst_winsrv_statusbar Call the of_SetBarDisplayStyle function,
passing either an integer or an n_cst_winsrv_statusbar constant to
specify the information displayed on the progress bar:
this.inv_statusbar.of_SetBarDisplayStyle &
(this.inv_statusbar.PCTCOMPLETE)
• Fill style Controls whether the progress bar fills from left to right, right
to left, bottom to top, or top to bottom. You call different functions
depending on whether the progress bar is in a window or in the status bar:
• U_progressbar Call the of_SetFillStyle function, passing either an
integer or a u_progressbar constant to specify the progress bar fill
style:
this.of_SetFillStyle(LEFTRIGHT)
• N_cst_winsrv_statusbar Call the of_SetBarFillStyle function,
passing either an integer or an n_cst_winsrv_statusbar constant to
specify the progress bar fill style:
this.inv_statusbar.of_SetBarFillStyle &
(this.inv_statusbar.LEFTRIGHT)
• Fill color Controls the color displayed as the progress bar fills. You call
different functions depending on whether the progress bar is in a window
or in the status bar:
• U_progressbar Call the of_SetColor function, passing the color
used to fill the bar:
this.of_SetFillColor(RGB(128, 128, 128))
204
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:
205
Using custom visual user objects
206
Chapter 5 Using PFC Visual Controls
207
Using custom visual user objects
208
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 210
Using menus with PFC 220
209
Using PFC windows
PFC windows contain instance variables, events, and functions that provide
advanced functionality and enable communication with other PFC objects.
210
Chapter 6 Using PFC Windows and Menus
Message.StringParm = "w_emplist"
lnv_menu.of_SendMessage(this, "pfc_Open")
211
Using PFC windows
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
212
Chapter 6 Using PFC Windows and Menus
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.
4 Code the pfc_Apply, pfc_Cancel, and pfc_Default events as necessary. For
example, a pfc_Default event might save the window contents in an INI
file and close the window:
String ls_temp
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.
213
Using PFC windows
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
127.
214
Chapter 6 Using PFC Windows and Menus
215
Using PFC windows
216
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
217
Using PFC windows
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)
Enabling a one-time PFC allows you to identify a specified group of controls and update them.
update
218
Chapter 6 Using PFC Windows and Menus
PowerObject lpo_objs[ ]
Integer li_return
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
...
219
Using menus with PFC
220
Chapter 6 Using PFC Windows and Menus
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()
221
Using menus with PFC
• 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.
222
Chapter 6 Using PFC Windows and Menus
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
Select All pfc_SelectAll U_ddlb, u_ddplb, u_dw, u_em,
u_mle, u_rte, and u_sle
Find pfc_FindDlg U_dw and u_rte
Replace pfc_ReplaceDlg U_dw and u_rte
Update Links pfc_UpdateLinks U_oc
Object>Edit pfc_EditObject U_oc
Object>Open pfc_OpenObject U_oc
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
223
Using menus with PFC
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
224
Chapter 6 Using PFC Windows and Menus
225
Using menus with PFC
226
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 228
SQL Spy 231
Security 234
Library Extender 246
Migration Assistant 247
227
DataWindow Properties window
228
Chapter 7 PFC Utilities
• Buffers Click the right mouse button to display a popup menu that
allows you to manipulate rows:
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:
229
DataWindow Properties window
• 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.
230
Chapter 7 PFC Utilities
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.
SQL Spy logs SQL to a file, which you can optionally display in a popup
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.
231
SQL Spy
The w_sqlspy popup 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.
232
Chapter 7 PFC Utilities
• Resume Updates the current row and updates all remaining rows;
disable the SQL Spy inspect capability
• Cancel Does not update the current row and displays the next row
to be updated
• Cancel All Does not update all remaining rows
233
Security
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.
The PFC security system includes:
• The security administration utility Allows you to define users, groups,
items to be secured, and user access.
• The security scanner Scans user-specified objects to gather
information on all items that can be secured.
• The security database Contains information on users, groups, items to
be secured, and user access to those secured items.
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:
234
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.
235
Security
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.
236
Chapter 7 PFC Utilities
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.
The Add Group dialog box displays:
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.
237
Security
3 Click OK.
4 Select File>Save from the menu bar.
238
Chapter 7 PFC Utilities
See "Defining users and groups" on page 235 for steps on adding the
security administration target file to your workspace.
2 Select File>Scan Application from the security administration utility
menu bar.
The Select Application dialog box displays a list of the applications
defined in the Application section of the PB.INI file:
239
Security
Selecting objects
To minimize the size of the security database, do not select objects for
which you will never assign security.
5 Click Scan.
240
Chapter 7 PFC Utilities
241
Security
3 Click the Users dropdown listbox 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.
242
Chapter 7 PFC Utilities
7 When you are finished, select File>Save from the menu bar.
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 = &
243
Security
gnv_app.inv_security.of_InitSecurity &
(gnv_app.itr_security, "EISAPP", &
gnv_app.of_GetUserID(), "Default")
244
Chapter 7 PFC Utilities
245
Library Extender
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.
246
Chapter 7 PFC Utilities
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.
247
Migration Assistant
248
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 250
Using PBR files 252
Deploying database tables 253
Deploying PFC dialog box Help 254
249
Choosing a deployment strategy
250
Chapter 8 Deploying a PFC Application
251
Using PBR files
252
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.
253
Deploying PFC dialog box Help
254
PART 4 PFC Tutorial
257
Create a PFC application
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.
258
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 listbox.
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:
259
Create a PFC application
10 Click Open.
The Library Search Path listbox 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 listbox. The
Generate To-Do List checkbox is selected.
12 Click Finish.
260
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".
261
Modify the application manager
4 Make sure Untitled displays as the name of the user object in the first
dropdown listbox of the Script view.
Make sure the Constructor event displays as the selected event in the
second dropdown listbox 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 8.0
is_logo drive:\pathname\pfc\tutorial\tutsport.bmp
is_copyright PFC tutorial application
262
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.
263
Modify the application manager
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
dropdown listbox of the Script view.
264
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.
265
Redefine a global variable and review events
266
Lesson 1 Generate a PFC Application
267
Use the PFC Transaction Object service
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).
268
Lesson 1 Generate a PFC Application
269
Use the PFC Transaction Object service
270
LE S S O N 2 Create the Frame Window
• How to open a sheet using a string passed via the message router
• How to enable the status bar service
• How to enable the sheet management service
• How to connect to a database using functions provided by n_tr
271
Create a descendent 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 checkbox.
You will not use a toolbar in the frame window, only in the sheet windows.
272
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.
273
Define pre- and post-open processing
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.
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
274
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.
275
Add script to open the frame window
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.
276
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:
277
Run the application
The MDI frame window displays behind the splash window and remains
open after the splash window closes.
278
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.
279
Create a descendent menu
Now you will create a master menu for the tutorial by inheriting from the
m_master menu.
5 Click OK.
PowerBuilder saves the menu.
280
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 dropdown listbox 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.
281
Add and modify items
282
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
dropdown listbox. When you created the Product List menu item,
PowerBuilder added it to the listbox.
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
dropdown listbox.
283
Add and modify items
13 Clear the Visible checkbox on the General page of the Properties view.
Select the Toolbar tab of the Properties view.
Clear the ToolbarItemVisible checkbox 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.
284
Lesson 3 Create Menus
285
Create a frame menu
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.
286
Lesson 3 Create Menus
287
Associate the frame window with a menu
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:
288
Lesson 3 Create Menus
Now you will create a sheet menu by inheriting from m_tut_master, the PFC
tutorial master menu.
289
Create a menu for the w_products sheet
290
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).
291
Create a menu for the w_product_report sheet
292
LE S S O N 4 Build the First Sheet Window
293
Add a library to the library list
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.
294
Lesson 4 Build the First Sheet Window
Now you will create a sheet window by inheriting from the w_sheet window.
295
Add a DataWindow control
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.
296
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.
297
Add a DataWindow control
7 Make the control almost as big as the window in the Layout view,
maximizing the Layout view if necessary:
298
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 dropdown listbox in the Script view.
Select the Constructor event from the second dropdown listbox.
The third dropdown listbox 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 &
299
Enable DataWindow services
(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.
300
Lesson 4 Build the First Sheet Window
PowerBuilder compiles the script you typed for the dw_list Constructor
event.
301
Retrieve rows
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.
302
Lesson 4 Build the First Sheet Window
Now you will make sure the sheet window opens properly by running the PFC
tutorial application.
303
Run the 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.
304
Lesson 4 Build the First Sheet Window
305
Run the application
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 dropdown calculator in the Unit Price column to
change column values.
306
Chapter
You can try enabling other DataWindow services and changing their
properties.
307
Run the application
308
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
309
Create a descendent window
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.
310
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 checkbox.
You add a horizontal scroll bar to the DataWindow that will be visible at
runtime.
311
Add a DataWindow control
6 Make the control almost as big as the window in the Layout view,
maximizing the Layout view if necessary:
312
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 dropdown listbox in the Script view.
Select the Constructor event from the second dropdown listbox.
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.
313
Enable report and print preview services
314
Lesson 5 Build the Second Sheet Window
315
Run the application
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.
316
Index
317
Index
318
Index
319
Index
n_cst_dwsrv_rowselection using 99
tutorial usage 299 online Help
usage 92 dialog box Help 254
n_cst_dwsrv_sort enabling for an application 54
tutorial usage 299 operational polymorphism 8
usage 95 overloading functions 8
n_cst_error 65 overriding functions 8
n_cst_luw
usage 127
w_master pfc_Save process 214
n_cst_mru, usage 62 P
n_cst_resize 106 paste 148
n_cst_security 68 paste special 148
n_cst_tmgmultiple 143 PBLs 16
n_cst_tmgsingle 143 PBR files 252
n_cst_trregistration 69 PFC
n_cst_winsrv 101 DLLs 250
n_cst_winsrv_preference 101 libraries 16, 259
n_cst_winsrv_sheetmanager services 10
usage 102 pfc_MessageRouter event
n_cst_winsrv_statusbar process diagram 49
usage 103 using 100
n_tmg 143 pfc_Save process 214
n_tr PFCDLG.HLP 254
autorollback 52, 70 platform service 118
creating an instance 52 polymorphism 8
initializing 52 popup menus, list of 148
registering a transaction 70 post-open processing 274
replacing default Transaction object 51, 268 PowerBuilder, prerequisite concepts 5
usage 51 preference service
nilisnull property 89 application 61
numerical service 116 window 101
pre-open processing 274
prerequisite concepts 5
print preview service
O tutorial usage 313
object administrator 22 usage 84
object-oriented programming progress bar control 200
delegation 12 Properties window 228
encapsulation 8
inheritance 8
polymorphism 8
usage in PFC 10 Q
of_SendMessage function querymode service 85
process diagram 48
tutorial example 283
320
Index
321
Index
322