Sunteți pe pagina 1din 135

Building Applications with SQLWindows

Preface
This manual provides supporting materials for the course Building Applications with SQLWindows. This preface provides the following information: Who should read this manual? The notation conventions used in this manual.

Audience
This manual is intended for: Application Developers building client/server applications in SQLWindows. Project Leaders managing development teams or evaluating development tools. This manual assumes you have an understanding of programming concepts and some programming experience in other languages. It does not assume you have Windows programming experience although it does assume that you have experience using the Windows interface.

Notation conventions
Before you start using this manual, it is important to understand the typographical conventions we use in this manual:

Formatting Convention
You User bold type A developer who reads this manual

Type of Information

The end-user of applications that you write Menu items, push buttons, and field names. Things that you select. Keyboard keys that you press. Programming Code Program names and file names

Courier New SQL.INI MAPDLL.EXE Warning:


NOTE

Warning Vital information

Table of Contents
Chapter 1: Introduction ...................................................................................................... 7 Course Objectives .......................................................................................................... 7 Team Developer............................................................................................................. 7 SQLWindows Features .................................................................................................. 8 Information (Data) Access ............................................................................................. 9 Database Terminology ................................................................................................... 9 Course Files ................................................................................................................. 10 HOLLYWD Data Model.............................................................................................. 10 Suggested Reading ....................................................................................................... 11 Chapter 2: SQLWindows Overview ................................................................................. 12 What We Will Cover.................................................................................................... 12 SQLWindows User Interface........................................................................................ 12 SQLWindows User Interface........................................................................................ 12 Outline View................................................................................................................ 13 Layout and Preview View ............................................................................................ 14 Controls Palette............................................................................................................ 14 Coding Assistant .......................................................................................................... 15 Active Coding Assistant ............................................................................................... 16 Attribute Inspector ....................................................................................................... 17 User Mode ................................................................................................................... 17 SQLWindows Processes............................................................................................... 18 Build Process ............................................................................................................... 18 Application Properties.................................................................................................. 18 Database Explorer ........................................................................................................ 19 Demo 2.1: SQLWindows Environment ........................................................................ 19 Demo 2.2: Active Coding Assistant.............................................................................. 19 Demo 2.3: Active Debugging Assistant ........................................................................ 20 Chapter 3: SQLWindows Objects..................................................................................... 21 What We Will Cover.................................................................................................... 21 Types of Window Objects ............................................................................................ 21 Form Windows ............................................................................................................ 22 Table Windows ............................................................................................................ 22 MDI Windows ............................................................................................................. 23 Dialog Boxes ............................................................................................................... 23 Standard Windows Dialog Boxes ................................................................................. 24 Creating Child Objects ................................................................................................. 24 Application Menus....................................................................................................... 27 Windows Message Boxes............................................................................................. 28 SQLWindows Outline Syntax ...................................................................................... 28 Mnemonics and Accelerators ....................................................................................... 29 Exercise 3.1: SQLWindows Objects............................................................................. 29 Application ToolBars ................................................................................................... 30 Exercise 3.2: Using Dockable Application Toolbars..................................................... 31 Chapter 4: Event/Message Programming.......................................................................... 32

What We Will Cover.................................................................................................... 32 A World of Windows Objects ...................................................................................... 32 SQLWindows Objects.................................................................................................. 33 Event/Message/Action Flow......................................................................................... 33 Where Messages are sent ............................................................................................. 34 Who Sends Messages ................................................................................................... 34 Event/Message/Action Examples ................................................................................. 35 Message Sequence ....................................................................................................... 35 Using Return in Message Actions................................................................................. 36 Initialization of Child Object Values ............................................................................ 37 Object Validation ......................................................................................................... 37 Exercise 4.1: Event/Message Programming .................................................................. 38 User-Defined Messages................................................................................................ 39 Additional Message Information .................................................................................. 39 Sending versus Posting Messages................................................................................. 40 Good Programming Technique..................................................................................... 41 Exercise 4.2: An OO Approach to Event/Message Programming.................................. 42 Chapter 5: A Simple Event-Based Application................................................................. 44 What We Will Cover.................................................................................................... 44 Demo 5.1: SALCulator ................................................................................................ 44 Demo 5.2: Defining User Messages ............................................................................. 44 Using the Case Statement ............................................................................................. 46 Using Simple Assignments........................................................................................... 46 Using Message Boxes .................................................................................................. 47 Using Case, Assignment and Message Boxes ............................................................... 47 Closing a Parent Window............................................................................................. 47 Exercise 5.1: A Simple Event-Based Application ......................................................... 48 Chapter 6: SAL Components............................................................................................ 50 What We Will Cover.................................................................................................... 50 What is SAL?............................................................................................................... 50 SAL Data Types........................................................................................................... 50 Variable Declarations................................................................................................... 51 System Variables ......................................................................................................... 52 Variable Qualification .................................................................................................. 53 Window Handles.......................................................................................................... 54 Arrays .......................................................................................................................... 55 Array Functions ........................................................................................................... 56 Command Line Arguments .......................................................................................... 56 Operators ..................................................................................................................... 57 Variable Expressions.................................................................................................... 58 Constants ..................................................................................................................... 58 System Constants ......................................................................................................... 58 Chapter 7: SAL Language Statements .............................................................................. 59 What We Will Cover.................................................................................................... 59 SAL Statements ........................................................................................................... 59 SQLWindows Function Types ..................................................................................... 64 Demo 7.1: External Functions ...................................................................................... 65

Internal Functions ........................................................................................................ 66 Receive Parameters ...................................................................................................... 67 Demo 7.2: Receive Parameters..................................................................................... 68 Top-Level Window Parameters .................................................................................... 68 Exercise 7.1: SAL Functions ........................................................................................ 69 Chapter 8: SQL Basics ..................................................................................................... 70 What We Will Cover.................................................................................................... 70 What is SQL?............................................................................................................... 70 SQLTalk and Database Explorer .................................................................................. 71 Demo 10-1: SQLTalk................................................................................................... 71 SELECT Statement ...................................................................................................... 71 Pattern Matching .......................................................................................................... 73 Sorting Data................................................................................................................. 74 Aggregate Functions .................................................................................................... 74 Retrieving Data from Multiple Tables .......................................................................... 75 Complex Joins ............................................................................................................. 76 INSERT Statement....................................................................................................... 78 UPDATE Statement ..................................................................................................... 78 DELETE Statement...................................................................................................... 78 COMMIT Statement .................................................................................................... 79 Exercise 8.1: SQL Basics ............................................................................................. 79 Chapter 9: Working with SQL Databases ......................................................................... 80 What We Will Cover.................................................................................................... 80 Connecting to a Database ............................................................................................. 80 Demo 11.1: Connecting to a Database .......................................................................... 80 Sql Handles.................................................................................................................. 81 OLE DB Constructs/Session Handles ........................................................................... 81 Disconnecting from a Database .................................................................................... 82 BIND Variables - Data Output ..................................................................................... 82 INTO Variables - Data Input ........................................................................................ 82 INSERT, UPDATE, DELETE ..................................................................................... 83 SQL Command Cycle .................................................................................................. 83 SqlPrepare.................................................................................................................... 84 SQLBase Stored Commands ........................................................................................ 84 SqlExecute................................................................................................................... 84 SqlPrepareAndExecute................................................................................................. 85 Fetching Data............................................................................................................... 85 Using SqlPrepare ......................................................................................................... 86 Using SqlStore and SqlRetrieve (SQLBase) ................................................................. 86 What is a Transaction? ................................................................................................. 86 Exercise 9.1: Working with SQL Databases ................................................................. 87 Chapter 10: SQLError Handling and Infrastructure .......................................................... 89 What We Will Cover.................................................................................................... 89 Demo 12-1: Login Dialog Box ..................................................................................... 89 Functions for Forms and Dialog Boxes......................................................................... 90 Types of Dialog Boxes Review ................................................................................. 91 Library Files ................................................................................................................ 92

Exercise 10.1: Login Dialog Box.................................................................................. 92 SQL Error Handling ..................................................................................................... 93 When SqlError ............................................................................................................. 95 Demo 12.2: Handling SQL Errors Locally.................................................................... 95 Global Error Handler.................................................................................................... 96 Default Error Handling................................................................................................. 97 Exercise 10.2: Handling Known Connection SQL Errors ............................................. 97 Chapter 11: Getting Started with Table Windows............................................................. 99 What We Will Cover.................................................................................................... 99 What is a Table Window? ............................................................................................ 99 Table Window Terminology ........................................................................................ 99 Result Set/Table Window Cache ................................................................................ 101 Populating a Table Window ....................................................................................... 101 Dynamic vs. Defined Columns................................................................................... 102 Table Window SAM* Messages ................................................................................ 102 Other SAM* Messages............................................................................................... 102 Demo 13.1: A Table Window for Browsing Data ....................................................... 103 Exercise 11.1: Getting Started with Table Windows ................................................... 104 Demo 13.2: Selecting Data......................................................................................... 105 Exercise 11.2: Selecting Data with a Combo Box....................................................... 107 Populating Combo Boxes ........................................................................................... 108 Demo 13.3: Loading Lookup Data from the Database ................................................ 108 Exercise 11.3: Populating a Combo Box..................................................................... 108 Chapter 12: SQLWindows and Reports.......................................................................... 110 What We Will Cover.................................................................................................. 110 Classic Report Interface ............................................................................................. 110 Report Builder Functions ........................................................................................... 111 Creating and Manipulating Reports ............................................................................ 111 Demo 16.1: Creating & Viewing Report Data ............................................................ 112 Report Builder Messages............................................................................................ 113 Function Details ......................................................................................................... 114 Demo 16.2: Using Report View ................................................................................. 115 More Function & Message Details ............................................................................. 115 Demo 16.3: A Simple Classic Interface Report........................................................... 116 Exercise 12.1: SQLWindows and Reports .................................................................. 118 Tasks...................................................................................................................... 118 Report Builder Errors................................................................................................. 119 Query/Report ............................................................................................................. 120 Report Objects ........................................................................................................... 121 Demo 16.4: Creating a Crosstab Report Demo 16.5: Printing Images ......................... 122 Integrating Report Builder with ActiveX .................................................................... 123 Demo 16.6: Report Builder Automation ..................................................................... 123 Exercise 12.2: Creating an RB Automation App......................................................... 124 Tasks...................................................................................................................... 124 Chapter 13: Team Developer 6 New Controls ................................................................ 125 Team Developer 6 NEW Controls .............................................................................. 126 Application Demonstration ........................................................................................ 128

Chapter 1: Introduction
Course Objectives
. . . . . Become familiar with the Team Developer product and its components Become proficient with the SQLWindows development environment Learn Scalable Application Language (SAL) Use SQLWindows to build client/server applications Using Report Builder with SQLWindows

Team Developer
An integrated family of tools for building database-centric business applications.

SQLWindows
The development environment (discussed in detail later in this chapter).

Report Builder
. . . . Full featured graphical report designer Graphical query builder Design time interface Run time interface

Team Object Manager


. . . . . . . . . . . . Integrated, project-based, version control and configuration management tool for complex applications and multi-developer environments Component orientation Simplifies navigation of large applications Graphical view of class hierarchies Automatically detect module dependencies Standards Promote code reuse and simplify documentation Naming conventions Multi-user Assigning privileges Assigning tasks Check out/check in of application and components

Object Compiler
Translates internal functions in an application outline into external functions in a Dynamic Linked Library (DLL) Speed-up performance Native compilation before deployment Up to 80% of object oriented code is compiled!

Object Nationalizer
Easily customize applications for specific locales

SQLBase Desktop
Desktop (single user) version of SQLBase is included. Here are some advantages to using SQLBase: . . . . . . . Better enterprise integration and scalability through MTS Support. Simplified administration with enhanced SQLBase Management. Better IDE integration through enhanced ODBC and OLEDB. Easier maintenance through descriptive identifiers. Improved database searching with new SQL features. Better management capabilities for larger databases. Completely automated upgrade process from previous versions of SQLBase.

SQLWindows Features
SQLWindows is a Windows based prototyping and development tool.

Powerful Development Environment


. . . . . . . . SQLWindows is the powerful development environment with: Graphical application development Event/Message oriented programming paradigm Multiple views of application code at any level of detail Context-sensitive help Coding Assistant Advanced debugging tools It is component based, and optionally, repository driven.

SAL
The language it uses is called Scalable Application Language (SAL). SAL is a productive 4GL programming language.

Objected Oriented Programming (OOP)


. . . . . . SQLWindows has Object-Oriented Features such as: Ready to use pre-built objects Customizable objects to meet business needs Class definitions Multiple inheritances - the ability of an object to inherit the properties of more than one class. Polymorphism - the ability of different objects to respond to the same request in different ways (i.e. to the MS Paint message).

Class Libraries
Third party libraries are available. Create your own class libraries Embbed classic, OCX, ActiveX and other controls

SQL Interface
A number of SQL* functions provide SQL access to SQL based databases.

Windows functionality
. . . . . . Easy and open access to Windows functionality Drag and drop OCX and ActiveX Controls COM servers and Object Linking and Embedding (OLE) DLL (Dynamic Linked Libraries) Full-featured, context-sensitive Help - (F1 key)

Integration with Report Builder Easy to use Wizards


Ease of Use is provided through the use of wizards

Top-level windows
Create Form Windows...

Class Wizard
Quickly guides you through building multi-level class hierarchies three-tier class libraries

Database Explorer
. . . . . . . The Database Explorer can: Manage any database schema from a single tool Database Objects: tables, views, indexes Stored procedures SQL scripting tool -hoc query/report tool View and edit table contents

ActiveX Explorer
The ActiveX Explorer allows you to manage any components needed for your application.

Information (Data) Access


SQL Databases
Most databases can be accessed via OLE DB and their native interfaces, while many others can be accessed via ODBC. . . . . . . . . SQLBase Oracle Sybase Informix IBM DB2 Microsoft SQL Server Microsoft Access

Mail Systems
MAPI compliant (Microsoft) Note In many of the exercises throughout this course you will be working with information contained in a database that has been created for you. On the next few pages you will be introduced to some database concepts and terminology to help you better understand how the data is organized.

Database Terminology
What is a Database?
A database is a collection of information or data that is related or integrated in some fashion usually shared amongst several users. A database management system (DBMS) is a set of utilities and tools to create and maintain databases. A relational database (RDB) stores the data in a database as tables (relations). Tables are accessed via columns (attributes) and rows.

Terminology
Base Table is a collection of data on a single topic that is organized into rows and columns (Relation). Row contains information about a single instance or occurrence of the data. Column contains the data values that describe the properties of a table (Attribute) each column has a name. Cell is where a row intersects a column and is where each data element is stored (Field). Relational Database Management System (RDBMS) manages tables containing data organized in accordance with the relational model. In

this course work, we will use the informal terms of tables, rows and columns.

Normalization
In a relational database, a data model is subjected to a process called normalization. Normalization ensures that each table contains information about a single entity. Normalization guarantees the integrity and accuracy of the data by ensuring that there are primary keys assigned to each base table. Primary

keys may be a single column or a combination of several columns that uniquely identify any given row in a table. Examples of primary keys are: Employee Number Job Code Normalization also ensures that proper foreign keys are established. A foreign key is created when a primary key of one base table is included in another base table. The use of primary (PK) and foreign (FK) key relationships provides a way that data stored in multiple tables can be brought together again by matching the primary key of one base table with the foreign key in another base table.

Course Files
Installed in \40-6201\STUDENT They contain information used in the course exercises Application files, where xx is the chapter and yy is the exercise . Templates - Chapter xx Template yy.app . Solutions - Chapter xx Solution yy.app Demonstration -Chapter xx Demo yy.app Databases used in the exercises and demonstrations . HOLLYWD database is used for instructor demonstrations User: HOLLYWD Password: HOLLYWD . PRESIDNT database is used for Student exercises User: PRESIDNT Password: PRESIDNT

HOLLYWD Data Model

Suggested Reading
. Developing SQLWindows Applications By David Gugick SAMS, 1995 . Using SQLWindows 5 By David Holmes-Kinsella QUE, 1995 . Using SQL By James R. Groff and Paul N. Weinberg Osborne McGraw-Hill, 1990 ISBN 0-0708811524-X . Windows API Bible By James L. Conger Waite Group

Handbook of Relational Database Design By Fleming and Von Halle Addison-Wesley

Chapter 2: SQLWindows Overview

What We Will Cover


. . . . . . . . . . SQLWindows User Interface Outline View Layout and Preview View Controls Palette Coding Assistant Attribute Inspector User Mode SQLWindows Processes Build Process Application Properties

SQLWindows User Interface


Design-time environment
The SQLWindows desktop uses a Multiple Document Interface (MDI), which provides an application development environment that allows opening multiple views of an application simultaneously. Each MDI window contains a left pane and a right pane.

Application windows
SQLWindows has an interface similar to Windows Explorer. It provides multiple views of the same application. There are two main panes, which are separated by an adjustable splitter.

Left pane
. . . . Tree view (outline) of application (or selected parts of an application) Eases code navigation Expanding the outline Selecting a folder

Right pane
Different ways of viewing application objects, using tabs. The content of the right pane is dependent upon the selected folder in left pane. To navigate in the right pane, you can either select from the tabs at the bottom of the pane or Scroll the tab list

SQLWindows User Interface

Note. Multiple views of a dialog box (dlgQOLogin) as displayed in the right pane of the design-time environment.

Outline View
There is an outline view for every object in the left pane. This is where application code is added and edited. It contains SAL statements. When you are viewing the outline or outline subset in the right pane, there are a number of sections in the outline. . . . . . . Outline Constants Libraries Message actions Parameters Variables

SQLWindows applications are physically stored in a form known as the Application Outline. To display the application outline for a window object, use the following steps: Click on the window object (in the left pane), which represents the window Click on the Outline view tab in the View window

The application code for the window is now displayed in the View Window.

Layout and Preview View


Window object design
Both the layout and preview views can be used to design top-level windows and classes. . Form Windows . Dialog Boxes . Top-level Table Windows . MDI Windows . Any kind of window class The design process involves . Creating child window objects . Customizing object properties . Orient and position window objects

Preview Window
Can be invoked from the Layout menu (Ctrl+L) Can be used to add and edit child windows (see following) Can also be used to set the runtime position of a window Bi-directional selection

Layout View
To display the application layout for a window object, use the following steps: . . . Click the Explorer window object, which represents the window Click on the Layout view tab in the View window

Controls Palette
The controls palette contains all the tools and objects that you'll need to add and customize child objects on top-level windows. To identify the function of each of these controls, simply rest the mouse pointer on each of the icons and their identity will be displayed via tool tips.

Controls for the layout and preview window


Displays child objects Displays any child object classes, if defined ActiveX controls and objects Can be customized with user-defined buttons for classes

Accessibility
Alt+4 Tools | Controls Dockable

Coding Assistant
Lists valid coding options for the Outline View. Every coding option is accessible via the Coding Assistant with the following exception: Objects from data sources (databases), for example, database tables and columns. In this case, you may use Database Explorer to obtain this information. It can be used to: Define functions, constants, and variables Code SAL statements Define events for COM objects Create Class definitions Create objects It is searchable and context-sensitive.

Accessibility
Alt+2 Tools | Coding Assistant Dockable

Components
Depending upon the context you will see

Combo Box
Permits you to select the type of objects you want to see in the list box

List boxes
The Coding Assistant has one or two lists depending on what is selected in the outline. These list boxes have associated push buttons:

Add Same Level


Add the highlighted item at the same level as the selected item in the outline

Add Next Level


Add the highlighted item at the next level under the selected item in the outline

Set to Function
Add the highlighted function to the statement selected in the outline

Data Field
A data field for searching the list box. Type the first few characters of a name in the data field at the top of the palette to scroll to the item that begins with them.

Active Coding Assistant


Like the Coding Assistant, lists valid coding options for the Outline View. Depending on where you are at in the outline; you are prompted with a dialog box containing a list of selections. It can be used to: Define functions, constants, and variables Code SAL statements Define events for COM objects Create Class definitions Create objects It is searchable and context-sensitive.

Accessibility
Automatic.

Components
Depending uponthe context you will see

Activation Properties
Located as an additional tab in Team Developer Preferences. The following is a list of each of the optional settings used to activate the Active Coding Assistant:

. . . .

Enable Features Turns the Active Coding Assistant on and off Quick Info Displays the complete declaration for any identifier in your code. List Members is a floating/modeless dialog box with a list box containing all members of the class or scope that has focus. Parameter Info Opens the parameters list to give you information about the number, names, and types of parameters required by a function or attribute. . Complete Word Types the rest of a variable, command, function, or symbol name once you have entered enough characters to disambiguate the term. . Automatic Quick Info/List Members/Parameter Info . These three options can be set to appear automatically if enabled. Otherwise you can activate them manually with hot keys, menu choices, or toolbar clicks.

Attribute Inspector
Parent and child window objects have many customizable attributes. The list of attributes is different for each type of object.

Accessibility
Alt + 3 Tools | Attribute Inspector Dockable

User Mode
User mode is when you are executing applications from design mode. You can easily switch between design and user mode.

Accessibility
Press F7 Or Project | Go (or Debug | Go)

Debugging during user mode


Effective method for testing/debugging

Break points
You can set/clear breakpoints You can stop program execution

Examining program variables/expressions


Displaying the value of variables Evaluate expressions

Monitoring program flow


Program animation Message occurrence/sequence Function call occurrence/sequence

Active Debugging Assistant


Allows you to view and change the value of a variable at runtime, or specify new variables, using the Expressions window and Variables window. You can also type directly into the cells in the Variable window. Type a new variable name in a blank cell in the Name column to add a variable. Type over the value of an existing variable to change its value at runtime. There are also two new variable watch windows: Auto and Locals. Auto shows those variables that are present in the current line of code (the breakpoint line) and the line of code preceding the current line. Locals shows only those variables that are in local scope at the time of the breakpoint. These new windows are accessed from the Debug toolbar. All the watch windows now handle complex user-defined-variables (UDVs) more smoothly. A + icon allows you to expand the UDV variable name in a tree view to see nested variables within the UDV.

SQLWindows Processes
Build Settings
The Build Settings dialog sets options for building a target object

Build Target
The target of the build can be of several types

Executable (*.EXE)
Use for deployment of completed applications Binary

Dynalib (*.APD)
Dynamic include library Shares compiled code during runtime

Include Library (*.APL)


Recompiled with application source code Share source code during design time The remaining options(COM) will be discussed in another course level.

Accessibility
Project | Build Settings

Build Process
Design time
. . . . Design the window objects Customizing Create/edit code in the Application Outline Coding Assistant can be used to assist . Check In/Check Out applications with Team Object Manager (if being used)

Test
User mode can be used for initial testing and debugging.

Build the target


. . . . Compile applications Specify build settings Build the object(s) Project | Build: <object>

Deployment
Can be deployed with the Team Developer deployment file. This is part of the SQLWindows deployment package, which is not discussed in this course. Remember to include all deployment files including connectivity files

Application Properties
Information about the contents of applications.

Accessibility
Select the application folder in the left pane Right-click on the application folder, select Properties Select Edit | Properties... Alt+Enter

Database Explorer
Supports multiple database vendors. Provides a consistent user interface. Work with any database object Browsing tables, columns or views Creating and modifying stored procedures Interactive SQL scripting interface

Accessibility
Tools | Database Explorer

Demo 2.1: SQLWindows Environment


We will open a new application and then demonstrate the following: Left and right panes Outline and layout views Controls Palette and Coding Assistant Docking - we will demonstrate docking the Controls Palette, Coding Assistant and Attribute Inspector Tool tips - we will display the tool tips. Note also the extended information in the status are at the bottom of the design time window. Object properties Outline view -we will demonstrate the outline view for various objects. Layout view -we will create a new Form Window and show its layout. Database Explorer We will demonstrate the use of the Database Explorer with the HOLLYWD database: Tables Views Stored procedures Indexes

Demo 2.2: Active Coding Assistant


Here we will see an example of how the active coding assistant can help when coding an application. First example is how the active coding assistant pops up with you insert a new line.

Next we see what is displayed if you are trying to insert a function from an object.

And here we see the pop up message describing parameters of the function we just added.

Demo 2.3: Active Debugging Assistant

Chapter 3: SQLWindows Objects


What We Will Cover
. . . . . . . . . . Types of Window Objects Form Windows Table Windows MDI Windows Dialog Boxes Standard Windows Dialog Boxes Creating Child Objects Windows Message Boxes SQLWindows Outline Syntax Mnemonics and Accelerators

Types of Window Objects


Parent (top-level) Windows
Dialog Boxes Form Windows MDI Windows Table Windows

How they are created


Select Windows folder in left pane, Right click (context menu) and then select New , Use Coding Assistant to, Add Next Level, Component | New

Features
Are containers for child objects May be a child of an MDI Window (except dialog boxes) May have a System Control menu May or may not be resizable, minimizable, or maximizable May contain Dockable toolbars

Components
Popup Menus folder Windows menu Tool Bar Functions folder Child Windows folder

Tabs to view
Components Actions Description Layout Parameters Variables

Outline

Child Windows (or Objects)


Contained within a parent , Created/destroyed with parent , Cannot be a parent (with the exception of a Child Table window)

Child Table Window


Is contained in a Parent Window, Also is a parent of the columns it contains, Used to display data in scrollable regions

Components
Columns Functions Variables Message Actions

Tabs to view
Components Actions Variables Outline

note

Dialog boxes do not have menu options

Form Windows
Often used for data display/entry. May be automatically created/not created at runtime. Contain menus, child windows May have an icon file

Table Windows
Child and Parent Table Windows permit tabular format for data from any source. User area can only contain columns. The optional tool bar may have all types of children.

Parent Table Windows


Parent Table Windows have the following features (these do not apply to Child Table Windows) May be created/not created at runtime May be resizable, inimitable, or maximizable May have a Title, System/Control Menu, menu bar, tool bar May have an icon file Have an initial state

MDI Windows
The Multiple Document Interface (MDI) is used for creating a desktop or frame for your application. It is useful for managing a number of other windows you may want to display simultaneously. An MDI Window can contain MDI Child Windows such as Form Windows and Parent Table Windows.

Dialog Boxes
Often used to prompt for data from user Typical uses are for Errors/Warnings: Message Boxes Has child objects (in the same fashion as Form Windows) Cannot be automatically created at runtime No resizing at runtime All have titles Absolute screen locations: Yes/No Can be Used as a toolbar with the option to dock it to a parent.

Dialog Box Modes


There are three different modes of dialog boxes, Modal, SysModal and Modeless.

Modal and SysModal


Modal and SysModal share the following properties Return a numeric value Do not have a System Control menu, only has a Close button To Create/destroy use the following functions: SalModalDialog() / SalEndDialog()

Modal
Stops application processing. For Example: File/Open Dialog Box

SysModal
Stops system processing. For Example: a system error Dialog Box

Modeless
Has System Control menu and Close button Does not halt processing Example: Search/Find Dialog Box To Create/destroy use the following functions: SalCreateWindow() / SalDestroyWindow() Owner/no owner behavior Function as a toolbar, with the option to dock and un-dock with a parent

Can be docked on Top, Left, Right, or Bottom as allowed by the parent

Standard Windows Dialog Boxes


MS Windows has standard dialog boxes available from within an SQLWindows application. You can: Choose a color via the Color dialog box Choose a font, size and color via the Font dialog box Open a file via the File | Open dialog box where you provide extension list and description for each type and Dialog Box title Save a file via the File | Save dialog box where you provide extension list and dialog box title along with default file name Use SalDlg* functions to display and use the Windows dialog boxes (discussed later???).

Creating Child Objects


Child objects may be created by using the Controls Palette or the Coding Assistant

Using the Controls Palette


Allows you to create and visually locate objects on your form by choosing an object and dropping it onto a form.

The boxed area identifies various classes of the object selected, or available ActiveX controls and objects

Controls Palette Buttons


Button Description
Pointer (normal pointer used to move and resize objects.) Background Text Group Box - Active Data Field Line Frame Multi-line Field Grid Child Table Window Table Column Push Button Radio Button Check Box Option Button List Box Combo Box Picture Quick Graph Horizontal Scroll Bar Vertical Scroll Bar Date Picker Date Time Picker Tab Bar Tab Page Rich Text Control Separator Yes Yes Yes Yes No Yes Yes Yes N/A No Yes Yes No No Yes Yes Yes Yes Yes Yes Yes Yes Yes Yes No

Active

Tree Control Navigation Bar Navigation Pane WPF Custom ActiveX Custom Control Report

Yes No Yes

Pushbuttons
Can be used to create both Standard Pushbuttons and Flat Look Pushbuttons

Using the Coding Assistant


It allows you to create child (and parent) objects within the Outline tab. You can also use the Active Coding Assistant to create these objects. The picture below shows both methods.

Sample of common child objects

Application Menus
A SQLWindows application can have a number of different types of menus.

Menu Types
Window Menus
Menu Item: top-level menu Popup Menu: menu with sub-menu items (the sub-menu items could be menu items and/or other popups)

Named Menus
Defines a shared popup among windows Floating Popup: creates a popup at application runtime

Menu Components
Menus are made up of the following components

Menu Row
Forces a new menu row to appear

Menu Column
Forces a new sub-menu column in a popup menu

Menu Separator
Adds a horizontal line in a popup to separate unlike sub-menu items

Sample of menu editor

Windows Message Boxes


Access the Windows Message Box from within a SQLWindows application (SalMessageBox).

A SQLWindows application can determine:


Title and message content Message Box icon, if any Push button style Message Box function returns a value indicating which button the user choose.

Windows determines:
Position and size of the message box Push button titles

Return Results:
IDOK (1), IDCANCEL (2), IDABORT (3), IDRETRY (4), IDIGNORE (5), IDYES (6), IDNO (7)

SQLWindows Outline Syntax

In this example, a Form Window frmMain contains child objects dfMessage, pbSet, pbExit and a frame. Code indented under On SAM_Click in pbSet is executed when the user clicks the button. Statements indented under If/Else form blocks to be executed based on the result of the conditional expression. The variable bValueSet is declared in the window.

Mnemonics and Accelerators


When the user presses a mnemonic key at the same time as the Alt key, the input focus moves to the object. You can assign a mnemonic to background text, columns, radio buttons, Push Buttons, option buttons, menu items, group boxes, and check boxes. An accelerator is a keyboard shortcut for choosing a menu item or clicking a Push Button. An accelerator always causes an action. Ctrl+<char> is an example. You can also use mnemonics with Menu Items and Push Buttons. A mnemonic for these objects does more than move the input focus; it also sends a SAM_Click message to the object.

Creating mnemonics
Create a mnemonic by typing an ampersand character (&) before the character, in the title of the object, which you want to be the mnemonic. A mnemonic character appears in an object's title with an underscore.

Creating accelerators
An accelerator is assigned to a Push Button using the Attribute Inspector. A drop down list contains valid keystrokes. An accelerator is assigned to a Menu Item in the outline. Possible keystrokes and combinations are listed in the Coding Assistant

Exercise 3.1: SQLWindows Objects


Objective
In this exercise you will create a simple application, which will display the text Hello World in a data field, when the user clicks on a set Push Button. The aim of this exercise is to familiarize you with the basic SQLWindows tools and their use.

Preview

Templates
None. This exercise requires you to start a NEW application.

Steps
Step 1: Step 2: Save any previous work. Start a new application.

Save it as Chapter 03 Exercise 1.app. Step 3: Create a Form Window (right click on the Windows folder in left pane, select New | Form Window). Give it a name frmHello. Step 4: Step 5: Using the Attribute Inspector, make the title of the form Hello World Application'. Using the Controls Palette, drop a Data Field onto the Form Window. Give it a name dfMessage. Step 6: Step 7: Using the Attribute Inspector, customize it so that it is Editable | No and Justify | Center. Drop two Push Buttons onto the Form Window. Give one a name of pbSet and a title of Set with the S as the mnemonic. Give the other a name of pbExit and a title of Exit with the x as the mnemonic. Step 8: Step 9: Step 10: Write the code for the pbSet Push Button to assign a value of 'Hello World' to the data field dfMessage. Write the code for the pbExit Push Button to quit the application. Save and test your application.

Optional Tasks
Step 10: Place a frame around the child objects. Step 11: Modify the push button pbSet to alternately clear or set the value of dfMessage.

Application ToolBars
A rectangular area, at edge of window, where you can place objects for frequently used functions. Can be defined for all top-level windows.

As you can see from the Attribute Inspector, you have additional settings for the Tool Bar: You can also specify weather the toolbar is Dockable and what locations the toolbar can be docked. This is where you can specify which edge the toolbar is on (top/bottom/left/right).

You can also create dialog boxes to be used as toolbars that are Dockable with Form Windows, MDI Windows, and/or Table Windows. The dialog box has to have the new property of Allow Dock to Parent set to Yes and the Parent Window must had its property of Allow Child Docking set to Yes.

Sample of common toolbar with flat pushbuttons

Exercise 3.2: Using Dockable Application Toolbars


Objective
In this exercise you will modify a simple application, to use a application toolbar. This toolbar will contain the two Push Button used to set and exit information in the window. The aim of this exercise is to familiarize you with the basic setup an a toolbar for a SQLWindows application.

Preview

Templates
Use template Chapter 03 Template 2.app or if you completed Chapter 03 Exercise 1.app, you may use that.

Steps
Step 1: Step 2: Save any previous work. Open the Template or previous exercise. Save it as Chapter 03 Exercise 2.app Step 3: Set Properties of the Window: Allow Child Docking = Yes Docking Orientation = All Accessories Enabled = Yes Docking Tool Bar = Yes Step 4: Move the two Push Buttons (Set & Exit) to the Toolbar) (hint, you will have to expand the toolbar to see them if you cut and paste) Step 5: Save and test your application. Try and making it a floating toolbar

See if you can move it to the bottom or the sides

Optional Tasks
Step 6: Change the properties of the form window to allow the toolbar to be docked on the sides

Chapter 4: Event/Message Programming


What We Will Cover
. . . . . . . . . . . . A World of Windows Objects SQLWindows Objects Where Messages are sent Who Sends Messages Event/Message/Action Examples Message Sequence Using Return in Message Actions Initialization of Child Object Values Object Validation User-Defined Messages Sending versus Posting Messages Good Programming Technique

A World of Windows Objects


All objects, (e.g. forms, data fields, push buttons), are windows in the context of a Microsoft Windows application. Microsoft Windows creates, maintains and destroys window objects on behalf of the application. SQLWindows takes one or more Windows (WM_*) messages and consolidates them into a single SQLWindows (SAM_*) message.

Event-driven
Microsoft Windows is an event-driven environment Windows waits for an event and alerts active application The user determines events Generally speaking, it is the end-user who controls events and as such it is the end-user who drives the application. For example, the user may click on a set of push buttons in a specific order to obtain one result. By clicking the push buttons in a different order, the application may produce a different output.

Hardware Events
At the most basic level, MS Windows has three hardware events. These events are keyboard events (key down, key up...), mouse events (clicking on the mouse buttons, moving the mouse...) and timer events (a form of hardware system clock).

Many other software generated events


There are many other events, some of which are derived from hardware events and some of which are generated by applications. For example, when an application is shutdown, an event is generated that results in the top-level window receiving a message.

SQLWindows is non-procedural
3GLs like C or Pascal are procedural based languages. SQLWindows, being event/message based, uses objects that 'listen' for a message. When they receive the message they carry out an action, hence the term non-procedural. Events and messages control the flow of the program.

Window objects communicate via messages


All window objects communicate with messages. The messages are the protocol for communication. A message is simply a hexadecimal number in the range of 0 to 0xFFFF.

Where do messages originate?


Messages can originate from Microsoft Windows, SQLWindows or the application's code. Applications send messages to objects; if the object has a handler defined for the message (e.g. a section of code that means "When I receive message number #### I carry out action XYZ"), then action XYZ will be executed. The message (number) is a way to uniquely inform the object which message has arrived. An event generates a message and, if the object is handling the message, an action will result.

SQLWindows Objects
What is an object?
Each SQLWindows object has a corresponding Outline section.

How do objects behave?


Passive
In SQLWindows, background text, group boxes, frames and lines are passive objects. Passive objects cannot receive messages, as they do not have a Message Actions section in the object outline. (Additionally, background text, lines, and frames are "painted" onto a form by default. As such, they are not considered true objects in the Windows sense. This behavior can be overridden by setting bStaticAsWindows = TRUE before the parent window is created.)

Active
Active objects are a second type of Windows object and have a message actions section defined in the object outline. An active object can receive a message and can handle that message if required to do so. To handle a message, the object performs an action block (which could involve sending another message). For example, when a user clicks on a push button a SAM_Click message is sent to the Push Button.
note

note

Use SalGetFirstChild() and SalGetNextChild() to cycle through a parents child objects

Event/Message/Action Flow
An event causes a message to be sent to an object

An event generates a message, the message is sent to a window object and, if the object is instructed to handle the message, an action results. If a message is handled, the object processes it by performing some action(s). An action can involve generating more messages. If the action involves issuing a Return statement then processing for the message will cease. If no Return is issued, the actions will continue until the end of the code block is reached.

Where Messages are sent


To the application
The template definition for each active object contains a Message Actions section. The exception to this is the application itself, which is an object and has its own Application Actions section that can handle messages. Not all objects can receive all messages. For example, only the application object receives a SAM_AppStartup message. The application receives this message before any application windows are created. A push button (often referred to as simply a button) cannot receive a SAM_AppStartup message. It does not make sense to try and process this message for a push button since the message is sent prior to any application windows being created.

To a window object
button will appear 'grayed out' on the screen and will not accept any messages. The push button needs to be enabled before it will start to receive messages. The push button is a child object of the form window called frmMain. The form also has a message action section that handles specified messages. In this case, the form is handling a SAM_Close message, which is sent to the form when a user wishes to close the form down.

Who Sends Messages


Microsoft Windows, SQLWindows run-time or the application itself can send messages. Messages sent by the application are Microsoft Windows messages, SQLWindows messages or User Defined messages.

MS Windows
Event-driven messages such as WM_KEYUP
Microsoft Windows messages are event-driven. For example, when a key is released after being depressed, a WM_KEYUP message is sent. Similarly, when a key is depressed a WM_KEYDOWN message is generated.

Generated messages such as WM_PAINT


Microsoft Windows messages can be generated by another event, for example, when a window positioned over an underlying window is closed. The underlying window needs to be re-painted. The message needed to repaint the window occurs as an indirect result of a hardware event. For example, clicking on the close menu option of the window. In this case, a WM_PAINT message would be generated.

SQLWindows run-time

Event-driven messages SAM_Timer


(Same as MS Windows WM_TIMER message) SQLWindows run-time messages are also event-driven. For example, the SAM_Timer message (which is actually the WM_TIMER message renamed) is generated by the system timer. The message is sent every N millisecond's, where N is a parameter of the SalTimerSet() function.

Generated messages SAM_Click


(From MS Windows WM_LBUTTONDOWN and WM_LBUTTONUP)

SQLWindows application
Sent via SAL functions to a window object SalPostMsg() adds a message to the object's message queue Message transmittal is asynchronous SalSendMsg() sends a message immediately to the object Message transmittal is synchronous SalSendMsgToChildren() sends a message immediately to the children of the object

SQLWindows Message Example


The Message Actions section of the form is where a window object handles the SAM_Create messages. While the form is being created the push button pbOk remains disabled and the wait cursor is displayed as an hourglass. Once the creation of the form is complete, the form receives a SAM_CreateComplete message and the window is displayed. If the data field dfStatus has an 'OPEN' status, then pbOk is enabled for use. The wait cursor reverts to its previous state.

Event/Message/Action Examples
Event
Application startup Check box creation Click on a push button Type character in a field Close a form window Application exit An SQL error SAM_Create SAM_Click SAM_AnyEdit SAM_Close SAM_AppExit SAM_SqlError

Message
SAM_AppStartup Connect to the database Disable selection Assign a data field value Enable a push button

Action

Prompt for application to terminate Disconnect from database Display error to the user

Message Sequence
As Windows programmers, we rarely control the sequence of hardware events and their resulting messages. It is important to understand which events spawn which messages. This is particularly true for top-level window create and destroy.

Form Window Creation


SAM_Create is sent to the form window

SAM_Create is sent to each child object, in the order they appear in the outline (usually) After all windows objects on the form window have been created, SAM_CreateComplete is send to the form window.

Form Window Close


SAM_Close is sent to the form window. SAM_Destroy is sent to the form window. SAM_Destroy is sent to each child object, in the order they appear in the outline (usually).

Using Return in Message Actions


Many messages are sent first to your SQLWindows application, then to the MS Windows OS. In these cases, executing a Return statement in your SQLWindows application will halt message processing not only for your program but also for MS Windows itself.

Examine the code below:

In this example, the value on the Return statement is actually not relevant! The mere execution of the Return statement blocks window close processing. The MS Windows OS never receives the close message and never acts on it.

Initialization of Child Object Values


Each child object received SAM_Create, as it is created and assigned a window handle by the MS Window OS. Handling SAM_Create provides a opportunity to initialize child object values. good

By initializing the check box cbSQLWindowsCustomer to TRUE, it appears initially checked.

Object Validation
Child objects receive SAM_AnyEdit as the user alters their value (key stroke by key stroke.) Altered data fields, multi-line fields, combo boxes and table window columns have their internal field edit flag set to TRUE. The state of a child object's field edit flag can be tested with SalQueryFieldEdit, and set or cleared with SalSetFieldEdit.

SAM_Validate message
When the user attempts to switch the focus a way from an altered child object, a SAM_Validate Message is set to it.
In the SAM_Validate message action, the application may return one of these constant values: VALIDATE_Ok - Allows focus to move as the user intends VALIDATE_OkClearFlag - Allows focus to move as the user intends and sets the object's field edit flag to false VALIDATE_Cancel - Forces focus back to the current field SAM_Validate processing is not suitable for mandatory field processing. If the user never goes into the field, it will remain empty and no SAM_Validate will ever be sent to it.

SalSendValidateMsg
SAM_Validate is sent to a child object when its value has been altered, and the user attempts to switch focus to another object. Clicking on a menu item or the parent window's close icon (upper right corner) does not switch focus. A well-written SQLWindows application will call SalSendValidateMsg prior to the close of menu triggered save processing. SalSendValidateMsg identifies and sends a SAM_Validate message to that child object which has been altered but not yet messaged. Typically, the return value is tested, as in the example below.

Exercise 4.1: Event/Message Programming


Objective
In this exercise you will create a simple prototype customer entry form window.

Preview

Template
None. This exercise requires you to start a NEW application.

Tasks
Step 1: Save any previous work. Step 2: Start a new application. Save it as Chapter 04 Exercise 1.app.

Step 3: Create a new Form Window. Name it frmCustomerEntry and title it 'Customer Entry'. Step 4: Add data fields dfName, dfAddress, dfCity, dfState, dfZipCode, dfCountry and dfCreditLimit. Step 5: Set the input mask on dfZipCode to 99999. Step 6: Set the data type on dfCreditLimit to numeric. Step 7: Set the format on dfCreditLimit to #,##0.00. Step 8: Add ON SAM_Create processing to initialize fields as follows: dfCity - 'Redwood Shores' dfState - 'CA' dfCountry - 'USA' dfCreditLimit - 5000

Step 9: Add SAM_Validate processing to dfCountry to ensure that it is either USA' or 'Canada'. Similarly, validate to ensure that dfCreditLimit is between 0 and 100,000. Step 10: Add SAM_Close processing to the form window to refuse a close request if SalSendValidateMsg() returns VALIDATE_Cancel. Step 11: Save and test your application.

User-Defined Messages
A message is simply a number and both Microsoft ans SQLWindows reserve the use of sets of message numbers. SAM_User is an internally defined constant, which marks the end of Microsofts, and SQLWindows reserved messages and the beginning of the messages, which are available to users of SQLWindows. We recommend that you prefix user message names with PAM_ or PM_. If you do, these messages will appear as such in the Coding Assistant.

Additional Message Information

Additional numeric information may be sent with a message. This is by means of two variables: wParam and lParam.

wParam and lParam


These variables are both 4 byte (LONG) and are assigned by the SQLWindows run-time; both could be zero. They are the third and fourth parameters in: SalPostMsg(), SalSendMsg(), SalSendMsgToChildren()

Using wParam
Here is an example of the use of wParam:

SalSendMsg(dfStatus,PAM_Clear,TRUE,0)
In this example the message is sent to dfStatus; the message being sent is PAM_Clear. When dfStatus receives this message, wParam is TRUE and lParam is 0. When dfStatus receives the PAM_Clear message, if wParam is set to TRUE, the field is cleared.

This example demonstrates the ability to test Booleans by simply checking their existence. 'If wParam' equates to 'If wParam = TRUE' and 'If wParam = 1'.

Sending versus Posting Messages


Sending
Sending is synchronous and immediate SalSendMsg() and SalSendMsgToChildren() cause execution to jump to the message action of the referenced object. The 'called' message action can return a numeric (or Boolean) value.

Example of sending a message

Posting

Posting is asynchronous and deferred. A call to SalPostMsg() does not transfer flow of program execution. Instead it places the requested message on the windows message queue for the receiving object. The receiving object will react to the message when the application falls into an idle state. This is typically after the 'post' message action completes but could be much later. Post is preferable to send as it uses the underlying windows architecture to provide better object separation. However Post cannot check for a return value.

Example of posting a message

Good Programming Technique


It is considered poor programming technique for one child object to explicitly reference another. As much as possible, objects should be independent.

Avoid Direct References

Instead rebroadcast messages


A better approach is to have child objects rely on their parent to 'rebroadcast' the message. In this case the child object sends or posts the message to the parent, and the parent sends the message to the children. However the only function that can forward messages to the children is SalSendMsgToChildren(), which involves send instead of post.

Exercise 4.2: An OO Approach to Event/Message Programming


Objective
In this exercise, you will modify an application you created earlier (in Chapter 3), only this time we will take a more object-oriented approach by using messaging. This will provide the program with the flexibility to have multiple objects respond to a click on the push button pbSet . While we do not expect you to write a real world application that has four data fields that say "Hello World", you may have several combo boxes or list boxes that must know how to populate themselves. Remember that this concept is important and is the main focus of the exercise.

Preview

Templates
Use template Chapter 04 Template 2.app or if you completed Chapter 03 Exercise 1.app, you may use that.

Tasks
Step 1: Step 2: Step 3: Step 4: Step 5: Save any previous work. Open the Template or previous exercise. Save it as Chapter 04 Exercise 2.app. Create a global user defined constant PAM_AppMessage. If you did not complete the optional exercise in Chapter 3, create a window variable of Boolean data type and call it bValueSet. Modify the code for pbSet: Remove the code, which sets the value in dfMessage. Send your new message to all the children of the form with a wParam value that may be either TRUE or FALSE (the best way

to do this is send bValueSet). Step 6: Modify the code for dfMessage: Handle the message PAM_AppMessage. When the message is received, evaluate wParam. If wParam is TRUE, set the data field value = "Hello World". If wParam is FALSE, clear the data field. Hint: You might want to use MyValue here. Step 7: Step 8: Step 9: Step 10: Save and test your application. Resize the form and the optional frame to be a bit longer, similar to the one in the Preview. Duplicate the data field three times making sure that each instance has a unique Object Name. Save and test your application again. Each data field you duplicated should behave exactly the same as your first. If so, you have completed the exercise correctly. If not - ask your instructor for ideas to fix the problem.

Chapter 5: A Simple Event-Based Application

What We Will Cover


. . . . . . . Demo 5.1: SALCulator Demo 5.2: Defining User Messages Using the Case Statement Using Simple Assignments Using Message Boxes Using Case, Assignment and Message Boxes Closing a Parent Window

Demo 5.1: SALCulator


We will demonstrate using the Controls Palette and Atribute Inspector to create and customize some visual objects. Creating the Form Window Setting Form Window properties Creating numeric Data Fields Creating Push Buttons Creating borders and lines

Demo 5.2: Defining User Messages


We will demonstrate defining User or Program Application Messages (PAM). In addition we will demonstrate using PAM and User constants. The dfnResult field must carry out the arithmetic required to determine its correct value.

Message Action Sequence


Push Buttons send messages to their parent (hWndForm). The Form Window receives the messages and broadcasts them to its children. Those children that handle the specific message will act upon the message.
note

Using PAM Messages, User Constants and wParam

Notice the use of the user defined constant ADD. It is being passed as wParam. The above screen capture illustrates the code that resides in the Message Action section of the push button pbAdd. With the exception of the constant (ADD) being passed in wParam, the code is identical for push buttons pbSub, pbMult and pbDiv. The parent receives the message and passes the message on to its children

note

This illustrates the code that resides in the message actions section of the push button pbClear

The following sergment of code resides in the Form Window Message Actions section.

Using PAM Messages


Each data field must know how to clear itself. When each data field receives the message PAM_Clear, it will call a function.

The remaining data fields, dfVar2 and dfnResult have the same code residing under their actions section as well. The reason we use a function is to provide a generic piece of code that will work regardless of the data type of the object.

Using the Case Statement


We will discuss the syntax of the Case statement in a later chapter

Example of Case Statement


Select Case nPaymentType Case PAYMENT_Late Set nTotalPayment = nTotalPayment + nLateFee Break Case PAYMENT_Current Set nTotalPayment = nTotalPayment + nRegularPmnt Break Default Set gnError = 108 Break

Using Simple Assignments


Syntax

Set <variable/fieldname> = expression

Example of Simple Assignments


Set dfnResult = dfnVar1 * dfnVar2 Set dfnVar1 = 0

Using Message Boxes


Syntax
nResult = SalMessageBox(strText,strTitle,nFlags)
strText: The message text: You can enter multiple lines of text by pressing Ctrl+Enter to start a new line. StrTitle: The message box title. nFlags: Message box style. MB_*

Example of a Message Box

Call SalMessageBox(Divide by ZERO', 'SALCulator', MB_Ok|MB_IconInformation)

Using Case, Assignment and Message Boxes


Using the statements just covered, the following code was written in our application at the Message Actions section of the data field dfnResult.

Closing a Parent Window


Syntax

Call SalSendMsg(hWndForm,SAM_Close,0,0)
Sends a SAM_Close statement to the parent window. If the parent does not handle SAM_Close the parent window will close automatically. If the parent does handle SAM_Close it can check to see if the user has any changes that were not saved. If so, it may prompt them to return and save those changes. Otherwise, the user may choose to close the window and lose the changes.

Example
Push Button pbExit

Exercise 5.1: A Simple Event-Based Application


Objective
In this exercise, you will create and test a simple application that illustrates the use of Programmer Application Messages and the use of wParam as a method of sending additional information. The aim is to create a simple SALCulator, like the one you have just seen demonstrated.

Preview

Templates
None. This exercise requires you to start a NEW application.

Tasks
Step 1: Step 2: Step 3: Step 4: Step 5: Save any previous work. Start a new application. Save it as Chapter 05 Exercise 1.app. Create all necessary PAM constants and user constants. Create a parent Form Window. Create three numeric data fields: One for the first value; One for the second value;

One for the result of any calculation - this data field should not be editable. Step 6: Step 7: Create Background Text item(s) for clarity. Create Push Buttons: One for Add; One for Subtract; One for Multiply; One for Divide; One for Exit; One for Clear. Step 8: You have now completed with the visual attributes and it is time to start programming the functionality. Turn to the Message Actions sections of the objects just created. Step 9: Step 10: Step 11: Code at the Form Window level to pass messages along (including wParam) to all child object that may handle the message. Code at the Data Field level to act upon the message(s) they receive such as Clear or calculate. Save and test your application.

Chapter 6: SAL Components


What We Will Cover
. . . . . . . . . . . . . What is SAL? SAL Data Types Variable Declarations System Variables Variable Qualification Window Handles Arrays Array Functions Command Line Arguments Operators Variable Expressions Constants System Constants

What is SAL?
SAL -Scalable Application Language consists of: Data types Arrays Expressions Variables Operators Constants All of the above will be covered in this chapter. The following items will be covered in following chapters: Language statements Functions Object-oriented programming features

SAL Data Types


Boolean
Boolean is either TRUE (1) or FALSE (0). Note: there are pre-defined system constants for TRUE and FALSE (discussed later in this chapter).

Date/Time
Date/Time can be a date variable, a time variable or a datetime variable.

File Handle
File Handle a 32-bit number used to uniquely reference a file. When a file is opened, the function, which opens that file, returns a file handle, which is used to determine the drive, path, filename and extension of the file.

Binary
This data type, introduced in TD 5.2, provides better support for binary data within SAL, including data from BLOB columns. To assign a value to a BINARY variable, use SalPicSetBinary, the BINARY_Null constant, or another BINARY variable. Example

Variables BINARY: binInput BINARY: binPic Set bOk = SalPicGetBinary(hWndPic,PIC_FormatObject,binInput) if (bOk) Set binPic=binInput

Long String
Long String is used when reading and writing LONG data (greater than or equal to 255 characters) with SQL databases.

Number
Number is used to store a number of any type. Specification of the number as a float, integer and so forth is not required. SQLWindows automatically allocates memory required for numeric data types and will also handle precision. If the result of a computation is numeric, SQLWindows will also automatically resolve any data type issues. For example, if an integer is divided by a float, SQLWindows will assign the result to a float.

Session Handle
Session Handle is similar to a File Handle but it is used to reference a session with a SQL database.

SqlHandle
SqlHandle is similar to a File Handle, but used to uniquely reference a connection to a SQL database.

String
String is a string data type, having no size limit other than available memory.

Window Handle
Window Handle is also similar to a File Handle. When a window is created, Microsoft Windows automatically assigns a Window Handle for that object. The Window Handle is unique for each object and is valid for the life of the object. Once the window has been closed, the handle can be re-used. Note: an object, which is minimized, is not closed.

Functional classes
Functional classes can be used as User Defined Variables and are covered in a later chapter.

Naming Conventions
The uses of prefixes for the data types are industry standard for Windows applications and are called Hungarian notation (in honor of the legendary Microsoft programmer Charles Simonyi). They are highly recommended. Using this notation will make it easier for other developers to read and maintain your applications. An example of Hungarian notation for a Boolean data type is bVariable.

Receive Data types


All data types can be defined as Receive data types in the Parameters section of Functions. This will be discussed in more detail later in the course.

Variable Declarations
SQLWindows is case sensitive so following a naming convention is important. As suggested earlier, the Hungarian notation is probably the best naming convention to use.

Syntax
<data type>: <variable_name>
The declaration location in the outline depends upon the scope of the variable.

Global Declarations
Variables

Local to an Internal Function


Static Variables Local Variables

Local to a Parent Window


Window Variables

Local to a User-Defined Class


(Discussed in a later chapter) Class Variables Instance Variables

Variable Declaration Examples


Global Declarations
In the example below, a variable (bQuit) of type Boolean is declared in the Global Variables section and a Window Handle (hWndReportWindow) is used to assign the value of the Window Handle to a Report Window

Form Window
The form frmBrowsePresidents has a child object of type Child Table called tblPresident. tblPresident has a Window Variables section where variables are declared within its scope.

System Variables
Variable
hWndForm hWndItem hWndMDI SqlDatabase SqlUser SqlPassword SqlResultSet wParam lParam nArgCount Window Handle Window Handle Window Handle String String String Boolean Number Number Number

Data Type

SqlInMessage SqlOutMessage SqlNoRecovery bStaticsAsWindows strArgArray[*] SqlIsolationLevel MyValue

Number Number Boolean Boolean String array String <current item reference>

MyValue has no set data type and is useful for defining classes and class message handlers. bStaticsAsWindows has a default value of FALSE. When bStaticsAsWindows is set to FALSE, any passive objects being created on a form are painted. This saves system resources and provides better performance. However, passive objects can be created as separate objects and accessed using the SalGetFirstChild() and SalGetNextChild() functions. For this to happen, bStaticsAsWindows must be set to TRUE. STRING_Null is included here (arguably) as a system variable. Even though its value is constant (" "), its data type dynamically changes to string or long string, depending on usage.

Variable Qualification
There are three ways to reference a variable, not including referencing class and instance variables. The referencing of class and instance variables will be covered in a later chapter.

Unqualified (simple) reference


The first type of referencing is a single or unqualified reference. A single reference is where only the object or variable name is used to specify the required object or variable.

Syntax
<variable/object_name>

Example of unqualified reference


Set dfDate = SalDateCurrent()

Qualified reference
A qualified reference uses the form name (or template) and the object or variable name to identify the object or variable. This method of referencing is used when two or more top-level objects have variables or objects of the same name.

Syntax
<form_name>.<variable/object_name>

Example of qualified reference


Set frmMain.dfDate = SalDateCurrent()

Fully-qualified (or Window-qualified) reference


A fully qualified, or window qualified, reference uses the Window Handle of the parent form to uniquely identify the child object or variable. Fully qualified referencing can be necessary if the application allows multiple instances of a form to be created at run-time.

Syntax
<parent_window_handle>.<qualified_reference>

Example of fully-qualified reference


Set hWnd.frmMain.dfDate = SalDateCurrent()

Window Handles
When a window is created, a unique window handle value is established by Microsoft Windows for that object. The window handle is used for accessing that window. The window handle value remains for the life of that window. A window handle is a number value (range: 1 to 4,294,967,295). Window object names can be used as function parameters requiring a parameter of type window handle. How is dfField being used in each of the following?

Call SalSendMsg(dfField, SAM_Validate, 0, 0)? Set dfField = 'some string'?

System Variables for Window Handles


hWndForm
The current (active) parent window handle hWndForm refers to the parent form whose child object currently has input focus. Input focus or focus is the area of a window which receives keystrokes or mouse actions.

hWndItem
The item which currently has the focus, or which is currently receiving a message. hWndItem refers to the child object which currently has focus or which is currently receiving a message. In the case of a table window, hWndItem refers to the column, which currently has focus. In the event of a form having no child objects, or a Table Window having no columns (e.g. On SAM_Create for the objects), then hWndForm = hWndItem until the first child object is created.

hWndMDI
The current MDI parent window handle

Examples of hWndItem and hWndForm

Getting the Window Handle


During SalCreateWindow()

Using SalGetFirstChild() and SalGetNextChild()

Arrays
SQLWindows supports three types of array declarations. The arrays can be of any valid variable type, including an array of functional classes instances (UDVs). Elements start at position zero (by default). The first element is at position zero (unless a range is declared other than zero)

Syntax
<data type>:<variable name>[ <array_size> ]

Array_size options
Arrays can be expressed as either a number of elements or as a range of elements, where the start and end of the range is supplied. Arrays can also be dynamically sized. Arrays can be multi-dimensional. However, only the first dimension can be dynamic. Consult your SQLWindows manual or on-line help document for more details. However, only the first dimension of a multi-dimensional array can be dynamic

Number of elements
[n]

A range of elements
[ n:m ]

A dynamic range
[*]

A dynamic range that starts with a non-zero lower bound


[1:* ]

A 2-dimensional array
[ n, m ]

A 4-dimensional array
[ *, n, m, p ]

Array Examples
The array dtMonth[1:12] is an array of datetime variables, which starts at element 1 and goes to element 12. The array could have been specified as dtMonth[12]. This would give an array with 12 elements, but the range would have been from dtMonth[0] to dtMonth[11]. It is probably easier to use 1 to 12 as we do in every day life.

The array nID and has a dynamic range. The elements of this array begin at zero.

Questions
How many elements are there in the array sError? What is the range of sError?

Array Functions
Array functions are available for querying and changing the size of an array.note

note

The second parameter of the SalArray*Bound( ) functions are the dimension of the array. For standard single dimension arrays this will be one (1).

Command Line Arguments


There are two SQLWindows variables for handling command line arguments: Command line arguments are parameters on the command line, which invokes a SQLWindows application executable (*.EXE)

nArgCount
nArgCount is the number of command line arguments. The number of command line arguments always includes the name of the .exe or .run file. This means nArgCount will always be >=1.

strArgArray[ * ]
strArgArray[ * ] is an array of command line arguments. strArgArray[0] will always represent the name of the application (including any specified path). Elements 1, 2, ..... are subsequent arguments passed to the application.

Example: Invoking an application with command line arguments

List Box outline code

Operators
Numeric
+, -, *, /

Unary
The unary operation - negates a value and hence needs only one operand

Relational
=, !=, >, <, >=, <=

Parentheses
( )
Parentheses ( ) are used the same as in all major languages. In the case of nested parentheses, the inner most parentheses are evaluated first and then evaluation takes place as the level of nesting reduces.

Boolean
AND, OR, NOT These are the only case-insensitive words in SAL.

Bitwise
The bitwise AND operator is & and the bitwise OR operator is |.

String Concatenation
||

Variable Expressions
Variable expressions (which may consist of a function; a variable, including a field or another window; a constant or a combination of expressions and operators) always equate to a single value.

Examples
Set dfDate = SalDateCurrent()
The function returns a single value, which is assigned to the dfDate data field.

Set nSalary = nGrade[JUNIOR] + BONUS


The constants JUNIOR and BONUS have been declared to the application (in the global declarations, constants, user section) and have a data type of number. The array nGrade[ ] is of data type number. Suppose JUNIOR = 1 and BONUS = 15000. The example above would set nSalary to the value in the second element of array nGrade[ ] (the first element is element 0) plus 15000. This expression would still only return a single value.

Constants
May be defined for these SQLWindows data types Boolean Date/time Number String

Syntax
<data type> : <constant name> = <constant expression>
A constant expression is similar to a variable expression except that it may not contain references to variables.

System Constants
SQLWindows has a number of pre-defined system constants TRUE FALSE NUMBER_Null DATETIME_Null OBJ_Null hWndNULL hWndNULL is the null window handle. A window handle is simply a number, therefore hWndNULL can be tested to equal zero. If the SalCreateWindow() function returns hWndNULL, this means the window was not created successfully. SAM_User STRING_Null In some databases, a Null string differs from a zero length string. In SQLBase they do not.

Chapter 7: SAL Language Statements


What We Will Cover
. . . . . . . . SAL Statements SQLWindows Function Types External Functions Demo 7.1: External Functions Internal Functions Receive Parameters Demo 7.2: Receive Parameters Top-Level Window Parameters

SAL Statements
SAL has the following statements. We will discuss each one of them in more detail in the following pages. Call If ... Else If ... Else Loop ... Break On Return Select Case ... Case ... Default Set When SQLError While ! Comments

Call Statement
The Call statement invokes a function. Functions can be invoked either explicitly via the Call statement or implicitly in another statement.

Syntax
Call <function_name( [ parameter1[, ] ] )>

Example
In this example we see both explicit and implicit invocation of functions. SalQuit, SalNumberToStr and SalMessageBox are invoked explicitly, whereas SalStrLeftX and SalStrLength are invoked implicitly as part of an expression. Functions can be nested and called recursively, assuming the logic within the function accommodates recursive calling. In the example, SalStrLeftX( sErrorString, SalStrLength( sErrorString ) - 4) we see nested calling of functions. Also, you will note the use of the exclamation mark (!) at the beginning of a line for comments.

IF Statement
The 'If' statement is used to control logic by testing the value of a variable. If the test returns TRUE, all code underneath and indented below the If statement is executed.

Syntax
If <expression1> statement(s)... [ Else If <expression2> ] statement(s)... [ Else If <expression3> ] statement(s)... [ Else ] ...statement(s)...

Notes
If NOT <expression> can also be tested. The Else and Else If are optional, although very often used. The logic is controlled by the indentation of the code. There is no need for the Begin...End, or { } statements to control the execution of the code.

Example
The application has two numeric constants declared, RESET = 1 and SAVE = 2. There is also a numeric window variable declared as nValue. The Actions section is from a menu of the form.

LOOP Statement
The Loop and Break statements are used in conjunction to loop through a block of code until a required breakpoint is reached. If there is no Break then the application will continue to loop forever!

Syntax
Loop [loop_name] Break [loop_name]

Example
If Break is executed in a nested loop then the application will break out of the current level of loop. That is to say, it will break back one level. In this example, the loop is performed 100 times. Once n = 100 then the Break is encountered and we break out of the current loop.

Named Loops
When a loop is defined it can optionally be given a name. The loop name can be used to break out from any level of nested loops by using Break name, where name is the name assigned to the loop.

Example

ON Statement
The On statement is used to define a message handler.

Syntax
On <message_name>

Example
The example shows the code executed when the form is created. The code defines the Database, user name and password for the database connection. The connection to the database is made using the SqlConnect(hSql), where hiSql is a variable declared elsewhere. The SalFileGetCurrentDirectory(siCurrentDirectory) assigns the value of the current directory to the variable siCurrentDirectory.

RETURN Statement
The Return statement can often be confusing because of its various meanings and uses. In some cases it is used to return a value to the calling statement. In other cases it is used to stop further processing.

Syntax
Return <return_value>

Return a value
Here, the function is simply returning a value for a variable. The return section of the function specifies the data type to be returned, not the variable name. The function performs some processing and returns the value of the variable. To work correctly, this example ought to have defined the variable nValue as a Static Variable in order to preserve its value between calls. Otherwise (as in this code), nValue will always have a value of 100 when it is returned.

Halt processing
In this example, the Menu Return is being used to halt processing. Return does not stop the application itself, but it will stop processing the current message loop. We could return anything, so return StopProcessingMessage might be another example, provided StopProcessingMessage had been declared as a constant.

SELECT CASE Statement


The Select Case statement tests a numeric expression to see if the expression matches one of the Case conditions. If the expression matches the case statement, then all of the code underneath and indented from the case statement is executed until a Break clause is executed or the end of the Select Case .

Syntax
Select Case <number expression> Case <number constant1> ...statement(s) Break [Case ... ...statement(s) Break ...] [Default ...statement(s)]
The Default case should always be included to account for the situation when the numeric expression does not match any of the Case conditions.
NOTE

Example
In this example, the constants for CLOSE, DELETE, OPEN_READ & OPEN_WRITE are declared elsewhere. When the DoFileHandling() function is called it takes four parameters: a file handle (hFile), a string holding the name of the file (sName), a number for the command (nCommand) and a number (nOpenFlag) containing the OF_* constant which is used by the OPEN_READ and OPEN_WRITE command to indicate whether a READ or WRITE open is required. The Actions Section has a Select Case, which checks the value of nCommand (the third parameter passed to the function). If nCommand = CLOSE then the SalFileClose() function is called. If nCommand = DELETE the SalFileOpen() function, with the OF_Delete is called to delete the file.

If nCommand = OPEN_READ or OPEN_WRITE the same block of code is executed. This is because there is no Break indented and underneath the Case OPEN_READ statement. If nCommand NOT = CLOSE, DELETE, OPEN_READ or OPEN_WRITE, then the default action is executed. In this example, a message box is displayed with the error message.
NOTE

The Break statement may be required. Otherwise program flow continues into the next block.

SET Statement
Set is used to assign a value to a variable, including setting the 'visible string attribute' of a window object. The variable must be declared before it can be used. If a variable is not declared then an error will occur during compilation.

Syntax
Set <variable/field name = expression>

Example
In this example, the following two lines of code result in the same thing:

Set nRtn = SalSendMsg(dfStatus, PAM_EVALUATE,0,0) Set nRtn = dfStatus


In an earlier example, we defined a message handler for the dfStatus object to trap the PAM_EVALUATE message and return the current setting of dfStatus. The second statement sets the value of nRtn equal to the current setting of dfStatus.

WHEN SQLERROR Statement


When SQLError defines a local error handler for an SQL function. The When SQLError statement needs to be defined prior to the function call, which generates an error, and at the same level of indentation within the object's outline.

Syntax
When SQLError [statement] [statement] Call <Sql* function>

Example

WHILE Statement
The While statement is an alternative to the Loop statement. Any code indented and following the While statement will be executed each time the loop is entered.

Syntax
While <expression> [statement]

Example Questions
What is the difference between the Loop and the While statements? Which is better: a Loop or a While statement?

SQLWindows Function Types


SQLWindows has four types of functions. In addition to the SAL and SQL functions there are External and Internal functions.

SAL and SQL functions


These are provided as part of the SQLWindows run-time environment. Argument template information is provided for each function by the Coding Assistant.

External Functions
External functions only contain the argument template information for the function in the application's Global Declaration > External Functions section. There is no code to define the logic of the function within the application. External functions which are stored in DLLs ( Dynamic Linked Library) for Microsoft OS or LIBs for Linux. USER32.DLL, for example, is a DLL used extensively by Microsoft Windows. They can be defined either by Function Name or by Export Ordinal. If you use the correct function name you can specify 0 for the export ordinal. Each function has an ordinal number declared in the library's *.DEF file. You can determine a function's export ordinal by running a utility such as QuickView.

Demo 7.1: External Functions


Placement of External Functions

The Library name is the name of the DLL containing the function(s) you intend to use in your application. The Function name is the name by which you are going to reference the function from within your application. The function name does not have to be the same name as the function within the DLL, as long as the correct ordinal number is specified. The Ordinal number is a unique positive integer, which identifies each function within the exports section of the module definition file. It can be 0 if the correct function name is specified. The ordinal numbers for all of the functions within a DLL should be well documented, along with the return type for the function, the parameters for the function and a description of what the function does.

External Function Template

The lines of code above determine the Window Handle of the menu and call the external function below to append a menu item to the system menu.

In the Parameters section, a mapping is provided between the SAL data types we will use in our program, and the C data type employed by the external function. There is no logic within the SQLWindows application; it is all contained within the DLL. The DLL being used is USER32.DLL, which is used by Microsoft Windows to define both the user interface and windowing. The application used in this demonstration is Chapter 07 Demo 1.app. The function call in this example is from the USER32.DLL found in the SYSTEM sub-directory of your WINDOWS directory.

Internal Functions
An Internal function has the code for the logic of the function contained within the application itself and is written purely in SAL. Argument template information is provided for each function by the Coding Assistant.

Placement of Internal Functions


Internal Functions can be defined in a number of places in the SQLWindows outline

In Global Declarations
Internal Functions section

In the Functions Section of Parent windows


Form Window MDI Window Table Window Dialog Box

In the Functions Section of Child Table Windows.


(To be discussed in a later chapter.)

In Class Definitions.
(Also to be discussed in a later chapter.)

Internal Function Template


The template for an internal function is similar to that of an external function, but it has three additional sections. The additional sections are for Static variables, Local variables and an Actions section. The parameters and returns are also slightly different in that they are only of the SQLWindows data types. The name of each of the Parameters passed to the function is for use within the function only. The name is simply a label to reference the parameter. The name of the parameter does not need to match the name of the variable being passed, but the data types must match. Variables can be passed either as an ordinary parameter (by value) or as a receive parameter (by reference). The Returns section specifies the data type, which the function will return. You do not specify the name of the variable you will be returning, only the data type. Static variables are initialized when the application is launched and their value will persist for the duration of the applications life. If the variable is assigned a value, it will remain set to that value until it is reset explicitly, or the application is stopped. Local variables are only in scope within the application. The Actions Section is where the logic for the function is defined.

Receive Parameters
A reveive parameter is a data type that lets you pass data to a function by reference rather than by value. Receive variables allow the called function to change the variable passed by the calling function. Receive parameters may be any valid SQLWindows data type As the fourth parameter we are passing the name of dfnResult. Because this is defined as a receive parameter on the next page, we are actually passing the address of dfnResult, not a value.

Demo 7.2: Receive Parameters


This example demonstrates the use of an internal function, with a receive parameter This example mirrors the upcoming exercise. The Actions section is continued on the next page. Notice that nowhere in the function do we "return" nResult. It is not necessary since we have declared it as a Receive parameter. The word receive indicated that we have passed the address of dfnResult, and not simply a value. When we alter the value of nResult in our function, we are actually altering the value of dfnResult, our fourth argument. The expanded Select Case statement follows.

Select Case statement.

Top-Level Window Parameters


Top-level window may take a list of parameters. The form has a parameters section where parameters are declared. The parameter are declared in exactly the same way parameters for functions are declared. The only limitation is that a field cannot be passed as a receive parameter. A top-level form with parameters declared cannot be created automatically, it needs to be created using SalCreateWindow() or SalModalDialog(). These two functions take a variable number of arguments, depending upon how many parameters the window being created has declared, following the window name and ownership arguments.

Exercise 7.1: SAL Functions


Objective
In this exercise, you will modify the application that you completed earlier. This application has four push buttons that determine the value of wParam sent in the PAM_Calc message to the result data field. The data field dfnResult in turn executes the appropriate mathematical operation to determine its correct value. This was a good solution, but not as encapsulated as we would like since it references data fields other than itself. This means if one data field was simply renamed, the calculations in dfnResult would fail.

You will now create and implement an internal function. The internal function will resolve this problem and the code will be more reusable and portable as a result.

Preview

Templates
Use template Chapter 07 Template 1.app or if you completed Chapter 05 Exercise 1.app, you may use that.

Tasks
Step 1: Step 2: Step 3: Step 4: Save any previous work. Open the Template or previous exercise. Save it as Chapter 07 Exercise 1.app. Create a push button named pbError with a title of Test Error that will send a PAM_Calc message to the Form Window and in wParam send the number 10. Create an Internal Function at the Form Window level. Name the function fnMyCalc and define parameters for each of the following: One to determine the type of mathematical operation to be performed; one each for the first and second arguments; and a receive parameter to place the result in. Step 5: Additionally, you should find a way to implement an error checking routine using the Default portion of the case statement. For example, what if some value other than 1 through 4 were sent to the function? It would execute the Default case. This really would be an error since we only planned on Add, Subtract, Multiply and Divide. Modify the On PAM_Calc section of code for the data field dfnResult so that it calls your function. Save and test your application.

Step 6: Step 7:

Chapter 8: SQL Basics


What We Will Cover
. . . . . . . . What is SQL? SQLTalk and Database Explorer Demo 10-1: SQLTalk SELECT Statement INSERT Statement UPDATE Statement DELETE Statement COMMIT Statement

What is SQL?
SQL stands for Structured Query Language, a relational (set-oriented) database language that is made up of statements, which allow the defining, manipulating and controlling of data. It was originally developed by IBM and is now the industry/ANSI standard. It is English-like and non-procedural.

What Can SQL Be Used For?


Define and maintain database objects
CREATE TABLE CREATE VIEW CREATE INDEX ALTER TABLE DROP TABLE DROP VIEW DROP INDEX

Manipulate data
SELECT INSERT UPDATE DELETE

Control data access


GRANT REVOKE

Control transaction management


COMMIT ROLLBACK SAVEPOINT

SQLTalk and Database Explorer


SQLTalk is an interactive user interface for SQLBase only. If you are using another database than SQLBase, it is recommended to use Database Explorer. Both SQLTalk and Database Explorer allow you to: Execute dynamic SQL commands. Perform ad-hoc queries. Useful to test queries: Test for correct results & Test for acceptable performance SQLTalk is located in <Team Developer>\ directory as SQLTalk.exe. Database Explorer is accessed from Team Developer (Tools | Database Explorer).

Demo 10-1: SQLTalk


We will discuss the icons on the toolbar; the input and output panes; and demonstrate how it can be used to execute dynamic SQL for an adhoc query.

SELECT Statement
SELECT is used to retrieve rows of data SELECT can be used to Retrieve a subset of columns Retrieve a subset of rows Sort the retrieved data Retrieve data from more than one table Group the retrieved data rows Summarize data for groups of rows All data is returned in the form of a result table

Syntax
SELECT [ALL | DISTINCT] expression {,expression}

FROM tablename [corr_name] {,tablename [corr_name]}

Unconditional Retrievals
Retrieving all rows

Syntax for all columns and all rows


SELECT * FROM tablename

Syntax for selected columns and all rows


SELECT columnname {,columnname} FROM tablename

Simple SELECT Example


To find all films and the year they were made.

Query
SELECT film_name, release_year FROM hollywd.film;

Qualifying the Data to Be Retrieved


WHERE clause
SELECT ... FROM tablename WHERE search_condition ...

Examples
SELECT character_name FROM role WHERE first_name = 'Humphrey';

SELECT film_name, director FROM film WHERE release_year > 1985;

SELECT * FROM prod_company WHERE country = 'France'; SELECT film_name, genre, star_rating FROM film WHERE run_time_mins >= 120 AND run_time_mins <= 180;

Commonly Used SQL Operators


Comparison
= != <> > < >= <=

Arithmetic
+, - (sign) *, / +, - (addition/subtraction)

Logical
NOT AND OR

Pattern Matching
The LIKE predicate searches for strings that match a specified pattern. It can only be used with CHAR or VARCHAR data types. These searches are case sensitive.

Syntax
columnname [NOT] LIKE pattern
There are two pattern match characters. Underscore (_) matches any single character . Percent (%) matches 0 or more characters.

Pattern Matching Example

To find all films which begin with the letter "A".

Sorting Data
ORDER BY specifies the ordering, or sorting, of rows in a result set. Rows can be sorted on more than one column. The major sort is on the first column specified in the ORDER BY clause with the minor sorts on columns specified after that.

Syntax
SELECT ... FROM tablename [WHERE search_condition] [ORDER BY columnname [ASC | DESC] {,columnname,}]

Example
SELECT film_name, director, genre, release_year FROM film WHERE release_year > 1978 ORDER BY release_year DESC;

Aggregate Functions
An aggregate function computes one summary value from a group of values. Can be applied to the data values of an entire table or to a subset of the rows in a table Sometimes known as 'Set functions'

Available functions
AVG COUNT

MAX MIN SUM

Examples
SELECT AVG(run_time_mins) FROM film;

SELECT MIN(release_year) FROM film WHERE director = 'Coppola';

Retrieving Data from Multiple Tables


A join obtains data from two or more tables by linking the tables on common columns The names of the joined columns need not be identical Ideally the columns being used to join should be of the same domain (or data type)

A Simple Join
Task
Find which production company made the film 'Casablanca' and also which country.

Query
SELECT prod_company.company_name, prod_company.country FROM film, prod_company WHERE film.film_name = 'Casablanca' AND film.prod_comp_id= prod_company.prod_comp_id;

Example of a Simple Join with pattern matching

Task
Find the film name, and the roles in those films, for all films starting with letters S through Z - using a simple join.

Query
SELECT film.film_name, role.character_name FROM film, role WHERE film.film_name = role.film_name AND film.film_name >= 'S%';

Complex Joins
Consider the situation where two tables are to be joined, but the second table does not always contain a row for every row in the first table. By default, SQL only returns rows where data exists in both tables (this is a standard, 'Equi Join') To get all rows from the first table, regardless of the existence of any corresponding rows in the second table, it is necessary to perform an 'Outer Join'

Syntax
Syntax is to place a bracketed plus sign (+) after the column where nulls may exist.

Example of an Outer Join


If, for example, you want to find the film name, and the roles in those films, for all films starting with letters S through Z, (and the possibility exists that there are films without roles) then you need to use an outer join.

Example
SELECT film.film_name, role.character_name FROM film, role WHERE film.film_name = role.film_name(+) AND film.film_name >= 'S%';

Correlation Names
A correlation name is simply an abbreviation for a table name used in an SQL statement. It can also be used whenever you need to refer to a table more than once in the same sub-select.

Example
SELECT p.company_name, p.country FROM film f, prod_company p WHERE f.film_name LIKE 'Cas%' AND f.prod_comp_id = p.prod_comp_id;

INSERT Statement
Inserts new rows of data into a table. There is a one-to-one correspondence between column and expression. Any unspecified columns will default to base table definitions.

Syntax
INSERT INTO tablename ([column {,column,}]) VALUES (expr {,expr})

Example
INSERT INTO film (film_name, prod_comp_id, release_year, run_time_mins) VALUES ('Magnificent Seven', 'MA', 1960, 128);

UPDATE Statement
Syntax
UPDATE tablename SET columnname = expr {,columnname = expr} WHERE search_condition

Example
UPDATE film SET director = 'Sturges', star_rating = 4 WHERE film_name = 'Magnificent Seven';
Warning: If you do not include a WHERE clause you can update ALL rows in a table.

DELETE Statement
Syntax
DELETE FROM tablename [WHERE search_condition]

Example
DELETE FROM film WHERE film_name = 'Magnificent Seven';
Warning: If you do not include a WHERE clause you can delete ALL rows from a table.

COMMIT Statement
The COMMIT statement makes permanent any changes to a database in a transaction, and also releases most locks acquired during the transaction. If you do wish to undo any changes made by a transaction, use the ROLLBACK statement. We will talk in more depth about transactions in the chapter 'Working with SQL Databases'.

Exercise 8.1: SQL Basics


Objective
In this exercise, invoke the Database Explorer (or SQLTalk) and connect to the PRESIDNT database. Then write SQL statements to obtain answers to the following questions.

Template
None. In this exercise you will write your own SQL statements.

Tasks
Step 1: Invoke Database Explorer (or SQLTalk for Windows). Step 2: Connect to the PRESIDNT database. Step 3: What are the names of Presidents born in the state of Texas? Step 4: What are the names of those Presidents with more than four children. Step 5: What was the name and party of the President elected in 1972? Step 6: Congratulations! You have just been elected the next president of the United States. Insert your own personal details into the President table. Be sure to leave the death_age blank as it is needed for the next step. Step 7: Generate a list of all Presidents that are still alive, along with any wives that they have had. Try this as an equal-join (notice that you ought not to appear because you don't have an entry in the Pres_marriage table). Now try this as an outer join (then you should appear in the list). Step 8: Unfortunately, there has just been a recount. You have lost the election to Arnold Schwarzenegger, who is now demanding that you delete your name from the President table. Please do this now. Step 9: Don't forget to COMMIT your changes. Step 10.Exit

Chapter 9: Working with SQL Databases


What We Will Cover
. . . . . . . . . . . . . . . . . . . Connecting to a Database Demo 11.1: Connecting to a Database Sql Handles OLE DB Constructs/Session Handles MTS Support Constructs Demo 11.2: MTS & Connecting thru OLEDB Disconnecting from a Database BIND Variables - Data Output INTO Variables - Data Input INSERT, UPDATE, DELETE SQL Command Cycle SqlPrepare SQLBase Stored Commands SqlExecute SqlPrepareAndExecute Fetching Data Using SqlPrepare Using SqlStore and SqlRetrieve (SQLBase) What is a Transaction?

Connecting to a Database
In the Client/Server environment, a database is uniquely identified by its database name. Knowledge of the operating system and network interface is not needed by a programmer or end-user. An application simply connects to a database with a username and a password.

SqlConnect (hSql)
The following system variables are used when SqlConnect is called SqlDatabase - Identifies the database, independent of DBMS or platform Default is ISLAND SqlUser - Identifies the user Default is SYSADM SqlPassword - Specifies the password Default is SYSADM Variables can be changed during application execution in your application, you may want to connect to a different database or with different user names. In this case, simply change the relevant system variable before issuing a SqlConnect() call and the appropriate connection will be established.

Demo 11.1: Connecting to a Database

Sql Handles
An application is connected to a database via a Sql Handle. A Sql Handle is similar in concept to a file handle or a pipe in that it establishes the connection to a data source. Similar concepts are a cursor, a pipe, and a file handle. Sql Handles may be initialized either explicitly (via SqlConnect) or implicitly (via SqlImmediate()). A Sql Handle can accommodate only one SQL statement at a time. Anytime you expect to execute the same SQL statement repeatedly, use different Sql Handles for other SQL statements. Generally, it is wise to use a different Sql Handle for each of the following operations: Populating a table window Routine inserts updates and deletes Ad hoc updates and deletes in the course of error processing

OLE DB Constructs/Session Handles


Session Handles are a feature of the OLE DB consumer interface. However, they can be used independently of it. They allow you to associate a SqlHandle to a SqlSession. This permits you to have many separate transactions from a single application to a single database.

Create a Session
SqlCreateSession ( hSessionHandle, sSessionProperties )
If you are not connecting to the database through OLE DB, the second parameter must be Null.

Set sSessionProperties = ''


Before calling SqlCreateSession, set the database name, user name, and password: as usual.

Create a Sql Handle for the session


SqlCreateStatement( Session_Handle, Sql_Handle )
This allows you to associate a Session Handle with a SQL Handle in order to process SQL Commands. There is no limit to the number of statements within a session

Retrieve a Session Handle


SqlGetSessionHandle ( Sql_Handle, hSessionHandle )
This call returns the session handle to which the specified statement handle belongs.

Commit a Session
SqlCommitSession ( hSessionHandle )
The SQL operations currently active on all the statements belonging to this session get committed.

Free a Session
SqlFreeSession ( hSessionHandle )
If there are any open statements belonging to this session, they are closed before the session is freed.

Disconnecting from a Database


Disconnect all connected Sql Handles before exiting from an application

Message
On SAM_AppExit

Function
bOk = SqlDisconnect( hSql )

Example

BIND Variables - Data Output


Data is bound before being passed to the database. Prefix the variable or field with a colon (:) A maximum of 255 Binds is allowed in a SQL statement

Example

INTO Variables - Data Input


Receives data passed from the database on a fetch

Prefix the variable or field with a colon (:) A maximum of 255 INTOs variables are allowed in a SQL statement

Example

INSERT, UPDATE, DELETE

SQL Command Cycle


Performing a SELECT (or other SQL command) involves the following Sql* function calls Having the DBMS compile the command SqlPrepare() or... Retrieving the stored command in SQLBase SqlRetrieve() then... Having the DBMS execute the command SqlExecute()

If a SELECT, fetching one row from the result set using

SqlFetchNext() SqlFetchPrevious() SqlFetchRow()

SqlPrepare
SQLWindows parses out the INTO clause of a SELECT statement and sets up the INTO and BIND variables. The DBMS clears the cursor workspace and input and output buffers. The statement is parsed, privileges, tables and columns are checked. The execution plan is generated. Buffers are allocated. Statement is compiled and stored in cursor workspace.

note

Declaration
bOk = SqlPrepare( hSql, sCommand )

Any illegal BIND or INTO variable is caught here by SQLWindows as a run-time error. However, SQLWindows doesn't search for existence of the variables at this point; that happens in the next step.
note

SQLBase Stored Commands


note

SQLBase allows storage of a SQL command directly into the database Command is compiled/prepared and stored Stored Commands can later be retrieved for execution Using stored commands is generally faster than calling SqlPrepare() to prepare the command

Declarations
bOk = SqlStore( hSql, sCmdName, sCommand ) bOk = SqlRetrieve( hSql, sCmdName, sBindList, sIntoList ) bOk = SqlDropStoredCmd( hSql, sCmdName )
note

This is a SQLBase feature

SqlExecute
SQLWindows locates the BIND and INTO variables, and sends off any BIND data.

Database executes prepared/retrieved SQL statement, after binding any data. For a Query, a result set is generated. For SQLBase, result set is kept as a list of ROWIDs on the server. For foreign backend's, if result set mode is ON the result set is maintained by the client-side router; called Front-End Result Sets (FERS). Result set mode is OFF by default. In SQLWindows it is changed by SqlResultSet ( ).

Declaration
bOk = SqlExecute( hSql )

SqlPrepareAndExecute
Combination of SqlPrepare() and SqlExecute() Prepares, binds and executes a SQL statement If no bind variables, uses one API call rather than two If already prepared will only execute the statement

Declaration
bRtn = SqlPrepareAndExecute( hSql, sCommand )

Fetching Data
A prepared/executed SQL SELECT command is required A SqlFetch* ( ) retrieves a row of data from the result set, and populates INTO variables with database table column values from the current result set row. For all the SqlFetch* ( ..., nIndicator ) functions: Function returns TRUE if there was a row to fetch, and nIndicator = FETCH_Ok Function returns FALSE if it could not fetch a row, and nIndicator = one of the following: FETCH_EOF FETCH_Update FETCH_Delete

SqlFetchNext()
Moves Sql Handle to the next row in the Result Set.

SqlFetchPrevious()
Moves Sql Handle to the previous row in the Result Set. A FETCH_* constant is returned in the Receive Number parameter nIndicator

Declarations
bOk = SqlFetchNext( hSql, nIndicator ) bOk = SqlFetchPrevious( hSql, nIndicator)

Using SqlPrepare
The Actions for a function - DoSelect

Using SqlStore and SqlRetrieve (SQLBase)


The Actions for a function - DoSelect

What is a Transaction?
Most DBMSs have the notion of a transaction. A transaction is defined as a logical series of operations, which belong together. At the end of the process, all changes made to the database are either committed or rolled back. A transaction consists of all Sql Handles to a given database and for a given user. If you are using Session Handles, a transaction consists of all SqlHandles to a given Session Handle. The rest of this discussion does not apply directly to Sessions.

Transaction begins when the first SqlConnect() is issued (implicitly or explicitly) either at beginning of execution or after a previous COMMIT/ROLLBACK. Transaction ends when a COMMIT or ROLLBACK is issued

COMMIT
Make permanent any changes. Transactions begin when an application instance connects the first Sql Handle and end (and begin again) when a program/user COMMITs or ROLLBACKs the work done within the transaction by use of either SqlCommit() or SqlImmediate(). Transactions will be implicitly committed when you disconnect the last Sql Handle from a database. Be careful; this may not always be what you intend. Note You need to understand the transaction behavior of the server that you are working with.

ROLLBACK
Discard any changes (be aware, ROLLBACK is generally a costly process no matter what the RDBMS)

Functions
SqlImmediate( 'COMMIT' ) SqlCommit( hSql ) SqlImmediate( 'ROLLBACK' ) SqlPrepareAndExecute( hSql, 'ROLLBACK' )

Locks
During the course of a transaction, the database engine may need to acquire locks on data, which may affect other users' access to data. A detailed discussion of transaction design is beyond the scope of this course. However, it is important that you realize the need to COMMIT changes. In general, write locks are held for the duration of a transaction, whereas the duration of read locks depends upon the DBMS being used (and the isolation level).

Exercise 9.1: Working with SQL Databases


Objective
In this exercise, you'll create and test an application that accesses a database. The form should look similar to the one pictured below. The Next and Previous push buttons should be disabled when those options are not valid. The File menu option is a pop-up menu and will allow the user to exit the application. The Select_All! menu item will execute the appropriate SQL statements to create a data set and load the first row into the data fields. You will have to write the SQL to retrieve the data and to step forward and backwards through the rows.

Preview

In this exercise we are concentrating on the SQL query cycle. However, in a real world situation, one might make this application more message driven as you learned in a previous chapter. If you have completed this exercise early, you might start implementing messaging as an additional exercise.

Templates
None. This exercise requires you to start a NEW application.

Tasks
Step 1: Step 2: Step 3: Step 4: Save any previous work. Start a new application. Save it as Chapter 11 Exercise 1.app. Define two Global Variables to manage a database connection. The first is a Sql Handle, g_hSqlSelect, and the second is a Boolean variable, g_bConnected, to track your success or failure in getting a connection Create a Form Window (see Preview) with data fields and their associated background text for the following: Name, Death Age, Birth date, Party, Yrs Served and State Born. Check and make sure you have specified the correct data types for each data field in the Attribute Inspector. Step 5: Step 6: Create two push buttons on the form: one to allow the user to see the next record, the second to see the previous record. These should initially be disabled (SalDisableWindow()) Create a numeric Window Variable nInd to track where we are in the data set. We use this as a return variable in our SQL statements. Its pool of possible values are: Error! No se encuentran elementos de tabla de ilustraciones.

Constant FETCH_Ok FETCH_EOF FETCH_Update FETCH_Delete Step 7: Step 8: Step 9: Step 10:

Value 0 1 2 3

Meaning OK End Of File (EOF) Rows were updated since last fetch unsuccessful fetch Row was deleted unsuccessful fetch

In Application Actions (when the application starts), connect to the PRESIDNT database. You will connect the global Sql Handle to this database. If the connect is successful, set our Boolean variable g_bConnected to TRUE. In Application Actions (when the application ends), if the Sql Handle was successfully connected, it should be disconnected at this time. It will be necessary to create one pop-up menu with an option to exit the application and one menu item to populate the data set and retrieve the first row of data. Write the code required for the Select_All! menu option. The code should prepare and execute a SQL Statement that selects all presidents from the database. Fetch the first row and, if this is successful, enable the Next push button (SalEnableWindow()).

Step 11:

Write the code required for the pbNext push button. It should fetch the next record. If the fetch reaches the end of the set, inform the user and disable this button. Always enable the Previous push button.

Step 12: Write the code required for the pbPrevious push button. Fetch the previous record. If the fetch reaches the start of the set, inform the user and disable this button. Always enable the Next push button. Step 13: Save and Test your application.

Chapter 10: SQLError Handling and Infrastructure

What We Will Cover


. . . . . . . . . Demo 12-1: Login Dialog Box Functions for Forms and Dialog Boxes Types of Dialog Boxes - Review Library Files SQL Error Handling When SqlError Demo 12.2: Handling SQL Errors Global Error Handler Default Error Handling

Demo 12-1: Login Dialog Box


In this demonstration we will build a dialog box for connecting to a database. During the demonstration, we will utilize the global variables, dialog boxes, formatted data fields and more. Replace 'hard coded' database connection information with a Dialog Box user interface We will place the functionality we create into a separate file - an Application Library - so that it can be used in many different programs. We will demonstrate Use of dialog box for getting small amounts of information Use of formatted data fields Use receive Window Parameters Program controlled window creation

Login Dialog Box

Dialog Box definition

Dialog Box Actions

Functions for Forms and Dialog Boxes


SalCreateWindow
SalCreateWindow( ) is used to create a form (window) dynamically at runtime through programmatic control, rather than at start-up. All the forms used so far have had the property Automatically Create set to Yes. This means that when the program starts, the form is automatically created and shown to the user. If you want to wait to show a form until the user requests it, then set Automatically Create to No, and make a call to the function SalCreateWindow( ) at the point in the program where you want the form displayed. This function can also be used to create second and third copies of the same form (if desired). SalCreateWindow can be used with Form Windows, MDI Windows and Modeless Dialog Boxes. Optionally passes data to/from window

Syntax
hWndCreated = SalCreateWindow(tWndToCreate,hWndOwner{,Param})
tWndToCreate is the name of the window to create

SalDestroyWindow
Use the function SalDestroyWindow( ) to close a form window programmatically.

Syntax
SalDestroyWindow(hWndCreated)

SalModalDialog
SalModalDialog( ) is used to show a modal dialog box. A modal dialog box is a type of form that suspends the application (or entire system) until the user closes the dialog box. This means that any code that appears after the call to SalModalDialog does not execute until the user closes the dialog. If an input value is required from the user in order to continue processing, SalModalDialog should be used. SalModalDialog can be used with Modal Dialog Boxes and System Modal Dialog Boxes. Optionally passes data to/from window

Syntax
hWndModal = SalModalDialog(tDlgBoxToCreate,hWndOwner{,Param})
tDlgBoxToCreate - the name of the dialog box to use

SalEndDialog
Destroys a modal dialog box and returns control to the caller

Syntax
SalEndDialog(hWndModal,nReturn)

SalWaitCursor
Displays or removes the hourglass cursor

Syntax
SalWaitCursor( bOn )
TRUE turns on hourglass FALSE turns off hourglass

Variables
tWndToCreate and tDlgBoxToCreate
Where you place the name of the template from which to create the form window or dialog box. The object name of a top-level window object is also known as the template name (i.e. frm1, or dlgLogin).

hWndOwner
The window handle of the form or dialog that will own the object you create. Usually, this will be the object from which you call the function SalCreateWindow or SalModalDialog. The form or dialog you create will always stay on top of its owner, even if the focus is put back on the owner. A call to SalParentWindow( ) from within the form or dialog you created will return the window handle of its owner. If you close the owner, the form or dialog you created will automatically be closed as well. If you don't want the form or dialog to be owned by any other window, specify the constant hWndNULL for hWndOwner.

Types of Dialog Boxes Review


Set at design time in the Type of Dialog property in the Attribute Inspector . When designing a dialog box, it is necessary to decide what type of dialog it should be. The type of dialog you choose has many implications for how you write your program, and what happens when the dialog is displayed.

Modal Dialog
A modal dialog box must be created with a call to SalModalDialog( ). This type of dialog box suspends any execution (after the call to SalModalDialog) until the user closes the dialog box. The user cannot put the focus on any other form or dialog within the current application. They can still switch to another application in the system if they wish, but when they return to your application, the focus will still be on the dialog box. This type of dialog is typically used when user input is required before processing continues.

System Modal Dialog


A system modal dialog box must also be created with SalModalDialog( ). This type of dialog also suspends execution until the user closes the dialog. However, unlike a modal dialog, the user cannot switch to any other program in the Windows Operating System. They must finish with the dialog box before anything else can happen. This types of dialog is typically used to report critical system errors, like memory problems or file sharing violations.

Modeless
A modeless dialog box must be created with SalCreateWindow( ). It behaves in much the same way as a form window except it cannot have a menu. With this type of dialog box, code execution in the calling routine continues as soon as the form is created. This type of dialog might be used as a tool palette that floats on top of its owner at all times. The user could switch focus back and forth between the owner and the dialog as they wished.

Library Files
A library file is like any other SQLWindows program. It may be saved in either normal or text format. A library file is referenced in the Libraries Section. The included code appears in the parent application in a different color or font. The code cannot be edited in the referencing program. To change the code you must edit the Library itself. A quick way to achieve this is to highlight the line in question and right-click | Go to library item (or <F5>). A new copy of SQLWindows is started with the Library file opened within it. The same library file can be used by many programs.

Exercise 10.1: Login Dialog Box


Objective
In this exercise, you will create and test a simple dialog box to obtain the connection parameters and use them to log onto the database. You will save this application as a library (.APL) and then include it in your previous application.

Preview

Templates
Part 1: None Part 2: Use template Chapter 10 Template 1.app or if you completed Chapter 9 Exercise 1.app, you may use that.

Tasks
Step 1: Step 2: Step 3: Step 4: Save any previous work. PART 1: Start a new application. Save it as Chapter 10 Exercise 1.apl. Create a Dialog Box dlgLogin. Add a Receive Window Parameter, hSqlParam, which will be passed in when the dialog is created and will return the connected Sql Handle to the calling routine. Step 5: Step 6: Step 7: Add data fields for: Database, UserID, & Password Initialize the Database to 'PRESIDNT' and UserID and Password fields to 'PRESIDNT' when they are created. Add a Cancel push button - pbCancel. This button will be used to quit the application if the user does not want to login, or cannot login for some reason. Set the keyboard accelerator to the <Esc> key. When the user clicks pbCancel, create code that closes the dialog box and returns FALSE (SalEndDialog). Step 8: Create two variables local to the dialog box: bConnect & hSqlLocal.

Step 9:

Add a Connect push button, pbConnect. This button will be used to connect to the database. Set the keyboard accelerator to be the <Enter> key. When the user clicks pbConnect, create code to display the Hourglass, set the SQL database parameters and then connect the handle, hSqlLocal, to the database. If the connect succeeds, set the window parameter hSqlParam equal to hSqlLocal, close the dialog and return TRUE

Step 10: Step 11: Step 12:

Save the Library file. Part 2: Open the template or your previous completed exercise. Save it as Chapter 10 Exercise 1.app. Add a line in the Libraries section to include Chapter 10 Exercise 01.apl. Notice that the code for dlgLogin now appears in this program, but in a different font or color. Also notice that you cannot edit the code here. If you need to edit the code, you can highlight the code and right-click then select Go to library item. Modify the SAM_AppStartup code to use your Dialog Box (SalModalDialog). Pass it the global Sql Handle g_hSqlSelect . The dialog box replaces the hard-coded database, user name and password assignments, as well as the call to SqlConnect that we coded earlier. If the call returns FALSE, quit the APP like we did if SqlConnect returned FALSE. If the return is TRUE, create frmMain (SalCreateWindow). Change the 'Automatically Create' property of frmMain to be NO. Previously, frmMain was automatically created by SQL Windows when the program started. Now, with this code, we control the creation of it from within the program. Save and test your application. Try entering an invalid parameter to see the behavior of the default error handler.

Step 13:

Step 14:

Step 15:

SQL Error Handling


Nearly all Sql*() functions return TRUE or FALSE, indicating success or failure. The errors can be trapped by error handlers at two levels: at the local level and at the global level. If neither is trapped, then SQLWindows default error handling will be invoked.

Error Handler Return


If return is specified in any of the error handlers, then the Boolean that is returned replaces the return for the Sql* function which generated the error. If return TRUE then that implies that the Sql* function succeeded. If return FALSE, then the Sql* function fails. If Return is not executed then will continue to the next error handler or the default error handler.

Flow of Error Messages


Error messages can be processed by the following error handlers

When SQLError
A local error handler, for any specific error handling; special-case certain local errors.

On SAM_SqlError
A global error handler, for more general error handling; special-case general errors.

wParam and lParam


When an error handler is invoked wParam and lParam contain additional information about the error condition.

wParam
Sql Handle, which generated error

lParam

Contains the error position in the SQL statement and the error number.

Sql*( ) error routines


In order to obtain useful information about an error event a number of error functions are provided. SqlExtractArgs() SQLError() SqlGetErrorText() SqlGetErrorPosition() SqlGetErrorTextX() SqlGetRollbackFlag() SqlErrorText() SqlGetModifiedRows()

When SqlError
A local error handler. Must be located above and at the same indent level as the Sql* ( ) statement(s) you are trapping.

Question
Why will the code on the bottom NOT work if there is an error in execution of the SqlPrepare call?

Demo 12.2: Handling SQL Errors Locally


Return from the message action (TRUE/FALSE) becomes the return for the Sql*( ) function which generated the error.

Global Error Handler


SQLWindows informs the application of any SQL error with the SAM _SqlError message. The SAM_SqlError message is sent to the Application Actions section only. Good for any user-written, general error processing.

Example of Global Error Handler

Default Error Handling


Invoked if no appropriate error handlers were defined or if they were defined but did not execute a Return statement.

SQL Error Dialog Box

Continue push button


Returns FALSE from Sql* ( ) function which caused the error

Halt push button


Causes the application to terminate. Equivalent to a call to SalQuit(). SAM_AppExit message sent to application actions.

Copy push button


Copies all of the selected text in the SQL statement to the clipboard.

Exercise 10.2: Handling Known Connection SQL Errors


Objective
Add a local SQL error handler to your login dialog library. It will be coded for some specific SQL errors. The standard errors that we will trap for are invalid database name, user name and password. Also add a global error handler to the application to capture all other errors and spare the user from the default SQL Error Dialog, unless they want to see it.

Preview

Template
Use template Chapter 10 Template 2.app and Chapter 10 Template 2.apl or if you completed Chapter 10 Exercise 1.apl and Chapter 10 Exercise 1.app, you may use that.

Tasks
Step 1: Step 2: Step 3: Save any previous work. Open the library file; the template ( .apl) or your previous completed exercise (.apl). Save it as Chapter 10 Exercise 2.app. Now open the applications file: the template (.app) or your previous completed exercise (.app). Save it as Chapter 10 Exercise 2.app. Step 4: Step 5: Step 6: Change the Libraries section to reference Chapter 10 Exercise 2.apl. Save this change. Open the library file Chapter 10 Exercise 2.apl again. Define global constants for the errors: SQL_Err_NoDatabase = 401 SQL_Err_InvalidPassword = 404 SQL_Err_InvalidUserName = 405 Step 7: Define Dialog Box Window Variables: Sql Handle: hSqlError Number: nSqlError Number: nSqlErrorPosition Step 8: Modify the click action for pbConnect, to include local error handler code (When SqlError). Ensure this code appears before the call to SqlConnect and at the same level of indentation. The code in the error handler should extract the error parameters, test them against the constants above and display appropriate messages. If the error is one of these three, return FALSE. If not, do nothing (so that the error falls through to default error processing). Step 9: Step 10: Step 11: Save the library and return to your application. Re-run your application to test your new error handler. Return to the library and remove the maximum character length constraint in the properties of the Database data field. Save the library and return to your application. Test that default error processing occurs if you enter a nine-character database name. Step 12: Add your own global error handler to your application. Capture the message SAM_SqlError and display a message saying 'An unknown database error occurred. Quit the application?'. Offer the user the opportunity to click Yes or No. If the user clicks Yes, quit the application. If the user clicks No, let the program fall through to default error processing.

Step 13:

Save the program and test. Try entering a nine-character database name to test the behavior of your global error handler.

Chapter 11: Getting Started with Table Windows


What We Will Cover
. . . . . . . . . . . . . What is a Table Window? Table Window Terminology Focus Row vs. Context Row Table Window Cache Result Set/Table Window Cache Populating a Table Window Dynamic vs. Defined Columns Table Window SAM* Messages Other SAM* Messages Demo 13.1: A Table Window for Browsing Data Demo 13.2: Selecting Data Populating Combo Boxes Demo 13.3: Loading Lookup Data from the Database

What is a Table Window?


A Table Window is a two dimensional, row and column representation of data. Table Windows, with the use of the scroll bars, allows the user to scroll forwards and backwards through the data set. A large number of columns can be viewed through horizontal scrolling. The rows in the Table Window can be marked as new, edited or deleted and then the application can perform batch Database Manipulation Language (DML), thus reducing locking contentions. Visual indicators identify marked rows

Data Driven
Data can come from any source(s) SQL databases Flat files Other external sources (Internet, TP Monitors, SAP, and so on) Several features simplify working with SQL databases. Can perform bulk DML (SQL UPDATE, INSERT or DELETE) based on marked rows SQLWindows supports automatic population from a SQL database via the function, SalTblPopulate. In addition, the programmer can manually populate a table from any other source. Table Windows maintain their own dynamic memory cache to locally buffer their data (this is covered in more detail later in this chapter).

Table Window Terminology


Column Row
A Row is a horizontal data set
note1

A Column is a vertical content item and is the only child object allowed in a Table Window.

Cell
A Cell is the intersection of a row with a column

Focus Frame
The Focus Frame is the bold outline (top and bottom), which identifies the focus row, or the row, which contains the focus cell

Focus Row
That row most recently selected by the user (can also be set programmatically). Bounded by the focus frame, it is the row, which will receive user input or affected by user actions

Focus Cell

note2

The Focus Cell is the cell, which has the input focus (with the blinking I-beam cursor)

Selected Row
The Selected Row is the row shown in reverse video. A row can be selected by a user by: Clicking on the row using the right mouse button Clicking on the row header Clicking on a non-editable column in the row To select multiple rows use: Click and drag Shift + Click (multiple contiguous rows) Ctrl + Click (multiple non-contiguous rows) Keyboard interface: Shift + up/down arrow keys To select programmatically, use SalTblSetFocusRow( ).

Visible Range
Visible Range is the number of rows, which can be visible at the same time in the Table Window

Row Header
The gray non-editable column at the far left-hand side of the Table Window (the row header may be hidden)

Column Header
The Column Header is the gray non-editable title at the top of every column.

note1 note2

A blinking I-beam in a cell identifies it as the focus cell (not shown on this diagram.) A top-level Table Window can have a Toolbar, Status Bar and Menu Items.

Focus Row vs. Context Row


Context Row
The row, which can be programmatically accessed or manipulated. Values are assigned or obtained by referencing a column in your program. When the user changes the Focus Row, the Context Row is synchronized to the same row. The Context Row may be different than the Focus Row, if it is changed programmatically (for example, via SalTblSetContext ( ), or another context modifying function). For most Table Window related SAM_* messages, lParam is the context row.

Table Window Cache


Cache is dynamically allocated and maintained client-side memory buffer of row(s) fetched from the data source. Grows to a given size, specified by the Max Rows in Memory property. Edited rows are never automatically discarded from the cache. Only programmatic function calls affect edited rows. A Table Window may discard a row if cache is at maximum size and another row needs to be fetched (and discarding is enabled)

Table Window cache properties Discardable


Possible Values: Yes or No Default: Yes

Max Rows in Memory


Possible Values: 78 to 4,294,967,295

Default: 100

Practical limit of the Table Window range determined by


Row size Available system resources

Result Set/Table Window Cache

Populating a Table Window


SalTblPopulate(hWndTbl, hSql, strSelect, nFillMethod)
Compiles, binds and executes a SQL SELECT statement, then fetches the rows of the result set and populates the Table Window. If the SQL Statement is NULL (an empty string) then the most recently prepared statement for hSql is used.

nFillMethod
TBL_FillNormal
Populates visible range, displays Table Window, then dynamically fetches additional rows as the Table Window is scrolled

TBL_FillAllBackground
Populates visible range, displays Table Window, then populates rest in background. Currently, the background population is equivalent to 4 rows per second. When all rows have been populated, a SAM_FetchDone message is sent to the Table Window.

TBL_FillAll
Populates entire range before displaying Table Window If TBL_FillNormal or TBL_FillAllBackground is employed, the Sql Handle used must be dedicated to the Table Window. The recommended starting point is TBL_FillNormal. If you know that the result sets will be small, you may want to use TBL_FillAll. TBL_FillAllBackground is suitable for some applications. If a Table Window is being populated from a database with other than TBL_FillAll, the programmer must ensure a valid Sql Handle will be maintained for the duration of the Table Window's existence. For example, with TBL_FillNormal, user scrolling will cause the SQLWindows Table Window Engine to fetch additional rows. The engine will expect to use the same Sql Handle, and presumes that it retains the same result set and column binding.

Dynamic vs. Defined Columns


You may call SalTblPopulate for a table that has no pre-defined columns. The Table Window will create the required columns in the Table Window, based on the columns in your SQL SELECT statement. Do not specify an INTO clause in your SQL SELECT statement if no columns are defined and you want columns automatically created. Table Window columns are the only SQLWindows child objects, which can be created and destroyed dynamically at run time. With pre-defined columns it is much easier to set properties such as title, width, justification, format, etc. Dynamically created columns are always string data type.

Table Window SAM* Messages


SAM_FetchRow
Sent to a Table Window whenever a row needs to be displayed and the row is not already in the cache. lParam has the requested row number, return FALSE to halt the message and indicate population is complete.

SAM_FetchRowDone
Requested row has been populated into table, lParam has the fetched row number. Use this message to execute code after a row has been fetched. For example, calculating a derived value.

SAM_CacheFull
Cache cannot grow and no row can be discarded

SAM_CountRows
Table Window needs to get range.

SAM_FetchDone
Completed background SQL fetch for Table Windows populated with TBL_FillAllBackground.

SAM_RowValidate
Allows for row level validation. Sent when you set the focus to a different row (or a cell in a different row) and changes were made to the previous row.

Other SAM* Messages


Table Window and column messages (sent to both)

SAM_Click
In a non-editable column only

SAM_DoubleClick
In a non-editable column only

SAM_AnyEdit SAM_Validate SAM_Kill/SetFocus


lParam contains the row number hWndForm = Table Window hWndItem = Column

Demo 13.1: A Table Window for Browsing Data

We will demonstrate the execution of the application. We will show how the features were developed: Create a new Form Window-based application. Add a Table Window. Define Table Window columns. Include the Login dialog box library. Connect to a database. Populate the Table Window from the database.

Connecting to the database


In this demo we connect to the database On SAM_Create of the frmFilm Window.

Previously we connected to the database during AppStartup. The decision on where to place the database connection is purely a design decision.

Populating the Table Window

Exercise 11.1: Getting Started with Table Windows


Objective
Functionally, this application is similar to the application you built to scroll through presidents in a previous chapter. This time, however, the presidents will be displayed in a Table Window as opposed to individually in data fields.

Preview

Templates
None. This exercise requires you start a NEW application. It requires the library file Chapter 11 Exercise 2.apl.

Tasks
Step 1: Step 2: Save any previous work. Create a new application. Save it as Chapter 11 Exercise 1.app. Step 3: Create a parent Form Window.

Step 4: Step 5: Step 6:

Add a Child Table Window and an "Exit" push button to the form. Create columns for the president's name, state born, birth date, party, spouse, spouse's age and number of children. Add the library file for the Login dialog box you created in the previous chapter to the application. You should have saved it as Chapter 10 Exercise 2.apl

Step 7: Step 8:

In the Form Window's variable section, add a Sql Handle variable. Add Message Actions to the Form Window to: connect the Sql Handle, using the Login dialog box, in the SAM_Create message handler; disconnect the handle in the SAM_Destroy message handler.

Step 9:

In the functions section of the Child Table Window, add a Populate function which when called, will use SalTblPopulate to fill

the Table Window with columns from the president and spouse tables, joined by pres_name. Step 10: Step 11: Call your Populate function from an On SAM_CreateComplete action on the Child Table Window. Save the program and test.

Demo 13.2: Selecting Data


Creating a Combo Box
Title: cmbCountry Use List Initialization to add some Countries Constraining the SalTblPopulate() Country column = cmbCountry We add a Push Button to do the query Title: &Query Name: pbQuery Action: Posts a PAM_Populate message to the form, which in turn sends the message to its children, including the Table Window

Initializing a Combo Box

Defining a Message

Constraining our Table Population The Query Push Button

The Query Push Button

Broadcasting the PM_Populate Message

Exercise 11.2: Selecting Data with a Combo Box


Objective
In this exercise, we enhance our President Browser to show just those presidents born in a specific state where the state is specified in a Combo Box.

Preview

Templates
Use template Chapter 11 Template 2.app or if you completed Chapter 11 Exercise 1.app, you may use that.

Tasks
Step 1: Save any previous work.

Step 2: Open the template or your previous completed exercise. Save it as Chapter 11 Exercise 2.app.

Step 3: Add a combo box for the state column. Set list initialization to three or four states (you should include Virginia, since we know it

has several presidents).

Step 4: Add a PAM_Populate user message.

Step 5: In the Child Table Window, change the On SAM_CreateComplete action that called the table's Populate function to On

PAM_Populate.

Step 6: In the Child Table Window's Populate function, include a reference to the Combo Box in the where clause of the

SalTblPopulate() function. Step 7: Add a "Query" pushbutton. Include a SAM_Click action to post a PAM_Populate message to the form. Step 8: Add an On PAM_Populate message handler to the form, which sends a PAM_Populate to the form's children. Step 9: Save the program and test.

Populating Combo Boxes


The previous demo and exercise used hard coded lists. It should come as no surprise that in almost all situations, hard-coding of reference data should be avoided and that a data-driven approach is much more maintainable. In the next demo we will initialize a combo box by obtaining the data from a reference table in our database In order to do this we will need.

SAM_DropDown
Received by combo boxes when the user clicks on the drop down icon.

SalListPopulate( )
A SAL function, which populates list boxes and combo boxes.

SalListQueryCount()
Returns the number of items currently in a combo box or list box.

Demo 13.3: Loading Lookup Data from the Database


We are now going to replace the List Initialization code with code to retrieve the countries information from the database. We can make use of our Form Window SQL handle and two new functions, SalListPopulate() and SalListQueryCount(). First, we remove the List Initialization Text items, then we add the code below. Note that we could have simply called SalListPopulate() in an On SAM_Create action for the Combo Box. The approach shown is slightly better in that the database is only hit with the SELECT to populate the Combo Box when the user clicks down on it for the first time. If the user simply runs the application and then closes it, the query is not needlessly performed. If we had a complex data entry form with many Combo Boxes, this approach can significantly speed up the initial create of the form. We can see from our enhanced application that we now have all the available countries represented. Also, our application is now completely data driven, which means as new countries are added, we simply have to add them to the 'Countries' table. However, a word of warning: Some programmers are given to using the SQL structure 'SELECT DISTINCT... ' to build reference lists from large tables which are not fully normalized. This can have crippling effects on on-line performance since the DISTINCT operation requires that the table be sorted. To build elegant applications with pick-lists and Combo Box lookups and the rest, one must first design the data- base correctly.

Exercise 11.3: Populating a Combo Box


Objective
In this exercise, you will enhance your Presidents browser so that the Combo Box data is selected from the database.

Preview

Templates
Use template Chapter 11 Template 3.app or if you completed Chapter 11 Exercise 2.app, you may use that.

Tasks
Step 1: Step 2: Save any previous work. Open the template or your previous completed exercise. Save it as Chapter 13 Exercise 3.app. Step 3: Step 4: Step 5: Remove the list initialization items from the Combo Box. Add an On SAM_DropDown Message Action to populate the Combo Box if the list count is 0. Save the program and test.

Chapter 12: SQLWindows and Reports


What We Will Cover
. . . . . . . . . . . . . . . . . . Classic Report Interface Report Builder Functions Creating Reports from Table Windows Demo 16.1: Creating & Viewing Report Data Report Builder Messages Function Details Demo 16.2: Using Report View More Function & Message Details Demo 16.3: A Simple Classic Interface Report Exercise 12.1: SQLWindows and Reports Report Builder Errors Query/Report Report Objects Demo 16.4: Creating a Crosstab Report Demo 16.5: Printing Images Integrating Report Builder with ActiveX Demo 16.6: Report Builder Automation Exercise 12.2: Creating an RB Automation App

Classic Report Interface


Design time
At design time, Report Builder is used to create a template (QRP) file. The template defines input items by name and data type, and describes visually the format and layout of data on the report pages. The template can be generate from a Table Window

Run time
At run time, SQLWindows invokes Report Builder to display or print the report via a call to SalReportView or SalReportPrint. The SalReportView/Print call identifies the template file, and provides a mapping between the template's input items, and bind variables in the SQLWindows program. Report Builder sends SAM_Report* messages to the invoking program, keeping it up to date on report progress. In particular, Report Builder sends a SAM_ReportFetchNext message whenever it needs a row of detail line data for the report. The invoking program loads the requested data into the specified bind variables, and does a Return TRUE from the message action. When no more data remains, the invoking program does a Return FALSE, terminating the report. In this architecture, the SQLWindows program acts as a data server for Report Builder. Data may come from any source, but typically a SQL database server provides the data.

SQL Database

SQLWindows

Report Builder

Application

Report Builder Functions


Table Windows Report Functions
Access to Report Builder directly using a Table Window as the data source. SalReportTableCreate() create a new default report template SalReportTableView() view an existing report SalReportTablePrint() print a report

Major Report Functions


Access to Report Builder directly using other data sources, such as a database. SalReportCreate() create a new default report template SalReportView() view an existing report SalReportPrint() print a report SalReportPrintToFile() print a report to a file

Miscellaneous Report Functions


Additional functions that allow you to manipulate the way the report is processed. SalReportFileInfo() get the file information a report template SalReportGetPrinterSettings() gets the printer properties at runtime. SalReportGetPrinterTray() returns the printer tray that is currently specified for a specific page in the report SalReportResetPages() causes the current page number and number of total pages to be reset when a change in break group value is encountered during a report at runtime. SalReportSetPrinterTray() Sets the printer tray at runtime.

Creating and Manipulating Reports


SalReportTable Functions
note

Create, View or Print a report using the data in a table window.

bOk = SalReportTableCreate(sReportName,hWndTbl,nReceiveError) hWndReport =SalReportTableView(hWndTbl,hWndDisplay,sReportName,nReceiveError) hWndReport = SalReportTablePrint(hWndTbl,sReportName,nParamArray,nReceiveError)

SalReportFileInfo Function
Get the file information a report template

Ok = SalReportFileInfo( sReportName, sFileInfo )

SalReportGetPrinter Functions
Get Printer name, paper orientation, paper type, paper size, and paper tray information at run time

bOk = SalReportGetPrinterSettings( WndReport, sPrinterName, nOrientation, nPaperType, nWidth, nHeight ) bOk = SalReportGetPrinterTray( hWndReport, nPage, strTray )

note

Data must be available in the table window

Demo 16.1: Creating & Viewing Report Data


Here we will look at how to create a report from a data-grid (child table) of information. We will also look at getting information about the report, like an optional report description or paper & tray information from the printer. Button Functions: . Report Info Gets the description information about the report . Paper Info Paper . Paper Tray print what . Print/View

Gets the information about the printer & Gets the information about which trays Used to print/view the report

SalReportTableView function call

SalReportGetFileInfo function call SalReportGetPrinterSettings function call

SalReportGetPrinterTray function call

Example of Table Window Output Report

Report Builder Messages


Report Builder sends a number of messages to the SQLWindows application. wParam = Report Builder handle. SAM_ReportStart SAM_ReportFetchInit SAM_ReportFetchNext SAM_ReportFinish SAM_ReportNotify

The SQL Query Cycle


If the report data is being provided by an SQL database, you may wish to follow this approach

On SAM_ReportStart
Do a SqlConnect() for each of the SQL handles your application will require. Return TRUE if it succeeds, Return FALSE if it fails. To stop the report, Return FALSE

On SAM_ReportFetchInit
SqlPrepareAndExecute() an appropriate SELECT statement. Return TRUE if it succeeds, Return FALSE if it fails.

On SAM_ReportFetchNext
SqlFetchNext(). Return TRUE if it succeeds, Return FALSE if it fails. Return TRUE from the message to continue, FALSE if end of data

On SAM_ReportFinish
SqlDisconnect() any Sql Handles you were using.

On SAM_ReportNotify
lParam = a RPT_Before* notify code

Function Details
SalReportCreate
Creates a new default report template (not based on Table Windows)

Declaration
bOk = SalReportCreate(sFilename,sVariables,sInputs,bDefaultReport,nReceiveError)

sVariables
String list of SQLWindows fields or variables, which will contain data for the report

Example
'nID, sName'

sInputs
String list of Report Builder input item field names in the report template

Example
'ID, NAME'

SalReportView
Preview a created report using Report Builder. Returns a window handle to Report Builder.

Declaration
HWndReport = SalReportView(hWndServer,hWndDisplay,sFilename, sVariables,sInputs,nReceiveError)

sVariables
String list of SQLWindows fields or variables, which will contain data for the report

sInputs
String list of Report Builder input item field names in the report template

nReceiveError
Set nReceiveError = RPT_NoPrint or RPT_NoToolbar

Demo 16.2: Using Report View


Activation

Output Report Example

More Function & Message Details


SalReportPrint
Prints a report from a previously created report file

Parameters
Variable List
String list of SQLWindows fields or variables, which contain data for the report

Inputs List
String list of Report Builder field names in the report

Options
RPT_PrintAll or RPT_PrintRange RPT_PrintDraft (flags can be OR'ed)

First/Last Page
(if RPT_PrintRange is used)

Declaration
hWndReport = SalReportPrint(hWndServer,Filename,sBinds,sIntos, nCopies,nOptions,nFirstPage,nLastPage,nReceiveError)

SAM_ReportNotify
The Report Builder sends SAM_ReportNotify messages as the report blocks are formatted and output into the page buffer. The lParam code sent in the SAM_ReportNotify message indicates which part of the Report Builder is ready to format.

lParam Codes
Report Header: Page Header: Break Header: Detail: Break Footer: Page Footer: Report Footer: RPT_<xxxx>ReportHeader RPT_<xxxx>PageHeader RPT_<xxxx>BreakHeader1 - 8 RPT_<xxxx>Detail RPT_<xxxx>BreakFooter1 - 8 RPT_<xxxx>PageFooter RPT_<xxxx>ReportFooter

<xxxx> is Before or Output or Done. (i.e. RPT_BeforeReportHeader) The Before notifications are sent before any formatting occurs, the Output notifications are sent when the first line of the report is output and the Done notifications are sent when the entire block is output. An application can keep track of the sequence of these notices to detect when a page break (page footer/header blocks) has been inserted into the flow of the report blocks.

Demo 16.3: A Simple Classic Interface Report

Launch Report Builder


Tools | Report Builder

Import a blank classic template


Edit | Import Template | newrep.qrp

Define input items


Right-click on Input Items in the left pane, then select New

Set a break group on COUNTRY


Right-click on Break Groups in the left pane, then select New

Define the report layuot


Create a simple form window with a single push button to call the reporting function.

Define suitable bind variables.

Finally, define message actions for the controlling window

Exercise 12.1: SQLWindows and Reports


Objective
In this exercise, you will create a simple classic interface report program of Presidents by State, and a matching QRP file.

Preview

Templates
None. This exercise requires you to start a NEW application.

Tasks
Step 1: Step 2: Save any previous work. Start a new application. Save it as Chapter 12 Exercise 1.app.

Step 3:

Launch Report Builder and import the blank classic template newrep.qrp. Save it as Chapter 12 Exercise 1.qrp

Step 4: Step 5: Step 6: Step 7: Step 8:

Define input items PRESNAME (string), BIRTH (date) and STATE (string) Set a break group on STATE Define the report layout, and re-save your template In your application, define a SAM_AppStartup message action to set SqlDatabase to 'Presidnt' Create a form window called frmSimpleReport, titled Simple Classic Report, add a push button called pbRunReport Add a SAM_Click Message action to pbRunReport, to call a function RunReport() At the form window level, declare these variables: Sql Handle: hSql String: sSelectPres Number: nFetchResult Number: nRptErr String: sPresName Date/Time: dBirthDate String: sStateBorn

Step 9: Step 10:

Step 11:

At the form window level, declare the function RunReport() . Add code to set the value of the sSelectPres to a suitable SELECT statement, and then call SalReportView() At the form window level, code message actions for SAM_ReportStart, SAM_ReportFetchInit, SAM_ReportFetchNext and SAM_ReportFinish Save and test your application.

Step 12:

Step 13:

Report Builder Errors


Possible error returns in nReportError

RPT_ErrBind
Incorrect bind information

RPT_ErrCount
Incorrect number of bind or into variables

RPT_ErrFilenameLength
File name too long

RPT_ErrFileOpen
Could not open specified report file

RPT_ErrInput
A mismatch between input and bind variables

RPT_ErrLoadDLL
Could not load needed DLL

RPT_ErrMaxRpts
The maximum number of reports was exceeded Maximum number of reports = 10

RPT_ErrPrtOpen
A report function was unable to open the printer

RPT_ErrRptOpen
A report function was unable to open the specified report for printing

RPT_ErrRptWindow
A report function was unable to open the Report Builder

RPT_ErrType
The data type of an input variable did not match the data type of the associated bind variable

Query/Report
At design time, Report Builder can be used to query data and create a file with both data selection & report template. This type of template can be saved as a CQT.

Define a Query
You can use the define query dialog box to select data from a database. It is a graphical process that allows you to select the source, conditions, sort clause, group by clause, and group by conditions. It will also allow you to display the SQL statement generated by your query along with the results of your selection.

Report Preview
After defining a query and selection the OK button, you are presented with an automatically generated report. This processing creates a generic heading along with headings for each column selected in the query. You can now use the Report Designer to change the layout/data to something more specific to your needs.

Report Objects
Reports have several Objects associated with them: Input Items, Input Variables, Formulas, Totals, Crosstabs, & Break Groups. In this section we will look at Break Groups, Totals, and Crosstabs.

Break Groups
The break group dialog box (Format Break Groups) allows you to define a break group for a report. A report template has the ability to display data in broken up into groups, up to 8 levels. When formatting a break group of have an option to reset pages when a break occurs in the data. For example: Printing a invoice with multiple pages on it, if printed one company at a time you would have pages starting from 1 to the max printed, this works fine. But if you printed a batch of company invoices the page numbers would normally start with the first invoice printed and end with that last company/page printed. So if the second company in the batch had more then one page on an invoice the starting page number could be starting at page 2. To solve this problem you can use the Reset Pages on the break group of company to reset the page number back to zero each time the company changed.

Totals
You can create total objects that can be used on reports by using the Totals dialog box (Format Totals). When creating a total you have several options, from what you are trying to total (input items, input variables, other formulas), to what kind of total are you trying to create (Average, Count, Maximum, Minimum, ), to whether you what to restart the total on an event, as well as whether the data needs to be preprocess.

Crosstabs
You can create total objects that can be used on reports by using the Totals dialog box (Format Totals). When creating a total you have several options, from what you are trying to total (input items, input variables, other formulas), to what kind of total are you trying to create (Average, Count, Maximum, Minimum, ), to whether you what to restart the total on an event, as well as whether the data needs to be preprocess.

Demo 16.4: Creating a Crosstab Report Demo 16.5: Printing Images

Integrating Report Builder with ActiveX


The last way you can use Report Builder is by integrating report building into your application with the Report Builder Automation Library (or embedding a Report Builder ActiveX Object).

Using RB Automation Functions


RB provides several functions to manipulate reports, some of which allow you to connect to a specific database with a specific user id and password and open pre-defined reports. Others allow you to create new on the fly reports as well as altering queries and every aspect of a report.

Demo 16.6: Report Builder Automation

Exercise 12.2: Creating an RB Automation App


Objective
In this exercise, you will create an automation interface report program of Presidents by Party, and the matching CQT file.

Preview

Templates
Use template Chapter 12 Template 2.app.

Tasks
Step 1: Step 2: Save any previous work. Open the template. Save it as Chapter 12 Exercise 2.app. Step 3: Launch Report Builder Create a query using the following tables and columns: Parties: President: Step 4: Step 5: Step 6: Step 7: Step 8: Party Pres_name, Birth_Date, Yrs_Serv, Death_Age

Set a break group on PARTY Define the report layout. Save it as Chapter 12 Exercise 2.cqt (a Query/Report template type) In your application, define a function ( OpenReport) as a global internal function. Save and test your application.

Chapter 13: Team Developer 6 New Controls

Team Developer 6 NEW Controls

Team Developer 6 introduces the following new controls:

Tree

A Tree control is a rich and compact way of representing hierarchical data. It allows end-users to navigate and interact with data. Each element in a Tree is called a Tree Item. Depending on the nature of the data that you might want to represent, tree items can be static or dynamically created the application used in this document builds a Tree control based on the result set of two SQL SELECT statements. To implement this control, create a top level window and look for the Tree Control icon () in your Controls screen; click on this icon and draw it on the window of your selection. Team Developer 6 provides a new set of SalTree* functions that have been properly docu-mented to ensure that you gain the flexibility and control that you will need to manipulate this object in any way for details about Tree Control new API please refer to Team Developer 6 Help and type the keyword: SalTree

Navigation Bar
The Navigation Bar is a container used primarily to control the navigation within your programs. To understand how a Navigation Bar behaves it is important for you to be aware that within a Navigation Bar you might find one or more Navigation Panes and Groups . Each of these Navigation Panes and Groups will help you get the screen layout you look for. To implement this control create a top level window and look for the Navigation Bar icon () in your Controls screen; click on this icon and draw it on the window of your selection. Team Developer 6 offers a vast num-ber of SalNav* functions that you are able to use to manipulate this control for details on Navigation Bar new API please refer to Team Developer 6 Help and type the keyword: SalNav

Tab Control

The Tab Control in Team De-veloper 6 is a brand new object that behaves pretty much like what you are accustomed to with QuickTabs in previous ver-sions of Team Developer. If you have QuickTabs applica-tion and you want to convert them to use Team Developer 6 new Tab Control, you can use the Quick Tab Migration Wi-zard that comes with Team Developer 6. With this Tab Control you are able to associate child object by simply selecting a Tab Page and then dropping any object in it.

l
To implement this control create a top level window and look for the Tab Bar icon () in your Controls screen; click on this icon and draw it on the window of your selection. If you want to add a new Tab Page to this control, please look for the Tab Page icon () in you Controls screen; click on this icon and then drop the Tab Page on the Tab Control. Team Developer 6 offers a new set of SalTab* functions that you are able to use to manipulate this control for details on Tab Control API please refer to Team Developer 6 Help and type the keyword: SalTab The application used for the purpose of this document illustrates the imple-mentation of a WPF Control: Microsoft .NET WebBrowser. You will find a more advanced WPF Control example in: C:\...\Unify\Team Developer 6.0\Samples\60Demos\Demo2.

Application Demonstration
Once you have installed Team Developer 6 Samples look for the following folder location: C:\...\Unify\Team Developer 6.0\Samples\60Demos\Demo1 Inside this folder you will find two *.APP files: a. Win32DemoApp.app In this file you will find an implementation of the Navigation Bar, Tree Control and SalMail Class for a Win32 application.

b. WPFDemoApp.app In this file you will find an implementation of the Navigation Bar, Tree Control, SalMail Class and the WPF Control

Creating a Split Window


To create a Split Window you will need: an MDI Window, a Form Window one (or two) Modeless Dialogs and the use of a combination of SalCreate-Window( ) and SalDlgSetDockStatus( ) calls. The application used in this document illustrates a simple method to create a Split Window the following screenshot illustrates the method used for this demonstration:

Implementing a Tree Control


Creating a Tree Control is an easy task in Team Developer 6. It is a matter of simply selecting the Tree Control icon () from the Controls window and then drop-ping the object into a top-level window of your selection. Filling the content of a Tree Con-trols can be achieved manually or dynamically the application used in this document illustrates the dynamic method. As we mention earlier in this doc-ument each element of a Tree Control is called a Tree Item. All Tree Items depend from a main element called Root. To obtain the Root handle of a Tree Element use the following call:

Set hRoot = SalTreeGetFirstItem( treeDemo, 0 ) the returned value for hRoot will be the one that belongs to the Root ele-ment. You can show or hide the Root element from a Tree Control by changing the Show Root attribute from the Attribute Inspector window to Yer or No. The following code illustrates how the Tree Control implemented in dlgLeft was populated based on the SQL Result Set of two SQL SELECT statements.

Implementing a Navigation Bar


Navigation Bar controls can be dropped on form windows and dialogs only. Across the application used in this document you will find multiple imple-mentations of this control. The Navigation Bar is, if not the most, one of the most representative controls to achieve the look and feel of a Microsoft Out-look application. Creating a Navigation Bar is just a matter of selecting this object from the Team Developer 6 Controls window and then dropping it into a form window or dialog of your selection. The following screenshots illustrates how a Navigation Bar is implemented and how its child objects get associated to each Navigation Pane for details about these screenshots please refer to the dlgLeft dialog.

Implementing a Tab Control

If you are familiar with cQuickTabs you will have no trouble to get use to Team Developer 6 new Tab Control. Existing applications that currently use cQuickTabs can be converted to Tab Controls by using Team Developer 6 Quick Tabs Migration Wizard.

Creating a Tab Control is as easy as creating any other Team Developer con-trol. Just click on the Tab Bar icon () in the Controls window and drop the object on a top-level window. Tab Page controls can be added to an existing Tab Control by clicking on the Tab Page icon () and then dropping them in it. Adding child objects to a Tab Page can also be achieved by directly dropping these objects on them or by editing the outline. Tab Page controls can be dynamically created by using the SalTabAddPage( ) function If you like to see an example of this procedure please look at the code below the frmContacts.PAM_SetLayout:

Implementing the SalMail Class


In order to properly implement the SalMail Class you will have to create two instances of it: one to send emails using SMTP protocol and another to re-ceive email using POP3 protocol If you look at the Variable Declaration for gridEmail you will find oSMTP and oPOP3, each of them represent an in-stance of the new SalMail Class.

Receiving emails using POP3 protocol 1. Define User and Mail Server settings as follows: Call oPOP3.SetUser( sUserName, sPassword ) Call oPOP3.SetMailServer( sServerName, nPort, bSSL1, bSend 2)
1) bSSL will be TRUE if the Mail Server requires an SSL connection, otherwise se it to FALSE. 2) bSend will always be FALSE when using SalMail Class instance to receive emails.

2. Connect to your Mail Server. To connect to your Mail Server use the fol-lowing call: Set nPOP3Connect = oPOP3.Connect( ) If the function succeeds nPOP3Connect will always be zero (0) for a list of the different return values for SalMail.Connect( ) function please look at Team Developer 6 Help and type the keyword: Connect - SalMail Method. 3. Retrieve envelope(s) information as follows: Set nPOP3ReturnGetEnvelopes = oPOP3.GetEnvelopes( bPOP3First, nPOP3Count, a_nPOP3MessageIDs, a_sPOP3DatesReceived, a_sPOP3Subjects, a_sPOP3Originators ) If SalMail.GetEnvelopes( ) succeeds (this will happen when its return is zero) run through the following arrays: a_nPOP3MessageIDs, a_sPOP3DatesReceived, a_sPOP3Subjects and a_sPOP3Originators. If you want to retrieve email body use: SalMail.GetMail( ) or Sal-Mail.GetNextEmail( ) respectively. 4. Once you finish downloading all your emails proceed to disconnect from the Mail Server as follows: Set nPOP3ReturnDisconnect = oPOP3.Disconnect( ) If SalMail.Disconnect( ) function succeeds the function will return zero (0).

The code under gridEmail.PAM_Get illustrates how to receive emails and then store then inside a database table. Sending emails using SMTP protocol 1. Define User and Mail Server settings as follows: Call oSMTP.SetUser( sUserName, sPassword ) Call oSMTP.SetMailServer(sServerName, nPort, bSSL3, bSend 4)
3 bSSL will be TRUE if the Mail Server requires an SSL connection, otherwise se it to FALSE. 4 bSend will always be TRUE when using SalMail Class instance to send emails.

2. Connect to your Mail Server. To connect to your Mail Server use the fol-lowing call: Set nreturnConnect = oSMTP.Connect( ) If the function succeeds nreturnConnect will always be zero (0) for a list of the different return values for SalMail.Connect( ) function please look at Team Developer 6 Help and type the keyword: Connect - SalMail Method. 3. Invoke SalMail.SendMail( ) function to deliver a email: Set nreturnSendMail = oSMTP.SendMail( nMailFormat, dfSubject, dfFrom, dfTo, dfCc, mlEmailContent, sAttachments, bDeliveryRecipient, nMailPriority ) sAttachments. This is a list of fully qualified file. If you want to attach more than one file use a semicolon to separate each file. For a full description of the SalMail.SendMail( ) function please use Team Developer 6 Help and type the keyword SendMail - SalMail Me-thod. 4. Once you have finished sending an email proceed to disconnect from the Mail Server as follows: Call oSMTP.Disconnect( ) In case you want to get a better sense of how to implement Team Devel-oper 6 SalMail Class to send emails please refer to the application used in this document and look the code under dlgEmailSend.pbSend.SAM_Click you will find everything you will need to implement this functionality yourself.

Implementing WPF Custom Control


WPF Custom Controls are used in Team Developer 6 WPF Applications to incorporate todays most modern graphical controls into your applications. The following WPF Controls are examples of the types of controls that you will be able to use in your Team Developer 6 WPF Applications:

The application used in this document illustrates how to implement Microsoft .NET WebBrowser Control. You will find this control implementation in WPFDemoApp.app under dlgEmail.SAM_CreateComplete.

For a complete description of Microsoft .NET WebBrowser Control please re-fer to the following link:

http://msdn.microsoft.com/en-us/library/cc491147.aspx

Note: For more information about the use of WPF Controls in Team De-veloper 6 please refer to the white paper titled: WPF Container and con-trol in TD 6.0

S-ar putea să vă placă și