Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
20-6201-0002
Trademarks
Centura, the Centura logo, Centura net.db, Centura Web Developer, Gupta, the Gupta logo, Gupta Powered, the Gupta Powered logo, Fast Facts, Object Nationalizer, Quest, QuickObjects, SQL/API, SQLBase, SQLBase Exchange, SQLConsole, SQLGateway, SQLHost, SQLNetwork, SQLRouter, SQLTalk, and Team Object Manager are trademarks of Gupta Technologies LLC and may be registered in the United States of America and/or other countries. The trademarks TeamWindows, ReportWindows and EditWindows, and the registered trademark SQLWindows, are all exclusively used and licensed by Gupta Technologies LLC. Adobe is a trademark of Adobe Systems, Incorporated. IBM, OS/2, NetBIOS, and AIX are registered trademarks of International Business Machines Corporation. Java, JavaScript, and Solaris are trademarks of Sun Microsystems, Incorporated. ActiveX, Microsoft, MSDN, Outlook, PowerPoint, SQL Server, Visual Basic, Visual C++, Visual Studio, Windows, Windows NT, and Win32 are either registered trademarks or trademarks of Microsoft Corporation in the United States of America and/or other countries. Netscape FastTrack and Navigator are trademarks of Netscape Communications Corporation. Novell is a registered trademark, and NetWare is a trademark of Novell, Incorporated. All other product or service names mentioned herein are trademarks or registered trademarks of their respective owners.
Copyright
Copyright 2002 by Gupta Technologies LLC. All rights reserved. SQLWindows 3.0 Developing with SQLWindows 20-6201-0002 May 2002 Author: Mark Hunter
Contents
Title:
Contents i
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Purpose and audience of this manual. . . . . . . . . . . . 1-16 Scope of this manual. . . . . . . . . . . . . . . . . . . . . . . . . 1-16 What you need to know. . . . . . . . . . . . . . . . . . . . . . . 1-16 Summary of chapters . . . . . . . . . . . . . . . . . . . . . . . . 1-16 Notation conventions. . . . . . . . . . . . . . . . . . . . . . . . . 1-18
1 About SQLWindows . . . . . . . . . . . . . . . . . . . . .
What is Team Developer?. . . . . . . . . . . . . . . . . . . . . . 1-2 What is SQLWindows? . . . . . . . . . . . . . . . . . . . . . . . . 1-2 SQLWindows environments . . . . . . . . . . . . . . . . . . . . 1-3 Objects, messages, and events . . . . . . . . . . . . . . . . . 1-5
2 SQLWindows Desktop . . . . . . . . . . . . . . . . . .
SQLWindows user interface . . . . . . . . . . . . . . . . . . . . 2-2 Toolbars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-4 Tab views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-7 Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-13 Right mouse button features . . . . . . . . . . . . . . . . . . . 2-13 Editing object attributes. . . . . . . . . . . . . . . . . . . . . . . 2-16 Attribute Inspector . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-17 Coding Assistant . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-18 Active Coding Assistant . . . . . . . . . . . . . . . . . . . . . . 2-20 Controls palette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-23 SQLWindows menus. . . . . . . . . . . . . . . . . . . . . . . . . 2-26 Debugger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2-26 Keyboard shortcuts . . . . . . . . . . . . . . . . . . . . . . . . . . 2-26 SQLWindows command line arguments . . . . . . . . . . 2-32 -3
Contents
4 SQLWindows Menus . . . . . . . . . . . . . . . . . . . . .1
File menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-2 Edit menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-5 Project menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-11 Component menu . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-20 Layout menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-21 Debug menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-26 Tools menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-28 Database Explorer menu . . . . . . . . . . . . . . . . . . . . . 4-40 ActiveX Explorer menu . . . . . . . . . . . . . . . . . . . . . . . 4-47 Window menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-48 Help menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4-49
5 SQLWindows Objects . . . . . . . . . . . . . . . . . . . .1
Adding objects. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-2 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4 Naming conventions for objects . . . . . . . . . . . . . . . . . 5-4 Types of objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-4 Top-level objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-5 MDI windows. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6 Messages that objects receive . . . . . . . . . . . . . . . . . . 5-6 Form window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6 Dialog box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-9 Table window . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-11 MDI window. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-12 Child windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-17 Background text . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-19 Group box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-20 Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-21
-4
Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-22 Data field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-23 Multiline field . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-25 Push button . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-26 Radio button . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-30 Option button. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-31 Check box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-35 List box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-36 Combo box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-38 Child table window . . . . . . . . . . . . . . . . . . . . . . . . . . 5-40 Table window column . . . . . . . . . . . . . . . . . . . . . . . . 5-41 Picture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-41 Scroll bars . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-41 Custom control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-42 ActiveX control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-42 Toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-42 Status bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-45 Message boxes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-46 Standard dialogs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-46 Object colors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-47 Fonts for objects with text . . . . . . . . . . . . . . . . . . . . . 5-47 Changing default colors and fonts. . . . . . . . . . . . . . . 5-48 Form units . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-48 Window handles . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-49 Docking windows . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-49 Using objects as variables . . . . . . . . . . . . . . . . . . . . 5-50 Using object names as parameters. . . . . . . . . . . . . . 5-51 Top-level window parameters . . . . . . . . . . . . . . . . . . 5-51
6 Application Menus . . . . . . . . . . . . . . . . . . . . . . . .1
About menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2 Popup menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-2 Menu items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-3
-5
Contents Menu separator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-5 Cascading menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-5 Menu row . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6 Menu column. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-6 Named menus. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-7 Menu status text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-9 Windows menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-9 Menu Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6-10
8 Object-Oriented Programming . . . . . . . . . . .1
About object-oriented programming . . . . . . . . . . . . . . 8-2 Objects, classes, and inheritance . . . . . . . . . . . . . . . . 8-2 Designing classes and objects . . . . . . . . . . . . . . . . . . 8-3 Writing applications with classes and objects . . . . . . . 8-3 -6
Developing with SQLWindows
Class inheritance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-3 Types of classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-5 Types of objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-7 Defining classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-9 Defining functional classes . . . . . . . . . . . . . . . . . . . . 8-10 About window classes. . . . . . . . . . . . . . . . . . . . . . . . 8-10 Class contents inheritance . . . . . . . . . . . . . . . . . . . . 8-15 Creating user-defined objects . . . . . . . . . . . . . . . . . . 8-18 Creating user-defined variables . . . . . . . . . . . . . . . . 8-19 Creating user-defined windows. . . . . . . . . . . . . . . . . 8-24 Using message actions in classes . . . . . . . . . . . . . . 8-26 Using message actions in objects . . . . . . . . . . . . . . . 8-33 Instance variables . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-36 Using instance variables in classes and objects . . . . 8-37 Class variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-42 Class functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-45 Using class functions in classes and objects . . . . . . 8-45 References in container objects . . . . . . . . . . . . . . . . 8-53 MyValue system variable . . . . . . . . . . . . . . . . . . . . . 8-54 SalObjIsValidClassName . . . . . . . . . . . . . . . . . . . . . 8-54 SqlVarSetup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8-54
9 Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
About messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-2 Types of messages . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-2 Message names and numbers . . . . . . . . . . . . . . . . . . 9-2 About SAM_* messages . . . . . . . . . . . . . . . . . . . . . . . 9-2 Application-defined messages . . . . . . . . . . . . . . . . . . 9-3 Microsoft Windows messages. . . . . . . . . . . . . . . . . . . 9-4 Processing messages . . . . . . . . . . . . . . . . . . . . . . . . . 9-4 System variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-5 SAM reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-6 SAM_* summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9-44
-7
Contents
10 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
Run mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 Breakpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-2 Debug toolbar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-4 Debugging COM servers. . . . . . . . . . . . . . . . . . . . . 10-11 Debugging DLLs . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-11 Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10-11 Writing your own debugging code . . . . . . . . . . . . . . 10-11
12 SQL Programming
. . . . . . . . . . . . . . . . . . . . . . .1
Using SQL in a SQLWindows application . . . . . . . . . 12-2 What you need to know. . . . . . . . . . . . . . . . . . . . . . . 12-2 Database access cycle . . . . . . . . . . . . . . . . . . . . . . . 12-3 Multistep interface . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-4 Single-step interface . . . . . . . . . . . . . . . . . . . . . . . . 12-15 Long Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-17 SQL error handling . . . . . . . . . . . . . . . . . . . . . . . . . 12-17 Using both SQL error handling methods. . . . . . . . . 12-18 Transaction scope . . . . . . . . . . . . . . . . . . . . . . . . . . 12-24 Multi-connection transactions . . . . . . . . . . . . . . . . . 12-25 Table windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-27
-8
List boxes and combo boxes. . . . . . . . . . . . . . . . . . 12-27 Other Sql* functions . . . . . . . . . . . . . . . . . . . . . . . . 12-28 Database parameters . . . . . . . . . . . . . . . . . . . . . . . 12-28 Techniques for multiuser databases . . . . . . . . . . . . 12-38 Stored commands . . . . . . . . . . . . . . . . . . . . . . . . . . 12-41 Setting the execution context . . . . . . . . . . . . . . . . . 12-43 Character conversion . . . . . . . . . . . . . . . . . . . . . . . 12-45 Named cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12-45 Database Explorer . . . . . . . . . . . . . . . . . . . . . . . . . 12-45 SQL troubleshooting . . . . . . . . . . . . . . . . . . . . . . . . 12-45
13 OLE DB Consumer . . . . . . . . . . . . . . . . . . . . . . .1
SQLWindows as a consumer . . . . . . . . . . . . . . . . . . 13-2 Session Handle data type . . . . . . . . . . . . . . . . . . . . . 13-2 Connecting to a data source . . . . . . . . . . . . . . . . . . . 13-3 Sql* functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13-4 OLE DB stored procedures . . . . . . . . . . . . . . . . . . . . 13-7
14 Report Programming . . . . . . . . . . . . . . . . . . . . .1
What you need to know. . . . . . . . . . . . . . . . . . . . . . . 14-2 About Report Builder . . . . . . . . . . . . . . . . . . . . . . . . . 14-2 Designtime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-3 Runtime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-5 SalReportPrint. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-7 SalReportPrintToFile . . . . . . . . . . . . . . . . . . . . . . . . 14-12 SalReportView . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-12 SalReportReset. . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-15 SalReportClose . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-17 SalReportCreate (creating a report template) . . . . . 14-17 Input variables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14-17 SAM_ReportNotify . . . . . . . . . . . . . . . . . . . . . . . . . 14-18 Creating reports from table windows. . . . . . . . . . . . 14-20
15 Table Windows . . . . . . . . . . . . . . . . . . . . . . . . . . .1
Developing with SQLWindows
-9
Contents About table windows . . . . . . . . . . . . . . . . . . . . . . . . . 15-2 Types of table windows. . . . . . . . . . . . . . . . . . . . . . . 15-2 Top-level table windows . . . . . . . . . . . . . . . . . . . . . . 15-3 Child table windows . . . . . . . . . . . . . . . . . . . . . . . . . 15-4 Table window columns . . . . . . . . . . . . . . . . . . . . . . . 15-7 User interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-9 Programming techniques . . . . . . . . . . . . . . . . . . . . 15-12 Context row . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-24 Populating a table window . . . . . . . . . . . . . . . . . . . 15-25 Dynamic table windows. . . . . . . . . . . . . . . . . . . . . . 15-31 Sum, average, and sort functions . . . . . . . . . . . . . . 15-32 Table range . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-33 Table window cache . . . . . . . . . . . . . . . . . . . . . . . . 15-35 Table window flags . . . . . . . . . . . . . . . . . . . . . . . . . 15-37 Row flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-38 Column flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-39 TBL_Error constant . . . . . . . . . . . . . . . . . . . . . . . . . 15-40 TBL_* constants . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-40 Table window messages . . . . . . . . . . . . . . . . . . . . . 15-40 Setting the focus row. . . . . . . . . . . . . . . . . . . . . . . . 15-43 Focus cell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-44 Deselecting all rows . . . . . . . . . . . . . . . . . . . . . . . . 15-44 Finding the visible range . . . . . . . . . . . . . . . . . . . . . 15-44 Scroll position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-44 Table window title . . . . . . . . . . . . . . . . . . . . . . . . . . 15-44 Table window font . . . . . . . . . . . . . . . . . . . . . . . . . . 15-45 Table window color . . . . . . . . . . . . . . . . . . . . . . . . . 15-45 Column title . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-45 Column width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-45 Column identifier and column position . . . . . . . . . . 15-45 Locking columns . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-47 Row header . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-47
-10
Split windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15-49 Using the Clipboard with table windows . . . . . . . . . 15-50 Using database result sets with table windows . . . . 15-51 Checking and setting a cell's field edit flag . . . . . . . 15-51 Processing WM_* cell editing messages . . . . . . . . 15-52
16 Pictures
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
About pictures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-2 Picture attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-2 Sources of pictures at designtime . . . . . . . . . . . . . . . 16-3 Using 256-color bitmaps . . . . . . . . . . . . . . . . . . . . . . 16-4 Picture messages . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-4 Picture functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16-5 Sources and destinations for pictures at runtime . . . 16-7 Storing pictures in a database. . . . . . . . . . . . . . . . . . 16-9 Other SAL picture functions . . . . . . . . . . . . . . . . . . 16-10
17 Drag-and-Drop . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
About drag-and-drop . . . . . . . . . . . . . . . . . . . . . . . . . 17-2 Source and target windows . . . . . . . . . . . . . . . . . . . . 17-2 Drag-mode events. . . . . . . . . . . . . . . . . . . . . . . . . . . 17-3 Auto dragging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-3 Application-initiated dragging . . . . . . . . . . . . . . . . . . 17-3 Enabling and disabling dropping . . . . . . . . . . . . . . . . 17-3 Application-defined cursors . . . . . . . . . . . . . . . . . . . . 17-4 Functions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17-4 Source window messages . . . . . . . . . . . . . . . . . . . . 17-5 Target window messages . . . . . . . . . . . . . . . . . . . . . 17-6 Auto-dragging example . . . . . . . . . . . . . . . . . . . . . . . 17-7 Application-initiated dragging example . . . . . . . . . . . 17-8 Dropping from Explorer . . . . . . . . . . . . . . . . . . . . . . . 17-9
18 Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
Include libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18-2
-11
Enumerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-20 Dynamic instantiation . . . . . . . . . . . . . . . . . . . . . . . 20-22 Assigning COM CoClass variables . . . . . . . . . . . . . 20-22 Reference counting . . . . . . . . . . . . . . . . . . . . . . . . . 20-23 Setting error information . . . . . . . . . . . . . . . . . . . . . 20-23 Interface inheritance . . . . . . . . . . . . . . . . . . . . . . . . 20-24 Debugging COM servers. . . . . . . . . . . . . . . . . . . . . 20-25 Type information . . . . . . . . . . . . . . . . . . . . . . . . . . . 20-26 Registering servers . . . . . . . . . . . . . . . . . . . . . . . . . 20-27 Regenerating GUIDs . . . . . . . . . . . . . . . . . . . . . . . . 20-28 Internal implementation . . . . . . . . . . . . . . . . . . . . . . 20-28 Threading support . . . . . . . . . . . . . . . . . . . . . . . . . . 20-28 MTS (Microsoft Transaction Server) support . . . . . 20-34
22 Custom Controls . . . . . . . . . . . . . . . . . . . . . . . . . .1
About custom controls. . . . . . . . . . . . . . . . . . . . . . . . 22-2 Adding a custom control to a window . . . . . . . . . . . . 22-2 Message actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-3 Using classes and libraries . . . . . . . . . . . . . . . . . . . . 22-4 Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-5 Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-6 Writing a SQLWindows-aware custom control . . . . 22-11 Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22-17
Developing with SQLWindows
-13
Contents
-14
Chapter i
Preface
This preface explains: Purpose and audience of this manual What the reader of this manual needs to know Organization of this manual Conventions used in this manual Other helpful resources How to send us your comments
i-15
Preface
Summary of chapters
This manual is organized in the chapters in the table below.
1 2 3 4 5 6 7
About SQLWindows SQLWindows Desktop Deploying and Migrating Applications SQLWindows Menus SQLWindows Objects Application Menus SAL (Scalable Application Language)
Designtime environment and runtime environment; objects, messages, and events Main window, Controls palette, Attribute Inspector, Coding Assistant, application outline Installing production applications, SQLWindows runtime, migrating to 32-bit Menu items in the main window Objects that you can add to an application, and their Attribute Inspector properties Popup menus, menu items, named menus, creating menus dynamically, menu status text Data types, variables, arrays, constants, operators, expressions, statements, functions
i-16
Summary of chapters
8 9 10 11 12 13 14 15 16 17 18 19
Object-Oriented Programming Messages Debugging Formatting and Validating SQL Programming OLE DB Consumer Report Programming Table Windows Pictures Drag-and-Drop Libraries Overview of COM and Writing COM Client Applications Writing COM Server Applications Using the HTML Designer Calling External Functions in DLLs Custom Controls Symbol Scoping and Qualified References
Classes, inheritance, objects, defining classes, creating objects, message actions, instance variables, class variables, class functions Types of messages, processing messages, an explanation of each SAM_* message Animation, breakpoints, debugging windows, writing custom debugging code Picture formats, profile-driven formats, country profiles, default validation, custom validation, input masks Database access cycles, error handling, database parameters, multiuser techniques When to use, Session Handle data type, functions, stored procedures, SAL/OLE DB mapping Writing reporting application for templates created by Report Builder Types of table windows, user interface, simple and advanced programming techniques, table window features, messages Picture properties, messages, and functions Functions and messages you use to write a drag-and-drop interface in an application Creating and using libraries to share common code Introduction to COM, the Controls palette and ActiveX Explorer, outline, events, controls and containers, automation, properties, exceptions, and include libraries COM Class Wizard, outline, automation types, events, enumerations, instantiation and assignment, debugging, type information, registration, threading and MTS Editing HTML, XML, ASP, and similar documents; integrating web pages with servers written in SQLWindows Using external functions and DLLs, writing a DLL, using SWIN.DLL Using custom controls in applications
20
21 22 23 24
i-17
Preface
Notation conventions
The table below show the notation conventions that this manual uses. Notation You User bold type Courier 9 REPBI*.EXE Explanation A developer who reads this manual The end-user of applications that you write Menu items, push buttons, and field names. Things that you select. Keyboard keys that you press.
Precaution
Warning:
Vital information
Important:
Note:
A plus sign between key names means to press and hold down the first key while you press the second key These are numeric boolean constants defined internally in
SQLWindows: Constant TRUE FALSE Value 1 0 Meaning Successful, on, set Unsuccessful, off, clear
i-18
Notation conventions
i-19
Chapter 1
About SQLWindows
This chapter introduces SQLWindows, including: Designtime environment Runtime environment Objects, messages, and events
1-1
Chapter 1
About SQLWindows
What is SQLWindows?
SQLWindows is an application development system that developers (programmers) use to create applications that run on Microsoft Windows. An application that you create in SQLWindows has scroll bars, menus, and dialog boxes, and other objects associated with a graphical user interface (GUI).
1-2
SQLWindows environments
To write a SQLWindows application, you draw screen objects in a design window. As you draw, SQLWindows generates predefined code definitions. You define behaviors in the outline with SAL (SQLWindows Application Language) and SAM (SQLWindows Application Messages).
SQLWindows environments
SQLWindows has two environments: Designtime Runtime 1-3
Chapter 1
About SQLWindows
Designtime environment
At designtime, you first create the user interface. SQLWindows automatically adds definitions in the application outline for each object that you create. Next, you code the logic in the outline. The context-sensitive Coding Assistant help you by showing the items appropriate for where you are in the outline. Finally, you test and debug an application using the animate and breakpoint features. Animate highlights each line of code in the outline it executes. Breakpoints let you suspend execution while you examine and set variables.
Runtime environment
After you develop an application, you make an executable version of the application. To put an application into production, you install the application and the SQLWindows Runtime product on the users computer.
1-4
1-5
Chapter 2
SQLWindows Desktop
This chapter explains the SQLWindows user interface, including: Outline Coding Assistant Right mouse button menus Toolbars Controls palette Attribute Inspector Debugger
2-1
Chapter 2
SQLWindows Desktop
Tree view
Tab view
Status bar The tree view displays a hierarchy of the application, while the tab view displays details about the item selected in the tree. You add and edit objects and actions in the tree view and the tab views. The tree view contains objects that represent parts of your application. The tabs on the right provide multiple views of your application. These views include a graphical layout of your applications interface, as well as an outline of its underlying code or parts of the code, such as variables and libraries. You can change the width of the tree view by putting the mouse pointer on the bar separating the left from the right side of the window. When the mouse pointer changes to a double-headed horizontal arrow, you can click-drag left or right. You can also click the Window toolbar buttons to: View only the tree view
2-2
You can open additional application views for the same application. In the tree view, select an item, click the right mouse button, and then select Open View. An additional application view opens with the tab view maximized. When you have more than one application view, you can navigate between them using the Windows menu. To write a SQLWindows application, you can add screen objects in a Layout tab or in a preview window. SQLWindows has a Controls palette that lets you select and create objects directly in top-level windows in your application. You use the Attribute Inspector to set the properties of objects. With SQLWindows Coding Assistant, you can continue to build and refine your application, defining functions, constants, and variables in SAL statements, and even create more objects if needed. The Controls palette, the Attribute Inspector, and the Coding Assistant are explained in this chapter.
Tree view
The tree on the left side of the explorer window contains objects that represent a hierarchical view of the application. You use the explorer tree to navigate through an application: Click a plus sign (+) to expand an item, revealing its contents Click a minus sign (-) to collapse an item, hiding its contents Click an icon or its name to display the contents of the item in the tab view
Tab views
A tab view can display different views of the item selected in the tree view. Each type of item that is displayed in the tree view has an associated set of tabs that appear at the bottom right. To select a view for the item, you click a specific tab. For example, if you select a form window in the tree view and then click the Layout tab, you see a graphical layout of your form window. If you select this same item, but click the Outline tab, you see a code outline of the form window. For details on the views, read Tab views on page 2-7.
Status bar
SQLWindows has a status bar at the bottom that shows the setting of the Num Lock, Scroll Lock and Caps Lock keys. The status bar also displays a message that shows the currently selected item on the menu or tool bar and the currently selected outline item.
2-3
Chapter 2
SQLWindows Desktop
Turn on the status bar by right-clicking a blank section of a toolbar and selecting Status Bar from the menu. Turn off the status bar by either right-clicking the status bar and selecting Status Bar from the menu or by right-clicking a blank section of a toolbar and selecting Status Bar.
Toolbars
SQLWindows has toolbars that let you quickly select often-used menu commands.
2-4
Toolbars
You control which toolbars are displayed by selecting Tools, Toolbars. For more, read Toolbars tab on page 4-30. Also, you can right-click a blank area of a toolbar and select a toolbar from the context menu.
If you hold the mouse pointer over any of the toolbar buttons for a second or two, a small popup window (a tool tip) displays the buttons function.
Custom toolbars
You can add your own programs to the Tools menu and toolbar (User Tools on page 4-28) and create custom toolbars (Tools tab on page 4-31).
2-5
Chapter 2
SQLWindows Desktop
SQLWindows remembers which toolbars and palettes you used last, including their position. A toolbar or palette appears in the same location, with the same properties, each time you display the toolbar until you change its properties manually. To dock a toolbar, palette, or menu bar: Click its window border or title bar, hold down the left mouse button, and drag it to an edge of the window. To prevent the toolbar from docking accidentally, hold down Ctrl when you drag. OR Double-click its window border or title bar.
Note: For a palette, window border means just below or above an active button or on the left or right edge.
To undock a toolbar, palette, or menu bar: Click its handle (double bar), hold down the left mouse button, and drag.
Handle When a toolbar, palette, or the menu bar is horizontally oriented, the handle is on the left. When a toolbar, palette, or the menu bar is vertically oriented, the handle is at the top. OR Click its window border, hold down the left mouse button, and drag. OR Double-click its window border. OR Hold down Ctrl and click its handle or window border
2-6
Tab views
When palettes are docked, they have a maximize/restore button and a close button.
Tab views
When you select a tree view item, you see an associated set of right tabs. Each tab provides a different view of the selected item. The tabs that are provided for each view are listed below: Actions Base classes Class variables Components
2-7
Chapter 2
SQLWindows Desktop
Constants Description Layout Libraries Outline Parameters Returns Static variables Variables
Components tab
The Components tab lists the major parts of the item selected in the tree view. You can change the display style of an item in a Components tab. Select Component, View to choose a list view option (large icons, small icons, list, and details). Each of the display styles is available for all items in the tree view that have children.
Actions tab
The Actions tab displays all statements in a function or message actions section. You can code any SAL statements in this section.
Outline tab
SQLWindows represents the entire application in the outline. Each line in the outline is called an item. To see the entire outline, click the highest-level item in the explorer tree and then click the Outline tab on the right. For other items, the Outline tab presents that part of the outline which corresponds to the selected item. An item can be a parent item or child item. Outline items can be nested. Therefore, some items can also be both child and parent items. A parent item has a solid diamond that signifies that subordinate child items are indented below it. If you double-click, the items expands and the child items appear. Double-click again to collapse the item and hide the child items. An item with a hollow diamond does not have child items. You can also select items in the Component menu to expand and
2-8
Tab views
collapse the selected item or items in an Outline view. For more, read Component menu on page 4-20.
Collapsed Item Expanded Item
Application Description. This is the top-most item in the outline where you enter a description of the application. Design-time Settings. SQLWindows maintains information for its own use in this section. Libraries. You specify include libraries in this section. For more, read Chapter 18, Libraries.
2-9
Chapter 2
SQLWindows Desktop
Global Declarations. This section defines default window settings, formats, internal and external functions, variables, constants, and application actions:
Name Window Defaults Formats Description The default font, color, display style, font, text color, and background color for each object. You can change the default values so that each time you add a particular object, it has the properties specified in this section. Input masks and output formats for number and date/time values. You can change the definitions and add new formats. For more, read Chapter 11, Formatting and Validating. DLLs (Dynamic Link Libraries) that contain functions that the application calls. For more, read Chapter 21, Calling External Functions in DLLs. Global system constants (such as WM_* Messages) and global user constants. For more, read Chapter 7, SAL (SQLWindows Application Language). The names of bitmap, cursor, and icon resource files that you use in the application. For more, read Chapter 7, SAL (SQLWindows Application Language). Global variables. For more, read Chapter 7, SAL (SQLWindows Application Language). Global functions that you write. For more, read Chapter 7, SAL (SQLWindows Application Language). Popup menus that windows in the application share. For more, read Chapter 6, Application Menus. Templates for classes. For more, read Chapter 8, Object-Oriented Programming. Statements to perform when the application receives messages. For more, read Chapter 9, Messages.
Resources
Tab views
Layout tab
When you select the Layout tab, SQLWindows displays the selected top-level window in a graphical view. You can change the size of the window, and move and resize any of its child windows.
To create a child window, select a child window type from the Controls palette. When you move the mouse over the window in the Layout tab the cursor matches the child window type selected in the Controls palette. Click the mouse at the point in the window where you want to place the child window. If you release the mouse, the child window is created at its default size. If you drag out a rectangle before releasing the mouse button, that rectangle is used as the size of the new child window. When the arrow cursor is selected in the toolbar, you can select, move, and resize the child windows. To duplicate the currently selected child window, press Ctrl while dragging the child window. While you are in a Layout tab, the menu of the top-level window is not visible. To see the window as it will appear to a user, select Layout, Preview Window.
2-11
Chapter 2
SQLWindows Desktop
You can also draw child objects graphically using the Controls palette in a Preview window. For more, read Preview Window on page 4-21.
The difference between the Layout tab and a Preview window is that in a Preview window you can: See menus See MDI children Set the runtime position of a window
Constants tab
The Constants tab displays constants declarations in the Global Declarations block of the outline.
Libraries tab
The Libraries tab displays files and dynalibs which are in the outline. An include library is a collection of SQLWindows objects such as form windows, dialog boxes, or class definitions that are shared by more than one application. A dynalib is a compiled SQLWindows module with functions and objects that other applications can dynamically load at runtime. For more, read Chapter 18, Libraries.
Variables tab
The Variables tab displays the Variables block of the application or the selected toplevel window, class, class function, or internal function. 2-12 Developing with SQLWindows
Cursors
Parameters tab
The Parameters tab displays the outline for a Parameters block which belongs to several item types in the application such as functions, top-level windows, and some message actions sections.
Description tab
In a Description tab you can enter text that describes the purpose of the selected item.
Returns tab
The Returns tab displays the return value for functions.
Cursors
In the left or right pane, use the left-pointing arrow to select, collapse, and expand items. On the left side of an Outline tab, use the right-pointing arrow to select, collapse, and expand outline items. On an editable item on the right side of an Outline tab, use the I-beam to select and edit text.
2-13
Chapter 2
SQLWindows Desktop
Note: You can also press Shift+F10 to display the right mouse button menus for the selected item.
Explore
Displays a submenu with selections for the tabs on the right side of the explorer window. This is a quick way to switch tabs.
Open View
Opens the selected item in a new MDI child window. The tab view is maximized, but you can use the splitter to restore the tree view on the left. By using multiple windows, you can maintain different contexts in each application view. You can access the application views from the Window menu.
New
Displays a submenu with items for each of the item types that you can create as a child of the selected item. For example, when the top-most item is selected in the explorer tree, New displays a submenu with one item for each top-level window type.
When an item is selected in an Outline tab, the right mouse button menu can have Add Same Level and Add Next Level selections like the Coding Assistant.
Other examples of when you can use New are shown in this table:
Item selected in tree view Windows External Functions Popup Menus Internal Functions New submenu Top-level window types Library Name Menu, Windows Menu Function
Delete, Rename
Deletes or renames the selected item. (Rename is only displayed in the tree and component views.)
Properties
When the top-level item in the tree view is selected, displays a tabbed dialog that displays application statistics and lets you change runtime settings. For more, read Edit, Properties.
2-15
Chapter 2
SQLWindows Desktop
Select in Layout
When a window item is selected, switches to the Layout tab. If a child window is selected, it will be selected within the top-level window in the Layout tab.
Attribute Inspector
You can also create custom templates so that each new application you create conforms to the default colors and fonts you choose. For more, read New on page 4-2 .
Attribute Inspector
You use the Attribute Inspector to set the properties for an object, such as how the object looks, where it appears, and other characteristics.
The Attribute Inspector uses these types of child controls to show a property's value: Data field Drop-down combo box with a value you can edit Drop-down list with a value you can select but not edit (such as a Yes/No selection) A push button with an ellipsis that displays a dialog (such as for selecting a font or color)
To display the Attribute Inspector: Select Tools, Attribute Inspector OR Click the Attribute Inspector toolbar button OR Press Alt+3
Note: You cannot display the Attribute Inspector while in run mode.
2-17
Chapter 2
SQLWindows Desktop
If another palette overlaps this palette, you must click in an editable area to bring it to the top.
Note: The Attribute Inspector can only display attributes for one object at a time.
The Attribute Inspector is a dockable palette. For more, read Docking toolbars, palettes, and the menu bar on page 2-5. When using the Attribute Inspector to edit properties: Double-clicking an object displays a context menu, but it does not have a Properties menu item The application's context menu has a Properties menu item at all times
Setting properties
To set properties for an object: 1. 2. 3. 4. Make the Attribute Inspector visible (through the menu item or toolbar button). Select the object in the tree view, an Outline tab, or a Layout tab. The Attribute Inspector displays attributes for the selected object. Make your attribute changes in the right hand column of the Attribute Inspector. Your changes are applied when you have finished editing the attribute. To undo changes made since the last update to this objects attributes, press Undo All. Note that you can undo your changes as long as you have not switched to another selection.
Coding Assistant
The Coding Assistant lists items that you can add to the application. You use the Coding Assistant to: Define classes Define menus Define functions, constants, and variables Define events Code SAL statements Set parameters for functions that you call Create objects
Coding Assistant
The Coding Assistant is context-sensitive. As you move through the application, the contents change to reflect the items that you can add where you are positioned in the outline. To display the Coding Assistant: Press Alt+2 OR Select Tools, Coding Assistant OR Press the Coding Assistant toolbar button
The Coding Assistant has one or two lists depending on what is selected in the outline: Click Add Same Level to add the highlighted item at the same level as the selected item in the outline Click Add Next Level to add the highlighted item at the next level under the selected item in the outline
When you edit an Actions section or Message Actions block, the Coding Assistant can display several categories of information. If it can, the Coding Assistant displays the name of the current category in a combo box at the top of the palette. As you change the selected category, the list changes to those symbols and constructs which belong to that category. When you select an item in the Message Actions block of a window, The Coding Assistant lists complete On statements with message names that are appropriate for
2-19
the object. For example, when you select an item in the Message Actions for a push button, the Coding Assistant presents a list of SAM events, such as On SAM_Click. 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 the prefix. If another palette overlaps this palette, you must click in an editable area to bring it to the top. The Coding Assistant is a dockable palette. For more, read Docking toolbars, palettes, and the menu bar on page 2-5. You can configure the Coding Assistant by selecting Tools, Preferences. For more, read Preferences on page 4-32.
Complete Word
Complete Word types the rest of a variable, command, function, or symbol name once you have entered enough characters to make the expression unambiguous. The Complete Word option is never automatic and always requires user action. The user can select the toolbar option, menu option, or hot key. The hot key is CTRL+SPACEBAR for complete word. Type the first few letters of the name, then press CTRL+SPACEBAR.
Developing with SQLWindows
2-20
If what you have typed has more than one possible match or no match at all, then invoking Complete Word will display the Members list, which you can then use to find the term and insert it into your code. See List Members for more information.
Parameter Info
The Parameter Info option opens the Parameters list to give you information about the number, names, and types of parameters required by a function or attribute, plus the parameter description if available.
The parameter in bold indicates the next parameter that is required as you type the function. The Parameters list is also displayed for nested functions. If you type a function as a parameter to another function, the Parameters list displays the parameters for the inner function. Then, when the inner function Parameters list is complete, the Parameters list reverts to displaying the outer function parameters. Parameter Info can be activated in the following ways: If the Preference Setting Auto Parameter Info is activated, then whenever the user is in the scope of an Actions outline section, after the name of a function, type an open parenthesis as you normally would to open the Parameters list. If the you select the name of a method and select the toolbar option, menu option, or hotkey. If the cursor is inside the parenthesis of a function and the user selects the toolbar option, menu, or hotkey.
2-21
Chapter 2
SQLWindows Desktop
Quick Info
The Quick Info option displays the complete declaration for any identifier in your code. Move the mouse so that the cursor is over an identifier (hover over an identifier), and you will see its declaration displayed in a yellow pop-up box. If the identifier is a function, then the Quick Info also contains descriptive information about the function.
Quick Info can be activated in the following ways: If the Preference Setting "Automatic Quick Info tooltips " is activated, then whenever an identifier is selected. If the user selects the identifier and selects the toolbar option, menu option, or hotkey (Ctrl+Q).
List Members
List Members is a floating/modeless dialog box with a list box containing all members of the class or scope that has focus. This list is intended to allow the user to select the desired member. In the example below, the user has just typed Call tblCompan, then typed a period:
List Members can be activated in the following ways: If the Preference Setting Auto List Members is activated, then whenever the user is in the scope of an Actions Outline Section and types the name of a class or a class instance followed by a period, the List Members is activated. If the user selects the name of a class or a class instance and selects the toolbar option, menu option, or hotkey.
When activated, this displays all valid members (for a class, an instance, or scope) in a scrollable list. For example, you can scroll or use the arrow keys to navigate
Controls palette
through the list, or, if you know the first few letters of the member name, begin typing to jump directly to the member in the list. To insert the selected member in your code, do one of the following: Type the character that will follow the member, such as open parenthesis, comma, space, semicolon, or others, to insert the selected member followed by the character that you have just typed. This works for any non-identifier character. -orPress TAB, CTRL+ENTER, ENTER, or double-click to insert just the member. If no item is selected in the drop-down menu, ENTER inserts a blank space. CTRLENTER will insert the item that has the focus box, even if it is not selected. Press ESC at any time to close the Members list.
Controls palette
The Controls palette has a set of buttons and list box for selecting objects. The lower part of the Controls palette lists subclasses of the selected object if any exists in the current application. Standard childwindow toolbar
The Controls palette has three toolbars: The standard child-window toolbar which contains a button for each window type built into SQLWindows.
2-23
Chapter 2
SQLWindows Desktop
The custom controls toolbar which contains a generic custom control push button and buttons for two QuickObject types: cQuickTable and cQuickGraph. You can add buttons for child window classes to this toolbar. The ActiveX toolbar which contains a generic ActiveX button. You can add buttons for ActiveX components to this area. This toolbar also contains a Report button, which represents the ActiveX interface of Gupta Report Builder. You can find detailed information about using this interface in chapter 6 of the Business Reporting manual.
As you move the mouse over the Controls palette, it displays as an arrow cursor. If you hold the mouse pointer over one of the buttons for a second or two, a tool tip window displays the title of the button. To display the Controls palette: Press Alt+4 OR Select Tools, Controls OR Press the Controls toolbar button
To add an object, click its button in the Controls palette, move the mouse pointer to the window where you want to place the child object, and click and drag. When the mouse pointer is over a child object, it changes to a four-headed arrow. You can then click to select the child object and move or delete it. You can also cut, copy, and paste objects. To duplicate a child object, hold down Ctrl when you click it. When an object is selected, it has handles on its sides. If it is the only selected object, you can move the mouse pointer over one of these handles and click-drag to change the size of the object. You can select multiple objects with the arrow cursor by holding down the Shift key and clicking them or by click-dragging a rectangular region that contains the objects you want to select. When you select multiple objects, you can use the commands in the Layout menu to neatly arrange and size objects. You can select multiple objects with the arrow cursor by holding down the Shift key and clicking them or by click-dragging a rectangular region that contains the objects you want to select. When you select multiple objects, you can use the commands in the Layout menu to neatly arrange and size objects. After you drop a child object on a window, SQLWindows changes the Controls palette selection to the arrow cursor.
Controls palette
You can resize the Controls palette. If another palette overlaps this palette, you must click a button or make a selection in the list to bring it to the top. The Controls palette is a dockable palette. For more, read Docking toolbars, palettes, and the menu bar on page 2-5.
If you have added a button to the custom controls toolbar and you use it to create an object in an application in which that button's class is not defined, SQLWindows automatically includes the application file that defines the class. Be aware of this when adding and using such classes. Gupta Technologies recommends that you define such classes in small APLs which contain a related set of classes and the definitions they require.
2-25
Chapter 2
SQLWindows Desktop
Add a button for the selected component to the Controls palette Choose to display only controls or insertable objects
SQLWindows menus
SQLWindows has these menus: File Edit Project Component Layout Debug Tools Window Help For more, read Chapter 4, SQLWindows Menus.
Debugger
Chapter 10, Debugging describes SQLWindows debugger. In summary, you use the debugger to: Set breakpoints where the application suspends execution Check the values of variables and evaluate expressions Monitor messages that an object receives Display a function call trace Highlight code as it executes (animation) Execute an application a statement at a time (step into) with the option to bypass single stepping when calling a function (step over)
When you are coding statements and building objects at designtime, it is called design mode. When you run the application at designtime, it is call run mode.
Keyboard shortcuts
Displaying SQLWindows palettes and controls
Window Coding Assistant Alt+2 Shortcut
Keyboard shortcuts
Shortcut
2-27
Chapter 2
SQLWindows Desktop
Editing
Action Undo (current edit only) Cut Copy Paste Clear Ctrl+Z Ctrl+X Ctrl+C Ctrl+V Del Shortcut
Expand all below selected section Collapse all below selected section
Keyboard shortcuts
Shortcut
2-29
Chapter 2
SQLWindows Desktop
Libraries
Action Edit library Show item information F5 Shift+F5 Shortcut
Keyboard shortcuts
Debugging
Action Execute or resume execution Stop Debugging Toggle breakpoint Step Into Step over Display Variables window
Display Stack window Display Messages window Display Expressions window
Other
Action Open online help Cycle through settings Properties Component wizards F1 Up/down Arrows Alt+Enter Ctrl+W Shortcut
2-31
Chapter 3
3-1
Chapter 3
Deploying an application
To run a SQLWindows application in a production environment, you must install these components on users' computers: An executable version of the SQLWindows application Deployment files that come with SQLWindows Other components that connect the application to a data source
3-2
Deploying an application
To install deploy*.exe on a development computer, select Gupta Runtime Installer in the Team Developer install program. You then include deploy*.exe in your build process and your application installer executes it.
deploy*.exe adds files to the directory the user specifies and to the Windows /system directory. To see the files that deploy*.exe installs, run it with the /x option:
deploy*.exe /x
deploy*.exe then lists the file names and you can choose individual files to install:
3-3
If you run deploy*.exe without any command line options, you are promoted for the name of the destination directory. To run deploy*.exe without any prompts (in silent mode), specify the /s and /m options:
deploy*.exe /s /m=silent.ini
In the file silent.ini, you specify the destination directory with the MAINDIR keyword:
MAINDIR=C:\destinationdir
deploy*.exe installs the files in the \deploy subdirectory of the directory specified by MAINDIR. Running in silent mode, deploy*.exe installs deploy*.wse (see below) and silent.ini along with the other files. silent.ini also lets you set other installation options. These options are documented by comments in silent.ini.
menuOLEEdit
Because the named menu, menuOLEEdit, calls some of the now unsupported OLE1 functions, SQLWindows does not support it. Many applications may have this menu defined by default as it was defined in the SQLWindows file, NEWAPP.APP. Remove this menu from your applications.
Developing with SQLWindows
3-4
VBXs
Replace VBXs with equivalent ActiveX controls.
QuickOLE
You can continue to use QuickOLE, but Gupta Technologies does not plan to enhance it. For new applications, use ActiveX instead.
CDK
A 32-bit version of the CDK is available for SQLWindows. You need to recompile your 16-bit CDK applications using the 32-bit CDK and save them.
QuickEmail
The 32-bit library of QuickEMail does not have cMailMeter, nor does it have dialog boxes dlgMailAddrsMsg or dlgMailSelectSys. These dialogs were used only by QuickEMail itself and are no longer necessary because the QuickEMail in SQLWindows supports the MAPI (Microsoft) mail interface. If you used these in your SQLWindows code, remove them before converting. Lotus Corporation VIM and Novell MHS are not supported.
Quest
Use Database Explorer to browse and update the database directly from SQLWindows. Report Builder is integrated into Database Explorer, so you can define queries and generate reports. You can also use Report Builder as a stand-alone application to define queries and generate reports.
QuestWindows
Replace QuestWindows with table windows, adding program code to execute a query, populate the table, apply and discard changes, and so on.
Note: SAM_QuestDoDetails has been renamed SAM_TBLDoDetails.
Test tools
Contact your test tool vendor about availability and requirements for their 16-bit tools working in 32-bit.
Developing with SQLWindows
3-5
Chapter 3
Obsolete functions
The following SQLWindows functions were provided for Windows features that are now obsolete, such as OLE1 or VBXs, and are therefore not in SQLWindows. If you use any of these functions in applications, you need to remove them.
OLE1 Support
VBX Support
SqlSharedAcquire SqlSharedRelease
SqlSharedSet SqlSSTGetID
3-6
SqlSSTStatus
QuestWindow Functions
3-7
Chapter 3
3-8
Chapter 4
SQLWindows Menus
This chapter explains these menus in SQLWindows: File Edit Project Component Layout Debug Tools Window Help
4-1
Chapter 4
SQLWindows Menus
File menu
New
Creates a new unnamed SQLWindows application. You name the application the first time you save it. Displays the Templates dialog where you choose an application template for a SQLWindows application. A template provides basic outline items used as a starting point to write an application. The Templates dialog displays the default template with a check box in the application icon. To accept the default template as the new application, click OK. This creates a new unnamed SQLWindows application. You can also select a template other than the default and Click OK to choose it. SQLWindows then opens the new application using the template that you selected. If you click Close, SQLWindows does not create a new application.
Note: If you select the New button on the toolbar, the Templates dialog is not displayed. Instead, a new application is created using the default template.
Note: If you enter an application name without a path, the file must reside in the Templates subdirectory where you installed SQLWindows or in the template directory path set with Tools, Preferences.
To change the default template for creating new applications, select the name of the application that you want as the default template and click Set As Default.
Note: The Templates dialog displays the default template with a check box in the application icon. The Set As Default button is disabled when the default template is selected.
4-2
File menu
To update an application name or description, select the application from the list, change the application name or description, and click Update. To delete an application from the list, select it and click Delete.
Click OK to close the dialog box and save any changes you made. Click Cancel to close the dialog box and undo any changes you made. To save changes to the Templates dialog without closing it, click Apply; you can then click Close to continue working on the current application.
Open
Displays a dialog that lets you select a different application to work on. The File Open dialog can display different file types and you can use the Files of type combo box to chose which you want to see. You can change the initial type shown when the dialog opens by selecting Tools, Preferences, clicking the General tab, and then editing the Default Application File Extension value. You can only open one application at a time. However, you can have more than one view of the same application open at the same time or you can run multiple instances of SQLWindows, each with a different open application.
Save
Saves the open application to disk, including any changes you made after the last time you saved the application. After saving, the application stays open. If you Save an unnamed application, SQLWindows displays the Save As dialog where you name the application and specify its path.
Save As
Saves a copy of the open application under a new name. When you open the application, change it, and then save it under a new name, the changes are not made to the original application. The open application is a newly-saved application. If you give the application a name that already exists, SQLWindows asks you if you want to replace the existing application.
4-3
Chapter 4
SQLWindows Menus
Save as type
You use this combo box to select how you want to save the application: Normal saves the application in an internal format that saves fast and loads fast at designtime. This is also called the binary format. The default extension is *.APP. Compiled saves the compiled code. The default extension is *.EXE Text saves the application in a form that you can open with a text editor. The default extension is *.APT. Indented Text is like Text, but it saves the application with tabs for the indent levels. The default extension is *.APT. Libraries saves the application as an include library. For more, read Include Libraries.
Page Settings
Displays a dialog where you set printing options.
SQLWindows remembers the settings you make in this dialog and uses them for all sessions and all applications on the computer. Collapsed items print exactly as they are currently displayed in the outline (the items under a collapsed item do not print).
Titles
Set titles for the header and footer at the left, center, and right. You can enter literals and these keywords: %A %P Name of application Page number
4-4
Edit menu
%D %T
Date Time
Text Style
Set the font and font size.
Margins
Set the left, right, top, and bottom margins in inches.
Options
Code Only. If checked, only lines that have actual SAL statements print. This does not include formats, external functions, constants, and variables. The Application Description always prints. Line Numbers. If checked, the lines are numbered. Include Display Attributes. If checked, the window attributes print in the outline in the same place as when you save an application as text. Include Named Properties. If checked, the named properties of QuickObjects print.
Print
Displays a standard Windows Print dialog. When you print, SQLWindows uses the settings you made in File, Page Settings. Collapsed items print exactly as they are currently displayed in the outline (the items under a collapsed item do not print).
Exit
Closes SQLWindows. If you changed the open application after the last time you saved it, SQLWindows displays the Save current changes? dialog.
Edit menu
The Edit menu displays these menu options to work with the code outline. Click a menu option to display details.
4-5
Chapter 4
SQLWindows Menus
Undo
Reverses the last editing or formatting action. If the last action is not reversible, this item is disabled.
Cut
Removes the selected items and places them on the Clipboard, overwriting the previous Clipboard contents. This item is disabled if nothing is selected.
Copy
Copies the selected items to the Clipboard, overwriting the previous Clipboard contents. This item is disabled if nothing is selected.
Paste
Pastes the contents of the Clipboard at the mouse position. This item is disabled if the Clipboard is empty.
Delete
Deletes the selected items without copying them to the Clipboard. This is the same as using the Delete key.
Insert Line
Inserts a new item below the selected outline item.
Comment Items
Makes the selected outline items comments. Commented items start with an exclamation point (!) and a space.
Uncomment Items
Changes the selected outline item from comments back to their original form.
Outline menu
Displays these options for displaying various levels of the outline.
4-6
Edit menu
Collapse
Hides all child items of the selected parent item. You can also collapse an outline item by double-clicking its diamond.
Collapse Outline
Collapses the outline so that only top-level items are visible.
Promote
Moves the selected item one indentation level to the left.
Demote
Moves the selected item one indentation level to the right.
Move Up
Moves the selected item above the previous item.
Move Down
Moves the selected item below the next item.
Find
Displays a dialog where you specify what to search for in the outline.
Each time SQLWindows finds the string, it highlights the string and enables Find Next. Click Find Next to search for the next occurrence of the search string.
Note: Find only works in an Outline tab. If you are in a different tab and you execute a Find, SQLWindows automatically switches to the Outline tab.
In an Outline tab, you can use this dialog for window attributes such as Background Color, Data Type, and Line Style. When SQLWindows locates matching text for a
4-7
Chapter 4
SQLWindows Menus
window attribute, it displays a field on top of the outline just below the item that has the matching property. You close the field by clicking elsewhere in the outline or by pressing Esc or Enter.
Match Case
Check this if you want the search to depend on the capitalization of the search string in Find What.
Find Again
Searches for the string you previously specified in the Find dialog.
Replace
Displays a dialog where you specify what to search for in the outline and what to replace it with.
After you enter a search string and a replace string, the push buttons on the bottom of the dialog are enabled.
Note: Replace only works in an Outline tab. If you are in a different tab and you execute a Replace, SQLWindows automatically switches to the Outline tab.
In an Outline tab, you can use this dialog for window attributes such as Background Color, Data Type, and Line Style. When SQLWindows locates matching text for a window attribute, it displays a field on top of the outline just below the item that has the matching property. You can edit this field like other outline items. SQLWindows updates the property when you close the field by clicking elsewhere in the outline or by pressing Esc or Enter.
Match Case
Check this if you want the search to depend on the capitalization of the strings in Find What and Change To.
4-8
Edit menu
Find Next
Searches for the next occurrence of the search string.
Change
Replaces the current selection but waits for you to click Find Next before searching for the next occurrence.
Change All
Replaces all occurrences of the search string without prompting.
Properties
If an object is selected in the tree view or a layout window, displays the Attribute Inspector for the object. If the top-most item is selected in the tree view, displays a tabbed dialog where you can view statistics and specify runtime settings for the application.
Statistics tab
This tab contains information about resource use and application components.
Most items in the Statistics dialog are self-explanatory. Outline Space. SQLWindows uses a 64-kilobyte directory table to organize and locate parts of the outline. Outline Space is the percentage of space available in this directory table.
4-9
Chapter 4
SQLWindows Menus
Runtime tab
Reject Multiple Window Instances. When you turn on this option, you get an error at runtime when the application tries to create a second instance of a form window, table window, dialog box, or MDI window. If the application never creates more than one instance of a window, you do not need to use window handles in references; an object-qualified reference is always enough. However, the design of some applications requires multiple instances of a window. Enable Runtime Checks of External References. You can turn on this option to generate extra code to ensure that a window handle refers to a window whose type or class is consistent with the SAL statement. For example, when you turn on this option, SQLWindows performs these checks for these expressions: hWnd.frm1.var hWnd.frm1.fun( ) hWnd.cls1.var hWnd.cls1.fun( ) hWnd.cls1..fun( ) hWnd refers to a window whose type is frm1 hWnd refers to a window whose type is frm1 hWnd refers to a window which is an instance of the class named cls1 hWnd refers to a window which is an instance of the class named cls1 hWnd refers to a window which is an instance of the class named cls1 or is an instance of a class derived from cls1
Gupta Technologies LLC recommends that you turn on this option during application development and testing to help find programming errors. This option generates extra
Project menu
code which slightly impacts the performance and size of an application, so turn off runtime checks for production applications (before making an *.EXE). You can enable runtime checks to help diagnose incorrect behavior in production applications. Usually you make an *.EXE with runtime checks enabled only if an application misbehaves. Such an *.EXE causes an error message if there is a programming error that assigns an incorrect value to a window handle. Fully Qualified External References. When you turn on this option, the compiler forces you to qualify all external references. When you turn off this option, when the compiler cannot find a symbol in an unqualified reference using the symbol resolution rules, the compiler silently uses any variable, object, or function with a matching name in any object throughout the application. This means that you must be sure that: You do not misspell a name The application only creates one instance of the containing top-level form
If both of these conditions are not true, then you can get errors at runtime or find that the application misbehaves. These problems are difficult to diagnose. This setting sometimes determines how SQLWindows interprets parent object names, as follows: Reference hWnd.Variable Explanation The compiler always accepts no matter what the setting
Object.Variable The compiler accepts if you make the reference in the object's scope no matter what the setting If you make the reference outside the object's scope, the compiler only accepts it if both of the following are true: Fully Qualified External References is off The objects name is unique
Project menu
Displays these options to work with the application project application. Click an option to display details.
Check Out
Checks the application out of the Team Object Manager Repository. Once you have checked out the application, you can edit it.
Developing with SQLWindows
4-11
Chapter 4
SQLWindows Menus
Check In
Returns the application to the Team Object Manager Repository so that others can access it.
Compile
Compiles the application. While compiling, SQLWindows displays a dialog. Click Cancel to stop the compile.
Next Error
When the compiler error message list is displayed, moves to the next statement that caused an error.
Previous Error
When the compiler error message list is displayed, moves to the previous statement that caused an error.
Execute
Compiles and runs the application. If the application compiles successfully, you can test it. While the application is running, this item is checked. While the application is running, you cannot edit the outline.
Register Server
Places information about the currently open COM server in the system registry. For more, read Registering servers on page 20-27.
Unregister Server
Removes information about the currently open COM server in the system registry. For more, read Registering servers on page 20-27.
Regenerate GUIDs
Displays a dialog where you select the GUIDs you want to regenerate for a COM server. For more, read Regenerating GUIDs on page 20-28.
Project menu
Build Settings
Displays a tabbed dialog where you set specify information about what to build.
Target Type
Choose the type of build: Executable. A double-clickable version of the application in an *.EXE file. An *.EXE file does not contain source code and you cannot edit it. Dynalib. A compiled Gupta SQLWindows module with functions and objects that other applications can dynamically load at runtime. For more, read Dynamically linked libraries (dynalibs) on page 18-6. Include Library. A collection of Gupta SQLWindows objects such as form windows, dialog boxes, or class definitions that can be shared by more than one application. For more, read Include libraries on page 18-2. Local COM Server (EXE). A COM server that runs in a separate address space than its clients. For more, read Local servers, in-process servers, and MTS servers on page 20-16. In-proc COM Server (DLL). A COM server that runs in the same address space as its clients. For more, read Local servers, in-process servers, and MTS servers on page 20-16.
4-13
Chapter 4
SQLWindows Menus
MTS COM Server (DLL). A COM server that runs in the MTS environment. For more, read Local servers, in-process servers, and MTS servers on page 20-16.
Target Name
Specify the name and path of what you are building. Click the ellipsis push button to navigate to the file.
Target Icon
You can select the icon that a user double-clicks to start the application. Click the ellipsis push button to navigate to the file.
Enable Playback
Check this to enable playback mode for COM servers. For more, read Debugging COM servers on page 20-25.
Optimization
To optimize memory usage of binaries (EXEs and DLLs) built with SQLWindows, the runtime environment manages a cache of loaded outline segments. The cache management can reduce the in-memory footprint of SQLWindows binaries by unloading segments not in use, reloading them as necessary when the running application refers to their contents. By default, the runtime tries to limit the cache to 50-60 percent of the total outline segments. This characteristic of the runtime may affect an applications performance, with the decrease in memory use causing a corresponding decrease in performance. To control the trade-off between execution speed and memory use, you can change this setting:
Setting Description Restrict the applications outline segments which are in memory to 50-60 percent of the total outline segments. Restrict the applications outline segments which are in memory to 25-30 percent of the total outline segments. Allow all outline segments to be loaded.
Default Optimize for memory Optimize for performance 4-14 Developing with SQLWindows
Project menu
You must have installed the Object Compiler to see this tab.
DLL Name
Specify the path and name of the output DLL. Click the ellipsis push button to navigate to the file.
Source Name
The path and name of the output application that contains external function definitions for each function in the DLL. This field is not editable.
4-15
Chapter 4
SQLWindows Menus
Default Entries
Aside from the entries below, SQLWindows automatically adds these entries to the version resource: FILEFLAGS FILEOS FILETYPE FILESUBTYPE 0x00L VOS_WINDOWS32 VFT_APP (for EXEs) or VFT_DLL (for DLLs) VFT_UNKNOWN
FILEFLAGSMASK 0x3FL
Product Name
The name of the product with which the file is distributed.
Company Name
The organization that produced the file.
File Version
The version number of the file. For example, 3.10 or 5.00.RC2.
Product Version
The version of the product with which the file is distributed.
Project menu
Internal Name
The internal name of the file, if one exists. If the file has no internal name, this string should be the original filename, without an extension.
Original Filename
The original name of the file, not including a path. This information enables an application to determine if a file has been renamed by a user.
Language
The locale. For example, English (New Zealand).
Encoding
The code page, which is an internal table that the operating system uses to map symbols (letters, numbers, and punctuation characters) to a character number. Different code pages provide support for the character sets used in different countries. For example: Unicode.
Legal Copyright
All copyright notices that apply to the file. This should include the full text of all notices, legal symbols, copyright dates, and so on.
Legal Trademarks
All trademarks that apply to the file.
Custom
Click this to display a dialog where you can add your own named string values to the version resource.
4-17
Chapter 4
SQLWindows Menus
To add a custom string, enter the name and value in the fields at the bottom of the dialog and click New. To change an existing custom string, select it in the list, change either or both values in the fields at the bottom of the dialog, and click Update. To delete a custom string, select it in the list and click Delete.
Threading Model
None. The application has one apartment and one thread. Single Threaded Apartment. The application has the number of single threaded apartments that you specify in Thread Count. Thread Settings. Displays a dialog where you set the threading model.
Multi-Use Server
If checked, a single server process handles multiple clients; if not checked, a separate server process is created for each client.
Helpfile Name
Sets the helpfile attribute of the type library of the server.
Project menu
Type Information
Version Major. Sets the major version number of the type library. This must be an integer in the range 0-65,535. Version Minor. Sets the minor version number of the type library. This must be an integer in the range 0-65,535. GUID. The globally unique identifier of the type library. New. Click this to automatically generate a new GUID. As you refine the design of a server, you may want to associate a new GUID to its type library.
Click the Y or N letter to associate or disassociate a CoClass with a thread number. Thread Model. The type of threading:
Setting Fixed Description Associate each CoClass with a specific thread. If you select this, the list in the dialog contains the names of CoClasses in the application. You can then associate each CoClass to a distinct thread by clicking the N in the column for the thread number. Each object is created in its own thread even if the client is single threaded.
4-19
Chapter 4
SQLWindows Menus
Build
Creates an executable, dynalib, include library, or COM server as specified in the Build Settings dialog. Click Settings to go to the Build Settings dialog.
Component menu
Displays options for the various SQLWindows components.
New
Displays a submenu where you can select an item to add to the application. The items in the cascading menu depend on what is selected in the tree view or tab view.
Wizards
Lets you create items using SQLWindows wizards which guide you through dialogs.
QuickObject Editor
Lets you associate a dialog with a class. The dialog is invoked at designtime on objects of the class, usually to set properties that are used at runtime.
Menu Editor
You build menus graphically with this dialog. For more, read Menu Editor on page 610.
Go To Item
Starts a new instance of SQLWindows and opens the include library that contains the selected included item. You can then edit the included item. When you save and close this instance of SQLWindows, the first instance of SQLWindows resumes. Unless you uncheck Refresh When Changed in Tools, Preferences (Preferences on page 4-32), SQLWindows detects that one of the included items has changed and automatically re-includes the changed include library. When you edit an included item in an include library, the target item is selected in the include library. For more, read Include libraries on page 18-2.
Layout menu
Refresh Libraries
Re-includes all libraries. Choose Refresh to include a recently-changed include library without closing the current application (such as when another person changes an include library on a file server). For more, read Include libraries on page 18-2.
Merge Libraries
Permanently merges all libraries with the open application. Once merged, the items are a fixed part of the application. Merging removes the information that relates the included items to their original libraries. Gupta SQLWindows displays a warning dialog before completing the merge. For more, read Include libraries on page 18-2.
Large Icons
Sets the type of view in the Components tab to large icons.
Small Icons
Sets the type of view in the Components tab to small icons.
List
Sets the type of view in the Components tab to a list.
Details
Sets the type of view in the Components tab to show details.
Layout menu
Displays these menu options to work with the code outline layout. Click an option to display details.
Preview Window
When a top-level window is selected in the tree or tab view, select this to display the window as it will appear to the user. The window floats free of SQLWindows's window. The windows menu will be visible and you can set the runtime position of the window. You can add, move, and remove child objects and use the Controls palette as you do in the Layout tab.
4-21
Chapter 4
SQLWindows Menus
While in preview you can select a different tab in the tab view. For example, you can display a top-level window in preview mode and then change the tab view to display the outline. While in preview mode, the focus in the Outline tab follows what is selected in the top-level window and vice versa. For example, if you are displaying a form window in preview mode and you click a push button on the form window, it is selected in the outline. If you select a push button in the outline, it is selected in the form window. This is true for the application view from which you launched preview mode. You cannot display a given window in preview mode more than once. While in preview mode you can navigate the window's subtree in the tree view. However, the tree view is not synchronized with the preview window. If you navigate outside the window's subtree, you exit preview mode. A preview window is associated with its launching view. That is, if you navigate outside window's subtree in the tree view of the launching view, you exit preview mode. However, in a view not associated with the preview window, you can navigate outside the window's subtree and remain in preview mode. To view more than one window in preview mode, open an additional view of the application by right clicking in the tree view and select Open View from the menu. While in preview mode, the Layout tab in the tab view is disabled.
Bring To Front
Brings the currently-selected objects to the top layer. If an object is under the top layer, it is not visible and you cannot select it. Select the object on top and choose Send to Back.
Send To Back
Sends the currently-selected objects to the back.
Align to Grid
Aligns the selected items with the nearest grid lines. You can align multiple items or a single item.
Align Edges
Aligns selected objects uses these menu options. Note: You must select at least two objects before this menu item is enabled. Click an option to display details.
Layout menu
Important: When you select multiple objects, the first object selected has darker handles than the others. All operations applied to a selection of objects are relative to the first selected object.
In this example, the developer selected the top data field first
Left
Aligns all selected objects with the left-hand edge of the first selected object.
Right
Aligns all selected objects with the right-hand edge of the first selected object.
Top
Aligns all selected objects with the top edge of the first selected object.
Bottom
Aligns all selected objects with the bottom edge of the first selected object.
Vertical Center
Aligns all selected objects with the vertical center of the first selected object.
Horizontal Center
Aligns all selected objects with the horizontal center of the first selected object.
Space Evenly
Evenly spaces selected objects using these menu options. Across Down
You must select at least two objects before this menu item is enabled.
Across
Evenly spaces objects horizontally.
Down
Evenly spaces objects vertically.
4-23
Chapter 4
SQLWindows Menus
Important: When you select multiple objects, the first one selected has darker handles than the others. All operations applied to a selection are relative to the first selected object.
Width
Makes all selected objects the same width as the first selected object.
Height
Makes all selected objects the same height as the first selected object.
Both
Makes all selected objects the same width and height as the first selected object.
Grid
Hides or shows the grid dots in top-level windows and toolbars.
Layout menu
Tab Order
Displays a dialog where you can change the tab sequence for objects on a form window or dialog. The tab sequence defaults to the order in which objects appear on the outline.
The tab sequence value is from 1 to the number of objects in the window which are editable or can receive the focus. The objects in the window display a number that shows their current tab sequence and the Tab Order dialog displays the tab sequence to assign to the next object that you select. To assign tab order: 1. Click the Up (increment) and Down (decrement) arrows in the Tab Order dialog to select a tab sequence. Position the mouse pointer (shown at the left) on the object to which you want to assign that tab sequence to and press the left mouse button. The object is assigned the tab sequence displayed in the Tab Order dialog.
2.
Click Reset to set the objects' tab sequences to their original values. To save changes and close the Tab Order dialog, click Close.
Chapter 4
SQLWindows Menus
For String and Long String data types, SQLWindows formats the sample data using the input mask if there is one
Debug menu
Displays menu options to debug the application. For more, read Chapter 10, Debugging.
Stop
Stop execution of the application and returns you to SQLWindows.
Continue
Resumes execution after it has suspended at a breakpoint
Break
Suspends execution.
Step Into
Executes the next statement and returns control to SQLWindows. If the application calls a function, SQLWindows takes you to the function and you can step through the function a statement at a time before returning to the statement after the function call. If the selected item is a call to an internal function, SQLWindows takes you to the first line but does not execute it. If the item is a call to an external function, SQLWindows behaves the same way as Debug, Step Over.
Step Over
Executes the next statement and returns control to SQLWindows. If the application calls a function, SQLWindows executes all the function's statements in one step and stops at the statement after the function call.
Debug menu
Breakpoints
Displays these options to work with the breakpoints.
Toggle
If the selected statement is not a breakpoint, selecting this makes it one. If the selected statement is a breakpoint, selecting this makes it a normal statement. Execution suspends before executing the statement. When you run the application, SQLWindows stops at each breakpoint and displays the Debug toolbar.
Clear All
Permanently removes all breakpoints in the application.
Disable All
Temporarily removes all breakpoints in the application.
Enable All
Restores all breakpoints in the application.
No Animate
Stops Fast Animate or Slow Animate. No Animate is the default. A check mark means that animation is not on.
Slow Animate
Highlights each item as it executes, but at a slower speed than Fast Animate. A check mark means that Slow Animate is on. You set the time interval between the execution of each item with Tools, Preferences.
Fast Animate
Highlights each item as it executes. A check mark means that Fast Animate is on.
Playback
Lets you debug a COM server application in the same way as a desktop application. For more, read Debugging COM servers on page 20-25.
Playback Rewind
Lets you debug a COM server application in the same way as a desktop application. For more, read Debugging COM servers on page 20-25.
4-27
Chapter 4
SQLWindows Menus
Tools menu
Displays these options for displaying the tools available in Gupta.
User Tools
Displays a dialog where you edit the items that appear in the group at the bottom of the Tools menu and in the Tools toolbar.
Tools
The current items in the Tools toolbar.
Command
The program name.
Tools menu
Browse
Click this to select the program using the standard File Open dialog.
Parameters
Command line arguments to pass to the program each time it starts.
$MarkedItem
Working Directory
The name of the directory that contains files that the program uses.
Menu Text
The name that appears in the Tools menu. Use an ampersand (&) for the mnemonic.
Tool Tip
The text that appears when the mouse pointer pauses over the programs button in the Tools toolbar.
Available Icons
The icon to use for the programs button in the Tools toolbar.
4-29
Chapter 4
SQLWindows Menus
Toolbars
Toolbars tab
Displays a dialog where you select the toolbars that you want to display.
Toolbar. Check a toolbar in the list to display it. Uncheck a toolbar to hide it. Show Tooltips. If checked, SQLWindows displays a small popup window that contains a single line of text that describes a button when the cursor is over it. Cool Look. If checked, buttons are displayed with flat appearance; if not checked, buttons are displayed with a three-dimensional appearance.
Cool look
Traditional look Large Buttons. If checked, buttons are displayed larger than the default size.
Tools menu
Tools tab
You create custom toolbars in this tab.
4-31
Chapter 4
SQLWindows Menus
Preferences
Displays a tabbed dialog with items that you use to customize SQLWindows environment. To see the effect of changing a setting without closing the dialog, click Apply.
Slow Animate Interval (In Seconds). The speed of Slow Animate in seconds. Maximum Compile Errors. SQLWindows continues to compile an application when finds an error. However, you can set the maximum number of errors at which SQLWindows will stop compiling. The default is 100.
Tools menu
Split Horizontally. Turn this on to display Coding Assistant's Add Same Level and Add Next Level lists stacked one on top of the other. Split Vertically.
Developing with SQLWindows
4-33
Chapter 4
SQLWindows Menus
Turn this on to display Coding Assistant's Add Same Level and Add Next Level lists side by side.
Cell Width and Cell Height. The units for the granularity are based on the character size of the font selected for the form window or dialog: 1 width unit = 1/2 character width
Tools menu
The default granularity is 2 for the width and 2 for the height. Visible. Check this to display a grid pattern in layout windows. When not checked, SQLWindows does not display the grid pattern in layout windows, but the grid can still be active. By default, the grid is visible. Active. Check this to align (snap) items automatically to the grid when you draw, move, or resize in a layout window. When not checked, you can change the size and location of the items independent of the grid. By default, the grid is active.
Templates. The directory where SQLWindows looks for templates to use as starting points for new applications. ActiveX Libraries. The directory where SQLWindows stores ActiveX include libraries.
4-35
Chapter 4
SQLWindows Menus
SQLWindows stores both the Application Path and the Global Path in the application.
Important: Gupta Technologies recommends that you specify relative paths.
This group specifies whether you want to use Active Coding Assistant, and which features you want to use. Enable. If unchecked, the Active Coding Assistant background process does not run at all. If checked, the process runs, subject to additional preferences listed below. For an explanation of the various features, see Active Coding Assistant on page 2-20 Quick Info. If checked, the Quick Info feature is active during editing sessions. List members. If checked, the List Members feature is active during editing sessions. Parameter Info. If checked, the Parameter Info feature is active during editing sessions. Complete Word. If checked, the Complete Word feature is active during editing sessions.
Tools menu
when certain conditions in the editing session are met. The preferences in the Automatic group control whether you allow such automatic actions to occur. Quick Info. If checked, the Quick Info feature can start automatically. List members. If checked, the List Members feature can start automatically. Parameter Info. If checked, the Parameter Info feature can start automatically.
Output
Displays the compiler error message list. When compiling, SQLWindows detects as many errors as possible before stopping. As SQLWindows compiles, it lists each error as it finds them. After the compilation completes, you can: Single-click an error message to select the corresponding source item in the outline without closing the error list Double-click an error message to change the focus to the corresponding source item in the outline
SQLWindows compiles until it reaches the maximum number of errors that you set in Tools, Preferences, General. The error list can be a palette or a toolbar. You dock and undock it the same way you dock and undock toolbars. For more, read Docking toolbars, palettes, and the menu bar on page 2-5. To change the width or height of a docked error list, move the mouse pointer to an inner edge and drag after the splitter cursor appears. You can also move from one offending source item to another with Project, Next Error (Next Error on page 4-12) and Project, Previous Error (Previous Error on page 4-12). If you close the compile error message window after an unsuccessful compilation, you can display it again with the messages by selecting Tools, Output. You can send the contents of the output window to an error log. Right-click on the output window, then choose the menu item to save the contents to a file.
Coding Assistant
Displays the Coding Assistant. For more, read Coding Assistant on page 2-18.
4-37
Chapter 4
SQLWindows Menus
Attribute Inspector
Displays the Attribute Inspector. For more, read Attribute Inspector on page 2-17.
Controls
Displays the Controls palette. For more, read Controls palette on page 2-23.
Variables
Displays the names and values of variables at a breakpoint. SQLWindows updates the variable values at each breakpoint. Click the plus/minus button to display the Select Watch Variable dialog where you can choose the variables to monitor. To add a watch variable: 1. Select a section name in the outline from the top list in Select Watch Variables on the left side of the dialog. You can type the first few characters of the name in the data field to scroll to the section that starts with that prefix. SQLWindows displays the variables defined in the selected section in the lower list. Select a variable by double-clicking it or by selecting it and clicking Add. Click Add All to add all the variables in the section. After you make a selection, SQLWindows adds the variables to Current Watch Variables on the right side of the dialog.
2.
To remove a watch variable, double-click it in Current Watch Variables or select it and click Clear. Click Clear All to remove all variables from the list. You can use Edit Watch Variables in the lower right side of the dialog to: Type variable names. Add qualifiers to variable names. Enter expressions to add to the watch variables list. SQLWindows evaluates the expression and displays the result when you display the Watch Variables window. (This is like entering an expression in the Expressions window.)
Click OK to save your selections and return to the Variables window. Click Cancel to return to the Variables window without saving your selections.
Call Stack
Displays the name of the current function (if any) and the name of the function or outline section that called it. For nested calls (where one function has called another function which has called another function, and so on), the Call Stack window shows the complete call path.
Tools menu
Messages
Displays every message sent in an application. Each line displays a message name or number, the handle of the window receiving the message, and the wParam and lParam values. Click SAM messages only to display only SQLWindows messages (SAM_*). The values displayed under the Message heading are SQLWindows message names.
Expressions
Evaluates an expression you type in the dropdown at the top of the window. After typing the expression, either click Evaluate or press Return. You can use this window with Step Into and Step Over to evaluate a variable's value before and after a statement uses or changes the variable's value. This window remembers all the expressions you entered for this instance of SQLWindows. You can select an expression entered earlier in the session by choosing it from the combo box list. You can evaluate any expression that results in a number or string. For example, you can evaluate expressions like these:
SalDateCurrent( ) 2+2
Database Explorer
Starts Database Explorer. While you display Database Explorer, SQLWindows has a Database Explorer menu to the right of the Tools menu. For more, read Database Explorer menu on page 4-40 .
ActiveX Explorer
Starts ActiveX Explorer. You use ActiveX Explorer to display the contents of an ActiveX server type library (*.OLB, *.TLB, *.DLL, *.OCX, *.EXE). For more, read Using ActiveX Explorer on page 19-9. While you display ActiveX Explorer, SQLWindows has an ActiveX Explorer menu to the right of the Tools menu. For more, read ActiveX Explorer menu on page 4-47.
Report Builder
Starts Report Builder.
4-39
Chapter 4
SQLWindows Menus
Diff/Merge
Starts the diff/merge tool which compares files and performs 3-way merges.
SQLTalk
Starts SQLTalk.
Database Explorer lets you work with all the databases you can connect to using a graphical user interface. The tree view of Database Explorer displays your database environment with an expandable/collapsible tree hierarchy. The tab view displays information appropriate to the element you have selected in the tree view.
New
This menu item lets you select these subitems:
Table
Displays the table Definition tab.
Index
Displays the New Index dialog.
Stored Procedure
Displays the New Stored Procedure dialog
Database
Displays the New Database dialog
SQL Script
Use this menu item to select the following subitems:
Execute Command
Executes the SQL command located at the current cursor position.
Execute Script
Executes the specified SQLTalk script.
Cancel Script
Stops a currently executing SQLTalk script or command.
New Script
Clears the command area and allows the entry of new commands. All current cursor connections remain.
Open Script
Allows a file of previously saved set of commands to be loaded.
Save Script
Writes the current command session to a file.
Save Script As
Writes the current command session to a file you specify.
4-41
Chapter 4
SQLWindows Menus
Commit
Commits specified changes to the database.
Rollback
Rolls back the specified (committed) changes to the database. The entire transaction is rolled back when there is a lock time-out. If rollback is OFF, only the current command is rolled back when there is a lock time-out. The default is ON.
Options
These options are available: Execute. Displays the Script Execution Settings dialog. Connections. Displays the Connections Settings dialog. Sessions. Displays the Session Settings dialog. Verbose Messages. Toggle to receive more detailed error messages. Show Execution Time. Toggle command time on to display the time elapsed to obtain the results of a given SQL command. Command time resolution is 0.01 seconds. Execution times below this resolution will be reported as 0.01 seconds. Split Vertically. Changes the split of the screen to and from horizontal and vertical orientation. (Note that while the output portion of the main SQLTalk Script screen cannot be edited, you can use the clipboard to copy portions of the output information.
SQLTalk Output
Writes current output to a file or printer you specify.
Table
This menu item lets you select these subitems:
Define Filter
Displays the Define Table Filter property pages: Conditions, Sort, and SQL. Use Define Filter to limit the amount of data being viewed or to rearrange the data into a sorted order.
Copy SQL
Copies the SQL statement to the clipboard. The SQL statement that is copied is the one used to populate the table: SELECT with all the column names.
New Row
Adds a new row to the table.
Clear Row
Marks the selected row(s) in the table for deletion.
Switch Set
This command is activated after you select New Row or Paste and allows you to switch back and forth between the top and bottom window panes in the right-hand side of the window. This menu item is disabled after you use Apply Edits or Discard Edits.
Apply Edits
Applies all the changes you made to the table to the database and refreshes the table. Apply Edits is enabled after you make a change to the data in the table (update a row, delete a row, or insert a new row).
Discard Edits
Discards all the changes you made to your table since the last time you clicked Apply Edits and refreshes the table. All table information is restored to its previous state. It does not reverse changes that you have already applied to the database with Apply Edits. This command is enabled when you have made a change to the data in the table.
Refresh
Refreshes the table by retrieving the new result set. If you have been away from your computer, select this command to see if any one else has updated the table or if you need to apply any edits. If you select this command and have not applied your edits yet, you are prompted to do so.
Stored Procedure
This menu item lets you select these subitems:
Compile
Compiles a SQLBase or Oracle stored procedure.
4-43
Chapter 4
SQLWindows Menus
Query
Use this menu item to select the following subitems:
Define Query
Use this menu option to access the property pages to the query you are currently defining. These property pages allow you to graphically edit the SQL SELECT statement used in the query.
Copy SQL
Copies the querys SQL statement to the clipboard.
New Query
Use this menu option to create a new query using the Query property pages. If you select this, you lose the current query.
Open Query
Opens a query that you previously saved.
Save Query
Saves the current query to a file. The first time you select this, you are asked to name the file and directory in which to store the query.
Save Query As
Saves query with another name in a directory you select.
First Page
Goes to the first page of the report containing the results of the query.
Next Page
Goes to the next page of the report containing the results of the query.
Previous Page
Goes to the previous page of the report containing the results of the query.
Last Page
Goes to the last page of the report containing the results of the query.
Go to Page
Goes to the specified page of the report containing the results of the query.
Save Pages As
Saves the specified pages of the report containing the results of the query as an RTF file. You are asked to specify the name of the file and the directory in which it is to be located.
Format
This menu item lets you select the following items to format: Report. Displays the Format Report dialog box to determine how to print the report. Input. This menu item lets you select the following subitems: Variables Totals Crosstabs Displays the Format Variables dialog box. Displays the Format Totals dialog box. Displays the Format Crosstabs dialog box.
Break Groups. Displays the Format Break Groups dialog box. Break Groups are typically used with queries that contain a Group By clause. Block. Displays the Format Block dialog box. A block can be a Report Header, a Page Header, a Detail Block, a Page Footer, or a Report Footer. Line. Displays the Format Line dialog box. Fields. Displays the Format Fields dialog box. Background Text. Displays the Format Background Text dialog box. You can control character fonts, position of the text, justification, borders, tab stops, colors. Box. Displays the Format Box dialog box. Picture. Displays the Format Picture dialog box. Graph. Displays the Format Graph dialog box. Borders. Displays the Format Border dialog box. Tabs. Displays the Format Tab Settings dialog box.
4-45
Chapter 4
SQLWindows Menus
Colors. Displays the Format Text Colors dialog box. This dialog controls background, border, and text colors. Link Fields. Physically links the selected fields on a line together for the current report. Unlink Fields. Unlinks the selected fields from their associated fields in the report template. Align Left Sides. Align the left sides of the selected design elements of the report. Align Centers. Align the centers of the selected design elements of the report. Align Right Sides. Align the right sides of the selected design elements of the report. Align to Grid. Align the design elements of the report to the grid. Grid On. Toggles the design grid on and off.
Print
Prints the report.
Report Design
Switches to design mode. In design mode you can change how the report look.
Report Preview
Switches to preview mode. In preview mode you can see how the current design of the report looks.
Show as Report
Display the results of the query as a report.
Show as Table
Display the results of the query as a table.
Add to List
Displays the Add To List dialog. Use this dialog to add or remove the names of remote SQLBase or DB2 servers. You also use this dialog to add to or remove from the Database Explorer tree (tree view) a remote SQLBase database.
Disconnect
Disconnect from the database you have selected in the Explorer (left) pane. You can also select any of the nested nodes underneath that database, then select the Disconnect menu item.
Open Library
Displays the ActiveX Explorer open type library dialog.
Library Help
Displays the help file for the open type library.
Generation Option
Sets the options for generating an *.APL.
Refresh
Regenerates the *.APL for the open type library.
Include APL
Includes the *.APL for the open type library in the outline.
4-47
Chapter 4
SQLWindows Menus
Show CoClasses
Shows or hides CoClasses in the open type library.
Show Interfaces
Shows or hides interfaces in the open type library.
Show Events
Shows or hides events in the open type library.
Show Enumerations
Shows or hides enums in the open type library.
Show Functions
Shows or hides functions in the open type library.
Window menu
You can have these Windows options to resize the Gupta application window.
Cascade
Displays the MDI Windows layered on top of each other so that only their title bars are visible except the top-most view. If any MDI windows are minimized, their icons are under the open outline views.
Tile Horizontally
Displays all MDI Windows one above another. If any windows are minimized, their icons are under the open outline views.
Help menu
Tile Vertically
Displays the MDI Windows side by side. If any outline views are minimized, their icons are under the open outline views.
Close All
Closes all windows except the main window
Help menu
Help Topics
Displays the main topic list. Double-click a topic to select it.
Functions
Displays help for system functions.
Messages
Displays help for messages.
QuickObjects
Displays help for QuickObjects.
Visual Toolchest
Displays help for Visual Toolchest.
Books Online
Opens the Gupta Books Online collection. The Gupta Books Online collection was created using Adobe Acrobat and lets you perform full-text searches across the entire document suite, navigate the table of contents using the expandable/collapsible browser, or print any chapter.
4-49
Chapter 4
SQLWindows Menus
About SQLWindows
Displays the version number of SQLWindows.
Chapter 5
SQLWindows Objects
This chapter: Describes most of the objects that you can add to an application Explains the attributes for each object
5-1
Chapter 5
SQLWindows Objects
Adding objects
You add objects with the Controls palette (page 2-23), the New menu (page 2-14), and the Coding Assistant (page 2-18). To add a new object: Click the right mouse button and select New OR Click a push button in the Controls palette, move the mouse pointer over a top-level window, and then click OR Cut, copy, paste, and duplicate existing objects OR Type an object's definition directly into the outline OR Double-click an object in the Coding Assistant
5-2
Adding objects
5-3
Chapter 5
SQLWindows Objects
Attributes
You use the Attribute Inspector to set properties of an object. For more, read Editing object attributes on page 2-16.
Types of objects
There are two types of objects: Top-level Child
5-4
Top-level objects
Top-level objects
There are three top-level objects: Form window Table window Dialog box
These objects are called top level because of their position in the outline. An application contains at least one of these objects.
Important: Table windows can be either top-level objects or child objects.
All top-level objects have: A border and a title bar A system menu
All top-level objects (except for dialog boxes) can: Have a menu (the next chapter explains menus). Have minimize and maximize push buttons. Be created automatically when the application starts or created dynamically by the application on demand. Dialog boxes are only created dynamically on demand. Have an initial state (normal, minimized, or maximized). Have an icon that is displayed when the window is minimized. Be resizable at runtime.
5-5
Chapter 5
SQLWindows Objects
In the outline, all top-level objects have: A Contents section where you add child windows A Message Actions section A Window Variables section A Functions section
MDI windows
MDI windows are in the top level of the outline, but they are different from top-level windows. You can place a form window or a top-level table window in the contents section of an MDI window.
Form window
Form windows are used to enter and display data. You can place child windows such as data fields, push buttons, and background text on a form window.
A form window with a toolbar, menus, data fields, and background text
5-6
Form window
If Yes (default), the window is created and displayed at application startup. If No, you must call SalCreateWindow to create the window. If Yes (default), the form window has a maximize button in the upper right corner. If No, the form window does not have a maximize button and the user cannot maximize the form window. If Yes (default), the form window has a minimize button in the upper right corner. If No, the form window does not have a minimize button and the user cannot minimize the form window. If Yes (default), the form window has a system menu.
Minimizable
System Menu
5-7
Chapter 5
SQLWindows Objects
Property Resizable Initial State Icon File Form Pages Location and Size Background Color Text Color Font Name Font Size Font Enhancement Allow child docking Docking orientation
Description If Yes (default), the user can resize the form window using sizing pointers. The window's state when created: Maximized, Minimized, or Normal (default). A file that contains an icon used when the form window is minimized. The icon file must be in *.ICO format. Displays a cascading menu where you can set the page dimensions and number of pages to use when printing the form window with SalPrtPrintForm. Displays a cascading menu with the form window's position (top and left) and size (width and height). The background color of the form window. The color of text in the form window. The font of text in the form window. The font size of text in the form window. The font enhancement of text in the form window. Set this property to Yes if you want this top-level window to allow docked windows.. Default value is No. This property is enabled only if the Allow child docking property is set to Yes. This property controls which directions can a child window dock itself to this top-level window.
5-8
Dialog box
Dialog box
You can use dialog boxes to let the user enter data, or to display warning or error messages. You can place child windows such as data fields, push buttons, and background text in a dialog box.
A dialog box is like a form window, but it cannot be resized at runtime, it does not have a menu, and it does not have minimize and maximize push buttons. Also, you cannot create a dialog box automatically when the application starts. You must call SalCreateWindow or SalModalDialog to create a dialog box. There are three types of dialog boxes: modeless, modal, and system modal.
Modeless
A modeless dialog box does not suspend application processing. The user can switch from the dialog box to another window in the application or to a window in a different application. You create a modeless dialog box with SalCreateWindow and close it with SalDestroyWindow.
Modal
A modal (also called application modal) dialog box suspends application processing until the user closes the dialog box. The user cannot switch from the dialog box to another window in the application. However, the user can switch to a window in a different application.
5-9
Chapter 5
SQLWindows Objects
You create a modal dialog box with SalModalDialog and close it with SalEndDialog.
System modal
A system modal dialog box suspends processing of the entire system until the user closes the dialog box. The user cannot switch between the dialog box and another window in the application or to a window in a different application. You create a system modal dialog box with SalModalDialog and close it with SalEndDialog.
Message boxes
If the application only needs to display a simple message or needs simple input from the user, you can call SalMessageBox to display a message box. For more about SalMessageBox, read the SQLWindows Function Reference or the online help.
Table window
Description By default, the toolbar is docked at the top of the client area. Other choices are Left, Right, and Bottom. If Yes, a portion of the bottom of the client area of the window is used to display the status bar. You may also select No. The visual appearance of child objects in the dialog box: Default Uses the setting in the Window Defaults section of Global Declarations (standard or etched) Child objects appear three-dimensional
Standard Child objects appear two-dimensional Etched Type of Dialog Location and Size
The type of dialog box: Modal (default), Modeless, or System modal. Displays a cascading menu with the dialog box's position (top and left) and size (width and height). If you check Absolute Screen Location, the position of the dialog box is relative to the upper left corner of the screen. If you do not check Absolute Screen Location, the position of the dialog box is relative to the owner of the dialog box (you specify the owner in SalModalDialog or SalCreateWindow). If not checked and the dialog box does not have an owner, the position of the dialog box is absolute (as it is if checked).
Background Color Text Color Font Name Font Size Font Enhancement Allow dock to parent
The background color of the dialog box. The color of text in the dialog box. The font of text in the dialog box. The font size of text in the dialog box. The font enhancement of text in the dialog box. (Enabled only for modeless dialog boxes.) Set this property to Yes if you want this dialog box to get docked and undocked. The value of this property can be changed programmatically by a call to SalDlgSetDockStatus. Note: Even if docking is enabled, the initial state of the dialog box will be floating. The application has to call SalDlgSetDockStatus to dock this dialog box. This property is enabled only if Allow dock to parent property is set to Yes. This property controls which directions a dialog can dock itself to the top-level window.
Docking orientation
Table window
Chapter 15 describes table windows.
5-11
Chapter 5
SQLWindows Objects
MDI window
You use an MDI window to create a workspace for an application. You can place form windows and top-level table windows in the workspace. MDI windows are useful for managing a large number of top-level windows that you need to display at the same time. This example has a toolbar and child windows (three table windows):
A form or table window within an MDI window is called an MDI child window. An MDI child window has a title bar, a menu, a sizing border, a system menu, and minimize and maximize push buttons. However, an MDI child window does not have a menu bar. MDI child windows use the menu bar of the MDI window. When an MDI child becomes active, its menu replaces the MDI window's menu. Only one child MDI window is active at a time. An active MDI child has a highlighted title bar and it appears in front of all other MDI child windows. MDI child windows can be minimized and appear at the bottom of the MDI window as an icon. When an MDI child window is maximized, its title bar disappears and it use the MDI window's title bar. MDI means Multiple Document Interface, which is a user interface model created by Microsoft. You can place an MDI window anywhere you can place a top-level window.
MDI window
Minimizable
System Menu Resizable Initial State Icon File Location and Size
5-13
Chapter 5
SQLWindows Objects
Description Set this property to Yes if you want this top-level window to allow docked windows.. Default value is No. This property is enabled only if the Allow child docking property is set to Yes. This property controls which directions can a child window dock itself to this top-level window.
Outline items
An MDI window outline has these items:
MDI Window: <name> Named Menus Menu Toolbar Contents Functions Window Parameters Window Variables Message Actions
Contents
You can put form windows and top-level table windows in the contents section.
Menu
A menu bar in an MDI window is active when there is not an MDI child active that defines its own menu bar. When an MDI child becomes active, its menu bar replaces the MDI window's menu in the MDI window's menu bar.
Toolbar
When an MDI child becomes active, the MDI window continues to display its toolbar if it has one.
MDI window
SAM_Destroy
SQLWindows sends SAM_Destroy to an MDI window and its children in this order: MDI window Form window or table window Form window or table window children and grandchildren (columns) Form window or table window toolbar children and grandchildren MDI window toolbar children and grandchildren
The first parameter is the window handle. The second parameter is a boolean that specifies how to tile the child window: TRUE = tile windows vertically FALSE = tile windows horizontally
SalMDICascade
This function arranges the child windows of an MDI window in a cascading style:
Call SalMDICascade( hWndMyMDI )
5-15
Chapter 5
SQLWindows Objects
SalMDIArrangeIcons
This function arranges the child window icons in an MDI window:
Call SalMDIArrangeIcons( hWndMyMDI )
SalParentWindow
This is how SalParentWindow behaves with MDI windows:
Where called Toolbar child in MDI window Top-level object in an MDI window SalParentWindow parameter hWndItem hWndForm Return Handle of containing MDI window (hWndMDI) Handle of containing MDI window (hWndMDI)
Windows menu
A windows menu is a special type of popup menu that you use in MDI windows and their children. A windows menu automatically lists all the MDI window's child windows without any coding. An end-user can shift the focus to a different MDI child by selecting the child from the menu or by using its accelerator key. You can add your own menu items to a windows menu. An example of a windows menu is shown below:
The developer specified the first four items in the menu in the same way as regular popup menu items. SQLWindows added the last three items and the menu separator automatically. The default title of the popup menu is Windows, but you can change it. This is the code in the outline for the menu:
MDI Window: mdi1 ...
Child windows
Menu ... Windows Menu: &Windows ... Menu Item: &Tile Vertical ... Menu Actions Call SalMDITile( hWndForm, TRUE ) Menu Item: &Tile Horizontal ... Menu Actions Call SalMDITile( hWndForm, FALSE ) Menu Item: &Cascade ... Menu Actions Call SalMDICascade( hWndForm ) Menu Item: &Arrange Icons ... Menu Actions Call SalMDIArrangeIcons( hWndForm )
Child windows
You place child windows in top-level objects. Each top-level object has a Contents section where you add child objects. Child objects are created and destroyed with their parent. The table below lists the objects that you can add to top-level objects.
These top-level objects... Form window Dialog Box Can have these child objects... Background text Group box Frame Line Data field Multiline field Push button Radio button Check box Option button List box Combo box Table window Picture Scroll bar (horizontal and vertical) Custom control
5-17
Chapter 5
SQLWindows Objects
Child objects cannot be parents of other objects, except for child table windows which can have columns as children.
Mnemonics
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, group boxes, and check boxes. You can also use mnemonics with menu items. A mnemonic for a menu item does more than move the input focus; it also invokes the menu item's actions. Create a mnemonic by typing an ampersand character (&) before the character in the object's title that you want to be the mnemonic. A mnemonic character appears in an object's title with an underscore.
The user can press Alt+A instead of clicking to invoke the push button's actions You can give a label (name) to a data field using background text. A background text mnemonic is associated with a data field to move the input focus to that data field. For example, if the background text for the data field dfName is &Name, pressing Alt+N moves the focus to dfName. The background text must come immediately before the data field in the outline; the background text can appear visually anywhere in the form window or dialog box.
Accelerators
An accelerator is a key that invokes the actions for a push button or menu item: You assign an accelerator to a push button using the Attribute Inspector. A cascading menu lists the keys that you can assign. You assign an accelerator to a menu item in the Keyboard Accelerator section of the outline. Coding Assistant lists the keys that you can assign.
Background text
Background text
You use background text for titles, labels, and instructions.
Background text for a data field At designtime, you can edit background text by pressing the Shift key and clicking the right mouse button. You can give a label (name) to a data field using background text. A background text mnemonic is associated with a data field to move the input focus to that data field. For example, if the background text for the data field dfName is &Name, pressing Alt+N moves the focus to dfName. The background text must come immediately before the data field in the outline; the background text can appear visually anywhere in the form window or dialog box.
5-19
Chapter 5
SQLWindows Objects
Group box
You use a group box to label a set of related objects such as radio buttons.
A group box around radio buttons At designtime, you can edit the title of a group box by pressing the Shift key and clicking the right mouse button.
Frame
Property Text Color Font Name Font Size Font Enhancement The color of the group box text. The font of the group box text. The font size of the group box text.
Description
Frame
A frame is a border that surrounds an object. A frame is visual only; it does not receive mouse or keyboard input and it does not have a message actions section.
Frame attributes
The table below describes the attributes for a frame.
Property Visible Location and Size Corners Border Style Border Thickness Background Color Description If Yes (default), the frame is visible at runtime. If No, the frame is not visible at runtime. Displays a cascading menu with the frame's position (top and left) and size (width and height). The corner shape of the frame (square or round). The default is square. The border style of the frame (no border, solid, drop-shadow, raised-shadow, etched). The default is solid. The thickness of the border. The default is 1. The background color of the frame.
5-21
Chapter 5
SQLWindows Objects
Description
Line
You can draw a line on a form window or dialog box at any angle. A line is visual only; it does not receive mouse or keyboard input and it does not have a message actions section.
Line attributes
The table below describes the attributes for a line.
Property Visible Coordinates Line Style Line Thickness Line Color Description If Yes (default), the line is visible at runtime. If No, the line is not visible at runtime. The X and Y coordinates of the start and end of the line. The visual appearance of the line (solid or etched). The thickness of the line. The default is 1. The color of the line.
Data field
Data field
A data field displays output or accepts input.
A data field with background text You can give a label (name) to a data field using background text. A background text mnemonic is associated with a data field to move the input focus to that data field. For example, if the background text for the data field dfName is &Name, pressing Alt+N moves the focus to dfName. The background text must come immediately before the data field in the outline; the background text can appear visually anywhere in the form window or dialog box. A non-editable data field only receives SAM_Create, SAM_Destroy, and SAM_Timer.
5-23
Chapter 5
SQLWindows Objects
Description The length of the data field. The default is 100. The maximum length of a String or Long String data type is 32 kilobytes. Important: The value that you specify in Max Data Length is the maximum capacity of the object, not the number of bytes that SQLWindows allocates for the objects value. At runtime, SQLWindows allocates the number of bytes in the actual value of the object at any one time. Also, when you set a variable or another object with the value, SQLWindows only copies the number of bytes in the actual value, not the number of bytes in the Max Data Length setting of the source object.
Editable
If Yes (default), the user can enter or edit text in the data field. If No, the user cannot enter or edit text. At runtime, you can change the setting of this property with SalEnableWindow and SalDisableWindow.
Border Justify Format Input Mask Country Background Color Text Color Font Name Font Size Font Enhancement
If Yes (default), the data field has a border. If No, the data field does not have a border. The justification for the data field. The default is left. The output format of the data field. The default is unformatted. For more, read Chapter 11, Formatting and Validating. Input validation criteria for the data field. For more, read Chapter 11, Formatting and Validating. The country profile for the data field. For more, read Chapter 11, Formatting and Validating. The background color of the data field. The color of text in the data field. The font of text in the data field. The font size of text in the data field. The font enhancement of text in the data field.
Multiline field
Multiline field
A multiline field accepts and displays multiple lines of data.
A multiline field with background text The user can press Enter or Ctrl+Enter to move the cursor to the next line when entering or editing text in a multiline field.
The length of the multiline field. The default is 1000. The maximum length of a String or Long String data type is 32 kilobytes. Important: The value that you specify in Max Data Length is the maximum capacity of the object, not the number of bytes that SQLWindows allocates for the objects value. At runtime, SQLWindows allocates the number of bytes in the actual value of the object at any one time. Also, when you set a variable or another object with the value, SQLWindows only copies the number of bytes in the actual value, not the number of bytes in the Max Data Length setting of the source object.
5-25
Chapter 5
SQLWindows Objects
Property Editable
Description If Yes (default) the user can enter or edit text in the multiline field. If No, the user cannot enter or edit text in the multiline field. At runtime, you can change the setting of this property with SalEnableWindow and SalDisableWindow.
Border Word Wrap Vertical Scroll Background Color Text Color Font Name Font Size Font Enhancement
If Yes (default), the multiline field has a border. If Yes, the text in the multiline field wraps. The default is no. If Yes (default), the multiline field has a vertical scroll bar on the right side. The background color of the multiline field. The color of text in the multiline field. The font of text in the multiline field. The font size of text in the multiline field. The font enhancement of text in the multiline field.
Push button
When the user clicks a push button, the application performs an action.
At designtime in a Layout tab or a Preview window you can edit the title of a push button by pressing the Shift key and clicking the right mouse button.
Push button
Description The title of the push button. Create a mnemonic by putting an ampersand (&) before the letter that you want to be the mnemonic. If Yes (default), the push button is visible at runtime. If No, the push button is not visible at runtime. At runtime, you can change the setting of this property with SalHideWindow and SalShowWindow.
Displays a cascading menu with the push button's position (top and left) and size (width and height). Whether the object is single image or multiple image. For more, read Images in push buttons on page 5-28. Displays a cascading menu where you enter a description, specify the name of the file that contains an image, and set the image style (single or multiple). Center: The default, and the behavior of pushbutton images in earlier versions of SQLWindows. The image is centered left to right and top to bottom. Any text appears centered left to right and below the image. With Text, the image is centered top to bottom excluding the area used by the text. Left: The image occupies the left third of the button. Any text appears to the right of the image, is left justified, and occupies the middle and right third of the push button. Right: The image occupies the right third of the button. Any text appears to the left of the image, is right justified, and occupies the middle and left third of the Push Button.
Determines whether the image will be resized when its associated button is resized. None: This is the default value. No image scaling occurs. Size to Fit: Stretches or shrinks the image to fit in the available space. Size for Best Fit: Sizes the image to fit either the width or height of the available space.
Displays a palette where you select a color in the image that you want to replace with the background color of the option button. This makes parts of the image transparent. This applies to bitmaps only (*.BMP). The default is None. At runtime, you can call SalColorGet and SalColorSet to get or set the transparent color of the bitmap. COLOR_IndexTransparent identifies the color. To clear the transparent color, pass COLOR_None to SalColorSet.
The accelerator that activates the push button. None is the default. The table below lists the keyboard accelerators. Displays a palette where you can set the color of the background (the area of the push button not covered by an image). The color of text in the push button title.
5-27
Chapter 5
SQLWindows Objects
Property Font Name Font Size Font Enhancement Appearance The font of text for the push button.
Description
The font size of text for the push button. The font enhancement of text for the push button. The appearance of the borders around the button. Choices are Standard (relief-style borders) or Flat (no borders). Default is Standard.
Accelerators
Function keys F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12 Other keys Enter, Esc
Push button
SalDisableWindow). This gives the bitmap a tin foil look. For a different disabled appearance, use a multiple-image bitmap.
A multiple-image file must be a bitmap (*.BMP). Arrange the 3 images vertically in the bitmap. In each image, use the same width and the same height.
3. 4.
5-29
Chapter 5
SQLWindows Objects
Radio button
When the user clicks a radio button, it turns an option on or off. You use a group of radio buttons for mutually exclusive options. Only one radio button in a group can be on at a time. When the user clicks a radio button in the group, the others are turned off. When a group of radio buttons is contiguous, but processed as two different groups, you must use a group box.
Radio buttons in a group box The user can press Tab to move to a checked radio button in a group and then use the arrow keys to move the input focus to another radio button in the group.
Option button
Description The font size of text for the radio button. The font enhancement of text in the radio button.
Option button
Option buttons are rectangular buttons that display an image and text on a window, toolbar, or palette.
5-31
Chapter 5
SQLWindows Objects
Description Displays a palette where you select a color in the image that you want to replace with the background color of the option button. This makes parts of the image transparent. This applies to bitmaps only (*.BMP). The default is None. At runtime, you can call SalColorGet and SalColorSet to get or set the transparent color of the bitmap. COLOR_IndexTransparent identifies the color. To clear the transparent color, pass COLOR_None to SalColorSet.
Button Style Background Color Text Color Font Name Font Size Font Enhancement Appearance
Displays a cascading menu where you select the option button style (Palette, Radio, or Check). The background color of the option button. The color of text in the option button. The font of text in the option button. The font size of text in the option button. The font enhancement of text in the option button. The appearance of the borders around the button. Choices are Standard (relief-style borders) or Flat (no borders). Default is Standard.
You set the option button style in the Attribute Inspector. You use radio-style option buttons and check box-style option buttons in any place where you can use standard radio buttons and check boxes. Radio-style option buttons behave like radio buttons and check box-style option buttons behave like check boxes. You place palette-style option buttons in a modeless dialog box to create a floating dialog like the toolbars in SQLWindows and in other Windows products. Palette-style
Option button
option buttons behave like radio buttons, but SQLWindows paints them differently and they do not have a focus frame. The table below summarizes the attributes of each option button style:
Style Radio Check Box Palette Corners Round Round Square Focus frame Yes Yes No Behavior Radio Check Box Radio State changes Up Up Down
In the table above: Corners means round or square corners. Focus frame means whether the option button displays a focus frame when it has the focus. Behavior means whether the option button behaves like a check box or a radio button. When the user selects a radio button in a group, the others are deselected. The user can select more than one check box in a group. State changes means whether the option button changes state when the user presses the mouse button (down) or when the user releases the mouse button (up). SQLWindows sends SAM_Click when the state changes.
You set the image file and the image style in the Attribute Inspector.
5-33
Chapter 5
SQLWindows Objects
Single-image style
For the single-image style, SQLWindows creates an up, down, and disabled picture from a single image. The image file can be an icon (*.ICO) or a bitmap (*.BMP).
Multiple-image style
A multiple-image bitmap gives you complete control over the look of an option button, but you must draw four images in the bitmap. SQLWindows expects the bitmap file for the option button to contain images for these states: Image when unchecked/up on a color display. Image when checked/down on a color display. Image when disabled on a color display. Image for monochrome display. SQLWindows inverts this image when the option button is checked or down and dithers it when the option button is disabled.
A multiple-image file must be a bitmap (*.BMP). Arrange the four images vertically in the bitmap. In each image, use the same width and the same height.
Check box
4 * (ImageHeight + 1) In Microsoft Paint, you can set the size of the bitmap with Image, Attributes. 2. Draw a single-pixel horizontal line between each image and after the last image to delimit them. SQLWindows does not draw these lines when it displays the option button. Save this bitmap as a template for drawing other multiple-image bitmaps. To create a new bitmap, open the template and save it with a new name and then fill in each of the four images.
3. 4.
Check box
When the user clicks a check box, it turns an option on or off. More than one check box can be on at the same time.
5-35
Chapter 5
SQLWindows Objects
Description The title of the check box. Create a mnemonic by putting an ampersand (&) before the letter that you want to be the mnemonic. If Yes (default), the check box is visible at runtime. If No, the check box is not visible at runtime. At runtime, you can change the setting of this property with SalHideWindow and SalShowWindow.
Location and Size Background Color Text Color Font Name Font Size Font Enhancement
Displays a cascading menu with the check box's position (top and left) and size (width and height). The background color of the check box. The color of the check box text. The font of the check box text. The font size of the check box text. The font enhancement of the check box text.
List box
A list box displays a single-column list that lets the user select one or more items. A list box is read-only.
You can create list boxes with these features: Single selection or multiple selection. With multiple selection, more than one item can be selected at a time. Vertical and horizontal scroll bar. Sorted items.
List box
User interface
A single selection list box has this user interface: One item in the list box is always selected Click an item to select it or deselect it The arrow keys move the selection and scroll the list box Press Page Up or Page Down to move the selection and scroll the list box Press a key to scroll to an item that starts with that letter and select the item
A multiple selection list box has this user interface: None, one, or more than one item in the list box can be selected at a time Click an item to select it; the previous selection remains Click to deselect an item The space bar does the same thing as a mouse click: selects or deselects The arrow keys scroll the list box without changing the selection Page Up or Page Down scrolls the list box without changing the selection Press a key to scroll to an item that starts with that letter without changing selections
5-37
Chapter 5
SQLWindows Objects
Property Horizontal Scroll Background Color Text Color Font Name Font Size Font Enhancement
Description If Yes, SalListAdd adds a horizontal scroll bar to the list box if the string being added is wider than the list box. The default is No. The background color of the list box. The color of text in the list box. The font of text in the list box. The font size of text in the list box. The font enhancement of text in the list box.
Combo box
A combo box contains a data field and a list box. The list box contains predefined scrollable items that a user chooses to fill the data field.
Combo box
The list box part of a combo box can have these features: Sorted items Vertical scroll bar Can always be dropped
The data field part of a combo box can be editable or non-editable. If the data field is non-editable, there is no space between the right side of the data field and the down arrow; if the data field is editable, there is a space between the right side of the data field and the down arrow. One or no items in a combo box list are selected at any given time.
User interface
This is the user interface for a combo box: Click an item in the list box to select it, put it in the data field part of the combo box, and close the list box. The arrow keys scroll the list box, change the selection, and the contents of the data field part of the combo box. If the list box is not down, the arrow keys change the selection in the data field. If the combo box is editable, press a key to scroll to an item that starts with that letter. Alt+up arrow and Alt+down arrow open and close the list box.
5-39
Chapter 5
SQLWindows Objects
Description The maximum number of characters that the user can enter in the data field part of the combo box. The maximum length of a String or Long String data type varies and depends on the number of child objects in the parent window. This option is only available if the combo box is editable. The maximum number of characters that can be in the list box part is 54 kilobytes (for all items combined). Important: The value that you specify in Max Data Length is the maximum capacity of the object, not the number of bytes that SQLWindows allocates for the objects value. At runtime, SQLWindows allocates the number of bytes in the actual value of the object at any one time. Also, when you set a variable or another object with the value, SQLWindows only copies the number of bytes in the actual value, not the number of bytes in the Max Data Length setting of the source object.
Editable
If Yes (default), the user can enter or edit text in the data field part of the combo box. If No, the user cannot enter or edit text. At runtime, you can change the setting of this property with SalEnableWindow and SalDisableWindow.
Input Mask Sorted Always Show List Vertical Scroll Background Color Text Color Font Name Font Size Font Enhancement
Input validation criteria for the data field. For more, read Chapter 11, Formatting and Validating. If Yes, (default) the items in the list box part of the combo box are sorted. The sort order (collating sequence) is determined by the Windows character set and the country setting. If Yes, the list box part of the combo box is always displayed. If No (default), the list box only drops down when the user clicks the arrow. If Yes (default), the list box part of the combo box has a vertical scroll bar on the right side. The background color of the combo box. The color of text in the combo box. The font of text in the combo box. The font size of text in the combo box. The font enhancement of text in the combo box.
Picture
Chapter 16 describes picture objects.
Scroll bars
You can add vertical and horizontal scroll bars to an application. Up arrow Scroll box (also called thumb, elevator box, or slider box) Scroll box area (also called alley)
Down arrow A scroll bar has an associated numeric value: When a user clicks a scroll bar arrow one time, the integer value of the scroll bar increases or decreases by the line unit, and the scroll box moves accordingly When a user clicks the scroll bar area one time, the value increases or decreases by the page unit and the scroll box moves accordingly When a user drags the scroll box, the scroll bar value increases or decreases accordingly
A scroll bar also has a range which is a pair of integers that represent the scroll bar's minimum and maximum value. When the scroll box is at the top (or left) of the scroll bar, the position of the scroll box is the minimum value of the range. When the scroll box is at the bottom (or right) of the scroll bar, the position of the scroll box is the maximum value of the range.
5-41
Chapter 5
SQLWindows Objects
Custom control
Chapter 22 describes custom controls.
ActiveX control
Chapter 19 describes ActiveX controls.
Toolbar
A toolbar is a rectangular area where you place objects for the most often-used functions of an application. This is an example of a toolbar:
You define toolbars in top-level windows and MDI windows. To display a toolbar, set the Accessories Enabled attribute to Yes for a top-level window or MDI window. Specify the toolbars position (top, left, right, or bottom) in the Accessories attribute of the top-level window or MDI window. If you place the toolbar at the top or bottom, you can adjust its height. If you place the toolbar at the left or right, you can adjust its width. The outline for these windows has a section called toolbar where you can place child windows.
Toolbar
Toolbar attributes
The table below describes the attributes for a toolbar.
Property Display Style Description The visual appearance of child objects in the toolbar: Default Standard Etched Background Color Text Color Font Name Font Size Font Enhancement Uses the setting in the Window Defaults section of Global Declarations (standard or etched) Child objects appear two-dimensional Child objects appear three-dimensional
The background color of the toolbar. The color of text in the toolbar. The font of text in the toolbar. The font size of text in the toolbar. The font enhancement of text in the toolbar.
Outline items
The outline items for a toolbar are after the menu section:
Menu ... Toolbar ... Contents ...
You can place any child object (except for a column) in the Contents section of a toolbar. This is an example of a toolbar definition:
Toolbar ... Contents ... Pushbutton: pb7 ... Picture File Name: cut.bmp ... Message Actions On SAM_Click
5-43
Chapter 5
SQLWindows Objects
If NOT SalEditCut( ) Call SalMessageBeep( MB_Ok ) ... Combo Box: cmb1 ... List Initialization Text: P1 ... Background Text: P#: ...
Functions
You can hide or show a toolbar by calling SalTBarSetVisible. Call SalGetFirstChild to get the handle of the toolbar window. The statement:
Set hWndToolBar = SalGetFirstChild( hWndForm, TYPE_FormToolBar )
returns the handle of the form windows toolbar, if any. You can use the window handle to change the properties of the toolbar (such as color or font) or to find the window handles of the toolbars children using SalGetFirstChild and SalGetNextChild.
Status bar
Status bar
You can place a status bar at the bottom of a top-level window or MDI window. The status bar shows the setting of the Num Lock, Scroll Lock, and Caps Lock keys.
To display a status bar, set the Accessories Enabled attribute to Yes for the top-level window or MDI window. You can turn the status bar on and off with SalStatusSetVisible. You can display a message in a status bar with SalStatusSetText. You can retrieve the text in a status bar with SalStatusGetText.
If a window with one of these types of menu items has a status bar, SQLWindows displays the status text when the user selects the menu item with the mouse. Popup menus that you create with SalTrackPopupMenu also display the status text when the user selects the menu item with the mouse.
5-45
Chapter 5
SQLWindows Objects
Message boxes
You can use a message box instead of a dialog box when you only need a simple response from the user or when you only need to display a message.
You do not create message boxes at designtime. Instead, you call the SalMessageBox function. The SQLWindows Function Reference describes SalMessageBox.
Standard dialogs
You can call these functions to display standard Windows dialog boxes: SalDlgChooseColor SalDlgChooseFont SalDlgOpenFile SalDlgSaveFile
Object colors
Object colors
When you add an object, you set its color in the Attribute Inspector. Instead of choosing a color, you can also choose Default, System Text Color, System Frame Color, or System Window Color: For top-level objects, Default means the system-defined text color or background color. For child objects, Default is the color set in the Windows Defaults section of the outline. Unless you change the Windows Defaults setting, this is the color of the top-level object. System Text Color, System Frame Color, and System Window Color are the defaults set in the control panel.
If you choose a color that does not exist in the computer, SQLWindows uses the closest color. On monochrome computers, SQLWindows ignores the color of objects.
Color inheritance
By default, child objects inherit their color from their top-level objects. For example, when you first add a child object, it appears in the color of its top-level object. To make the child object a different color, change the Text Color or Background Color property.
Functions
At runtime you can get and set an objects color with SalColorGet and SalColorSet. The SQLWindows Function Reference describes these functions.
5-47
Chapter 5
SQLWindows Objects
Description
For top-level objects, Default means no font enhancement For child objects, Default means to use the parent's font enhancement
When choosing fonts, always design applications for the lowest resolution that is used. This ensures that the windows will fit within the monitor's screen.
Font inheritance
By default, child objects inherit their font properties from their top-level object. For example, when you first add a child object, it appears in the font of the top-level object. If you want the child object to use different font properties, change the font name, font size, or font enhancement. Table windows are the exception to this rule. You can only set font properties for the entire table window. You cannot set different font properties for a table window column.
Form units
SQLWindows uses form units as the unit of measure for objects. Form units are independent of the screen resolution which allows applications to run with different resolutions. Windows sizes and locations are proportional across different resolutions, although the physical size changes as expected. Form units are based on the selected font to allow the screen resolution independence. All SAL functions that involve window location or sizes use form units as the unit of measure. If you want to convert form units to pixels on the current screen, you can use the SalFormUnitsToPixels function. If you are using external functions that return values in pixels, you can convert them to form units with the SalPixelsToFormUnits function. 5-48 Developing with SQLWindows
Window handles
Window handles
When a window is created, a window handle is established for that instance of the window. The window handle uniquely identifies the window. You can use the handle to access the window. SQLWindows has a specific data type for window handles. For more, read Window Handle on page 7-9.
You can call SalGetFirstChild and SalGetNextChild to return the child window handle of the parent. Do not write code that assumes the order of child objects. There is no guaranteed order in which SalGetFirstChild and SalGetNextChild returns window handles.
Docking windows
In SQLWindows, top-level windows (MDI windows, form windows, and top-level table windows) are capable of docking with some child windows. In version 3.0, these child windows include modeless dialog boxes and the toolbars of the top-level windows themselves. Docking can occur through user actions, like dragging a child window to an edge of a top-level window. It can also occur programmatically, using the functions SalDlgSetDockStatus, SalDlgGetDockStatus, and SalWindowGetDockSettings. Docking events are made available to SAL developers through the messages SAM_Dock and SAM_DockChange. Top-level windows and child windows must specify which edges are available for docking. This is known as the docking orientation. Top-level windows cannot do this at runtime; you must specify the docking orientation using the Attribute Inspector at design time. Toolbar docking orientation must also be specified at design time. However, dialog boxes can change their docking orientation at design time and also at run time, using the functions shown above. Windows can only dock on the edges specified by their docking orientation. If there is an incompatibility between the orientation of the child window and the orientation of the top-level window, docking will not occur. If you design a modeless dialog box that docks on the left edge, and it belongs to a top-level window that only permits
5-49
Chapter 5
SQLWindows Objects
docking on the top edge, attempts to dock the dialog will fail and it will remain freefloating. If a tool bar has been designed as docking-enabled, and the orientation specified for the toolbar is not compatible with the orientation of the top-level window, the toolbar will not be displayed at all.
You can use variables and objects interchangeably. For example, if a form window has a data field called dfName, the SAL language statement:
Set dfName = 'Hello'
You can use an object's name (such as frmMain or tblCustomer) as a window handle except when multiple instances of the window exist.
The parameters that you pass must be defined in the Window Parameters section of the outline for the window that you are creating. SQLWindows uses the values that you pass to fill the window parameters in the order that they are defined in the Window Parameters section. You can define window parameters in top-level windows and for MDI windows. Before sending SAM_Create to the window being created, SQLWindows sets the window parameters with the values that you pass. You can refer to the window parameters in the message actions of the window that you are creating.
Important: You cannot pass the value of a window object such as a data field to a receive window parameter. However, you can pass the value of a window object to a non-receive window parameter.
You cannot use receive window parameters as receive function arguments. You can use a temporary variable as the function argument and then assign the temporary variable to the receive function parameter. SalCreateWindow and SalModalDialog accept a string or a window name as the first parameter. When you pass a string, you cannot also pass window parameters.
5-51
Chapter 5
SQLWindows Objects
Chapter 6
Application Menus
This chapter explains the elements of menus that you can add to applications: Popup menus Menu items Named menus Creating menus dynamically at runtime Displaying menu text in the status bar Window menus Graphical Menu Editor
6-1
Chapter 6
Application Menus
About menus
You can add menus to form windows, top-level table windows, and MDI windows. Menus are like other objects, but you do not use the Controls toolbar to create them. Instead, you use Coding Assistant or the graphical Menu Editor to add popup menus and menu items, and to define menu features.
Popup menus
A popup menu groups menu items in a list. You define properties for a popup menu in the Menu section of the outline for form windows, top-level table windows, and MDI windows:
Popup Menu: &Edit Enabled when: Status Text: Menu Item: &Undo ... Menu Separator Menu Item: Cu&t ... Menu Item: &Copy ... Menu Item: &Paste ... Menu Item: C&lear ...
Select Popup Menu in the Coding Assistant to create a Popup Menu section under the Menu section or type a menu definition directly into the outline.
Property Menu Title Description The name of a popup menu that appears in the menu bar. Create a mnemonic for a menu by putting an ampersand (&) before a menu title character. The & causes the character to be underlined. Enabled When You can place an expression here that controls when the popup menu is enabled. When the expression is TRUE, the menu is enabled. When the expression is FALSE, the menu is disabled. The expression is TRUE by default: if Enabled When is blank, the menu is always enabled. The expression is only evaluated when you call SalDrawMenuBar. Status Text Text to display in the status bar of the window. For more, read Menu status text on page 6-9.
6-2
Menu items
Menu items
When the user selects a menu item, the statements in its Actions section execute:
Menu Item: Cu&t Keyboard Accelerator: Shift+Del Status Text: Menu Settings Enabled when: SalEditCanCut() Checked when: Menu Actions Call SalEditCut()
You can place a menu item in a: Menu bar as a top-level command Popup menu
When positioned on a popup menu in the outline, you can add menu items at the same level or at the next level using Coding Assistant. This controls whether the menu item is in the popup menu (next level) or is on the menu bar (same level) as a top-level menu item. Select menu item in Coding Assistant to create a Menu Item section. The table below lists the menu item properties.
6-3
Chapter 6
Application Menus
Description You place an expression here that controls when the menu item is enabled. When the expression is TRUE, the menu item is enabled and the user can select it to invoke the associated action. When enabled, the menu item name is black. When the expression is FALSE, the menu item is disabled and the user cannot select it to invoke the associated action. When disabled, the menu item name is gray. For example, if you only want the Cut menu item to be enabled when the user has highlighted something to cut: Enabled when: SalEditCanCut ( ) The expression is TRUE by default: if Enabled When is blank, the menu item is always enabled. For a top-level menu item, the expression is only evaluated when you call SalDrawMenuBar.
Checked when
You place an expression here that controls when the menu item has a check mark. When the expression is TRUE, the menu item has a check mark on its left side. When the expression is FALSE, the menu item does not have a check mark. The expression is FALSE by default: if Checked When is blank, the menu item does not have a check mark. SAL statements that execute when the user selects the menu item.
Menu Actions
Accelerators
Ctrl + character key combinations Ctrl+A Ctrl+B Ctrl+C Ctrl+D Ctrl+E Ctrl+F Ctrl+G Ctrl+H Ctrl+I Ctrl+J Ctrl+K Ctrl+L Ctrl+M Ctrl+N Ctrl+O Ctrl+P Ctrl+Q Ctrl+R Ctrl+S Ctrl+T Ctrl+U Ctrl+V Ctrl+W Ctrl+X Ctrl+Y Ctrl+Z Function keys F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 Shift + function key combinations Shift+F1 Shift+F2 Shift+F3 Shift+F4 Shift+F5 Shift+F6 Shift+F7 Shift+F8 Shift+F9 Shift+F10 Shift+F11 Shift+F12 Other Ins Shift+Ins Alt+BkSp Del Ctrl+Del Ctrl+Fkey Ctrl+Ins - (minus) + (plus) Shift+Ctrl+<char> Shift+Ctrl+Fkey Shift+Ctrl+Del Shift+Ctrl+Ins Shift+Del
6-4
Menu separator
Menu separator
A menu separator is a horizontal line between menu items that groups related items in a menu.
Menu separator
Cascading menus
A cascading menu is a child popup menu inside another popup menu. A menu item that displays a cascading menu has an arrow on its right side. A popup menu can contain both menu items and cascading menus. Both levels can have accelerators and mnemonics. Cascading menus have the same properties as popup menus.
Cascading menu
6-5
Chapter 6
Application Menus
Menu row
A menu row starts a new row of menu items and popup menus. All popup menu names or top-level menu items after a menu row are on the next row of the menu bar.
Menu row
Menu column
A menu column groups menu items in vertical columns. Menu column
6-6
Named menus
Named menus
You use named menus to create popup menus that windows in an application can share. You can also use named menus to create popup menus dynamically that can appear anywhere on the screen. You define a named menu in the section called Named Menus in Global Declarations. For example:
Named Menus Menu: menuEdit Description: Edit menu Title: &Edit Enabled when: Status Text: Undo, Cut, Copy, Paste, Clear Menu Item: &Undo Menu Separator Menu Item: C&ut Menu Item: &Copy Menu Item: &Paste Menu Item: &Clear
Place the name of the menu after the colon. This is different from other popup menus which only have a display title. You use this name when you add a named menu to a window. There is also a Named Menus section in window definitions where you can add named menus that you create dynamically at runtime or share between an MDI window's children. A named menu can have two types of children: Menu and Windows Menu. To use a named menu, specify its name in the menu definition of a window:
Menu Popup Menu: &File Named Menu: menuEdit
A Windows Menu can refer to any of its own named menus or any global named menus. An MDI child window can also refer to named menus in its MDI window parent. If a reference to a named menu is unresolved the menu will display the referenced name surrounded by <and >. For example, if the menuEdit example above was not a named menu, the menu of this window would display File <menuEdit>. You can only use named menus for top-level popup menus, not for cascading menus in a popup menu.
6-7
Chapter 6
Application Menus
The parameters are: hWnd strMenuName The window handle for a top-level window that processes messages that the popup menu sends A named menu defined in one of the following: nFlags The Named Menus section of hWnd The Named Menus section of hWnd's MDI window parent The Named Menus section of Global Declarations
How to display the popup menu. You can combine these flags using the | operator: TPM_CursorX TPM_CursorY TPM_LeftButton Display the menu at the location of the mouse cursor instead of nX Display the menu at the location of the mouse cursor instead of nY The user can click items in the menu with the left button (default)
TPM_RightButton The user can click items in the menu with the right button TPM_LeftAlign TPM_CenterAlign Left-align the menu with its horizontal screen coordinate Center-align the menu with its horizontal screen coordinate
6-8
TPM_RightAlign nX, nY
Example
This example creates an Edit popup menu when the user clicks the mouse button. The menu appears where the mouse is positioned when the user clicks.
On SAM_Click Call SalTrackPopupMenu( hWndForm, 'menuEdit', TPM_CursorX | TPM_CursorY | TPM_CenterAlign, 0, 0 )
If a window with one of these types of menu items has a status bar, SQLWindows displays the status text when the user selects the menu item with the mouse. Popup menus that you create with SalTrackPopupMenu also display the status text when the user selects the menu item with the mouse.
Windows menu
A windows menu is a special type of popup menu that you use in MDI windows and their children. A windows menu automatically lists all the MDI window's child windows without any coding. You can add your own menu items to a windows menu. For more, read MDI window on page 5-12.
6-9
Chapter 6
Application Menus
Menu Editor
You build menus graphically using this dialog.
To display this dialog: With a window menu selected in the tree view or outline, click the right mouse button and select Menu Editor OR With a top-level window selected in a layout window OR With a top-level window selected in the tree view or outline OR Select Component, Menu Editor
The upper left of the dialog shows the menu definition in hierarchical form. A toolbar below this list has buttons that you use to build the menu. From left to right, the buttons are: Selection Popup menu, windows menu, or named menu Menu item or object menu
Menu Editor
The middle of the dialog has areas for: Title and status text for popup menus and menu items. Accelerator information for menu items. Functions for popup menus and menu items. Group Information for ActiveX menu merging. For more, read Menu groups on page 19-37.
The sections below explain how to add and delete menu components. After you perform an operation, click OK to save your changes and close this dialog or click Cancel to close the dialog without saving your changes.
Note: You can also double-click Popup Menu in the list below the toolbar to add a popup menu below the selected item in the menu definition area.
3. 4.
In the middle of the dialog, enter a menu title and status text. In the title, put an ampersand before the character that you want to be the mnemonic. You can call a function that determines when the popup menu is enabled. For more, read Function Call Editor dialog on page 6-13.
6-11
Chapter 6
Application Menus
Note: You can also double-click Menu Item in the list below the toolbar to add a menu item below the selected item in the menu definition area. You can also add a menu item to the menu bar.
4. 5. 6.
In the middle of the dialog, enter a menu title and status text. In the title, put an ampersand before the character that you want to be the mnemonic. Specify information about the menu accelerator in the middle of the dialog. You can call a function that determines: When the menu item is enabled When the menu item is checked The statement that executes when a user chooses the menu item
Menu Editor
1. 2. 3.
Click the fourth (menu separator), fifth (menu column), or sixth (menu row) button in the toolbar. Move the mouse to the menu definition area above the toolbar. Note that the mouse pointer changes. Click where you want to add the menu component. Note that the mouse pointer changes. The menu component appears above the item you selected in the menu definition. If the menu component does not appear where you want it, drag it up or down, or left or right.
Note: You can also double-click the component name in the list below the toolbar to add the component below the selected item in the menu definition area.
6-13
Chapter 6
Application Menus
Building statements
To build statements, use the Function Call Editor dialog. After you add a popup menu or menu item, click Enabled When, Checked When, or Call Function to display this dialog. For menu items, click Create Window to display a dialog where you select a window that SQLWindows uses to automatically build a SalCreateWindow or SalModalDialog statement.
Clearing functions
If you have associated functions with menu components, you can delete them by selecting the function in the lower middle section of the Menu Editor dialog and clicking Clear Function. After you perform an operation, click OK to save your changes and close the Function Editor dialog or click Cancel to close the dialog without saving your changes.
Menu Editor
Selecting a function
When you first display this dialog, the top left contains (none). The middle left of the dialog lists functions. Type in the data field above the list to scroll to a function that begins with what you type. Uncheck Global Functions in the lower left to list only functions local to the window. After you select a function name, double-click or click Select Function. The upper left of the dialog displays the function with its parameters listed below it.
Note: For enabled when and checked when functions, you can only select a function that returns a Boolean value.
Selecting parameters
After you select a function, the list in the lower left of the dialog changes and shows symbols defined in the application. Type in the data field above the list to scroll to a symbol that begins with what you type. Use Symbols in the middle left of the dialog to limit what the list displays. Uncheck Global Symbols in the lower left to list only symbols local to the window. After you select a symbol name, double-click or click Change Parameter. The symbol you chose replaces the parameter in the upper left of the dialog.
6-15
Chapter 6
Application Menus
Create Window dialog The list in the lower left of the dialog shows the names of all windows in the application. You can scroll the list by typing the first few characters of the window name in the data field above the list.
Make a selection in the combo box to list only a certain type of window. The choices are: All Form window Dialog Table window MDI window MDI children
Choose the window to create by selecting and double-clicking or clicking Select Window. After you choose a window, its name appears in the data field in the upper left of the dialog. After you choose a window, click OK to save your changes and close this dialog or click Cancel to close the dialog without saving your changes.
Chapter 7
7-1
Chapter 7
Case sensitivity
SQLWindows is case sensitive. Uppercase and lowercase characters are seen as different.
Data types
You specify a data type for variables and constants. Variables can be one of these data types: Boolean Date/Time File Handle Long String Number Sql Handle String Window Handle
Constants can be one of these data types: Boolean Date/Time Number String
7-2
Data types
Boolean
Use this data type for variables that can be TRUE or FALSE. These values are system constants: TRUE is 1 and FALSE is 0.
Example
Set bBool = TRUE Set bBool3 = bBool2
Date/Time
Use this data type for dates and times. The default output format is ISO: YYYY-MM-DD-HH.MM.SS.MSMSMS The only valid input format for Date/Time values in Set statements is ISO as shown above. Note the following: The year must be four digits The month, day, hour, minute, and seconds must be 2 digits. Include a leading zero when the value is less than 10 You must use the hyphens and periods as separators in the positions shown above The microseconds (MS) can be up to six digits
You can use the DATETIME_Null system constant to set a Date/Time to a null value, or to check if a Date/Time value is null.
Example
Variables Date/Time: dtBirthday Date/Time: dtOrder ... Set dtBirthday = 1983-10-25 Set dtOrder = 1986-01-12-05.23.10.875345
7-3
Chapter 7
Internal format
Internally, SQLWindows stores Date/Time data in its own floating point format. This format interprets a Date/Time value as a number in this form: DAY.TIME DAY is a whole number that represents the number of days since December 30, 1899. December 30, 1899 is 0, December 31, 1899 is 1, and so on. TIME is the fractional part of the day. Zero represents 12:00 AM, .25 is 6:00 AM, .5 is 12:00, .75 is 3:00, and so on. For example, March 1, 1900 12:00:00 PM is represented by the floating value 61.5 and March 1, 1900 12:00:00 AM is 61.0. If you omit a part of an input Date/Time value, SQLWindows supplies the default of 0, which converts to December 30, 1899 (date part) 12:00:00 AM (time part). For example, if you define this variable:
Date/Time: dtExample
and execute this Set statement that does not specify a time:
Set dtExample = 1983-10-02
Date/Time arithmetic
You can perform these arithmetic operations with Date/Time values: Add a Number value to a Date/Time value, giving you a Date/Time value Subtract a Number value from a Date/Time value, giving you a Date/Time value Subtract one Date/Time value from another Date/Time value, giving you a Number value
Note that if you add or subtract a Number value to or from a Date/Time value, the result is a Date/Time value.
7-4
Data types
The next sections show examples of each type of Date/Time arithmetic. In these examples, these variables are used:
Date/Time: dtExample1 Date/Time: dtExample2 Number: nResult
7-5
Chapter 7
Examples: 1. Assume the current year is 1996: If 05 is entered, the computed date is 2005 If 89 is entered, the computed date is 1989 2. Assume the current year is 2014: If 05 is entered, the computed date is 2005 If 34 is entered, the computed date is 2034 If 97 is entered, the computed date is 1997 3. Assume the current year is 2065: If 05 is entered, the computed date is 2105 7-6
Developing with SQLWindows
Data types
Number
Use this data type for numbers with up to 44 digits of precision. You can use the NUMBER_Null system constant to set a Number to a null value, or to check if a Number value is a null. If you use a Number data type as a bind variable to write a SQLBase DECIMAL data type column, truncation can happen because SQLBase DECIMAL data types have a maximum of 22 digits of precision.
Example
Variables Number: nMonth ... Set nMonth = SalDateMonth( SalDateCurrent( ) )
Session Handle
You use this data type for multi-connection transactions and OLE DB provider connections. For more, read Multi-connection transactions on page 12-25 and Session Handle data type on page 13-2.
Sql Handle
Use this data type to identify an open connection to a database. All access to a database requires a Sql handle. You use Sql Handles in Sql* functions to execute SQL statements. For more, read Chapter 12, SQL Programming.
Example
SqlConnect returns the handle. Before you call SqlConnect, hSql does not have a valid value.
7-7
Chapter 7
File Handle
Use this data type to identify an open file. When you open or create a file, SQLWindows returns a file handle. You then use the file handle to identify the file.
Example
Variables File Handle: hFile ... Set bOk = SalFilePutStr( hFile, strOneLine )
String
Use this data type for character data. The only limit on the length of a String data type is available system memory. Enclose literal strings in single quotes. You can also enclose literal Strings in double quotes. When you do, you do not need to put escape characters before embedded single quote characters. For example:
String: strSelect = "select * from customers where name = 'smith'"
Example
This example defines the string strQuery and assigns it a literal value.
Variables String: strQuery ... Set strQuery = 'SELECT APPT INTO :FLDAPPT FROM CLIENT'
Long String
Use this data type for character data. The only limit on the length of a Long String data type is available system memory. Use this data type to read and write SQL database columns longer than 254 bytes.
Example
Variables Long String: sLong ... Set sLong = 'Long String'
7-8
Data types
Internally, SQLWindows uses the SQL/API functions sqlrlo and sqlwlo to read and write these column data types.
Window Handle
Use this data type to identify a single instance of a window. At runtime, each instance of a window has a unique handle. Until you assign a value to this data type, it contains hWndNULL. For more, read Window handles on page 5-49.
Example
Variables Window Handle: hWndItem ... Form Window: frmMain ... Contents Data Field: dfClock ... Message Actions On SAM_Create Call SalTimerSet( hWndItem, 1, 1000)
7-9
Chapter 7
An uninitialized variable, of any data type, when converted to a Boolean, evaluates to FALSE. A variable, of any data type, which has been assigned a null value from a database, evaluates to FALSE. A string variable or constant with the value '' (null string) evaluates to FALSE. A number variable or constant with the value 0 (zero) evaluates to FALSE. A window handle matching hWndNULL evaluates to FALSE. Everything else evaluates to TRUE.
Variables
A variable can hold any value of its data type.
Variables
Syntax
Use this syntax to declare a variable:
Data Type: VariableName
Examples
These are examples of variable declarations:
Boolean: bReturn Date/Time: dtBirthday Long String: strLong Number: nCount Sql Handle: hSql String: strName Window Handle: hWndHelp
7-11
Chapter 7
You qualify references to: Eliminate ambiguity with duplicate names Refer to a window that has multiple instances Refer to a variable in a child from its parent Refer to a variable in a different top-level window or MDI window
The next sections show examples of qualified references. For more, read Chapter 7, SAL (SQLWindows Application Language).
Variables
Two windows exist with identical names (frm1) and identically-named variables (dfName). SQLWindows cannot determine the copy of dfName to which the dialog box dlg1 refers:
Dialog Box: dlg1 ... Window Variables String: strName Message Actions On SAM_Create Set strName = frm1.dfName
To eliminate the ambiguity, specify: The window handle that the variable is associated with (hWnd1 or hWnd2) The template name with which the variable is associated (frm1)
7-13
Chapter 7
You must qualify the reference because it is in the form and is not in the scope of the child variable. In the example below, a form window makes a reference to a window variable defined in its child table window:
Form Window: frm1 ... Contents Data Field: df1 Child Table: tblChild ... Window Variables String: strInfo Window Variables Message Actions On SAM_Create Set df1 = tblChild.strInfo
When you use variables in a SQL statement, you must prefix them with a colon (:). For more about how to use variables in SQL statements, read Chapter 12, SQL Programming
System variables
The table below lists SQLWindows's system variables.
System variable MyValue hWndMDI hWndNULL hWndForm hWndItem wParam lParam Data type Data type of current window Window Handle Window Handle Window Handle Window Handle Number Number Description The value in the current window. The current MDI window. Returned when a window does not exist. The current top-level window (form window, table window, or dialog box). The current object. A generic message parameter. A generic message parameter.
Arrays
System variable nArgCount strArgArray[*] SqlDatabase SqlUser SqlPassword SqlNoRecovery SqlInMessage SqlOutMessage SqlResultSet SqlIsolationLevel
Data type Number Array String String String Boolean Number Number Boolean String
Description The number of command line arguments that the user entered when starting the application. The command line arguments that the user entered when starting the application.
You use these system variables to access SQL databases. For more, read Chapter 12, SQL Programming.
Arrays
An array is a collection of variables (elements) of the same data type that you refer to with a common name. You refer to an individual element in an array with a number that represents the index offset. An array can be static or dynamic: A static array contains a fixed number of elements A dynamic array contains a variable number of elements
An array can be one-dimensional or multi-dimensional (an array of arrays). SQLWindows always passes array elements to functions by reference even if the function parameter is declared with the Receive keyword. The maximum number of arrays in an application is 64 kilobytes.
One-dimensional arrays
Static arrays
If you know the maximum number of elements that an array can contain at one time, specify that number when you declare the array:
String: strEmployees[10]
7-15
Chapter 7
The ten elements in the array above are numbered 0-9. An array like this with a fixed number of elements is called a static array. You must specify a numeric literal for the number of elements. You can put any expression that evaluates to a number between the square brackets.
Dynamic arrays
If you cannot predict the maximum number of elements in an array, use an asterisk instead of a number to tell SQLWindows that it is a dynamic array:
String: strEmployees[*]
The elements in the array above are numbered 0-n, where n depends on available system resources. Dynamic arrays initially have zero elements. Call SalArrayIsEmpty to determine if an array contains data. You can reset a dynamic array to zero elements by calling SalArraySetUpperBound and setting the nBound parameter to -1.
The ten elements in the array above are numbered 1-10. You can set the lower bound in a dynamic array:
String: strEmployees[1:*]
The elements in the array above are numbered 1-n, where n depends on available system resources. Important: You cannot specify an asterisk for the lower bound.
Referring to arrays
You refer to an element in an array by specifying its index:
Set df1 = strEmployees[5]
Multi-dimensional arrays
You declare a multi-dimensional array like a one-dimensional array, but you also specify the number of elements in the second and subsequent dimensions after the number of elements in the first dimension. You separate each dimension specification with a comma.
Arrays
Note: The maximum number of dimensions in an array is limited only by available system resources.
Static arrays
This example declares a 2-dimensional array with a fixed number of elements in both dimensions:
String: strEmployees[10, 3]
The array above has ten elements in its first dimension (numbered 0-9) and three in its second dimension (numbered 0-2).
Dynamic arrays
You can make the first dimension dynamic:
String: strEmployees[*,3]
The array above has a dynamic number of elements in its first dimension (numbered 0-n) and three in its second dimension (numbered 0-2).
Important: You can make only the first dimension of a multi-dimensional array dynamic.
The array above has ten elements in its first dimension (numbered 1-10) and three in its second dimension (numbered 1-3). You can set the lower bound if the first dimension is dynamic:
String: strEmployees[1:*, 1:3]
The array above has a dynamic number of elements in its first dimension (numbered 1-n) and three in its second dimension (numbered 1-3).
7-17
Chapter 7
Important: When you refer to a multi-dimensional array, you must explicitly specify an index for every dimension.
Array functions
You use these functions with arrays: SalArrayAvg SalArrayDimCount SalArrayGetLowerBound SalArrayGetUpperBound SalArrayIsEmpty SalArrayMax SalArrayMin SalArraySetUpperBound SalArraySum
For more about these functions, read the SQLWindows Function Reference or the online help.
Constants
A constant contains a single, unchanging value. You can declare a constant as one of these data types: Boolean Date/Time Number String
Naming conventions
You can only declare constants in the Global Declarations section. You can refer to a constant wherever you can refer to a variable. You can declare numeric constants with hexadecimal values. For example: 0x1234ABCD.
Syntax
Use this syntax to declare a constant:
Data Type: ConstantName = expression
Examples
These are examples of constant declarations:
Constants Number: BASE = 500 Number: MAXNUM = BASE+1000 String: STATE = 'New Jersey' String: City = 'Newark' String: PLACE = CITY || ',' || STATE Date/Time: July_4 = 1994-07-04 Boolean: bDone = FALSE
System constants
SQLWindows has many system constants that are explained in the online help.
Naming conventions
Variables
Use prefixes in the names of variables to make the outline self-documenting. The table below lists the name prefixes.
Data type Boolean Date/Time File Handle Long String Number Sql Handle String Window Handle b dt fh ls n hSql s (or) str hWnd Name prefix Example bVarName dtVarName fhFileVarName lsVarName nVarName hSqlVarName sVarName hWndVarName
7-19
Chapter 7
Constants
Use an uppercase prefix with an underscore followed by a mixed-case or uppercase name. For example:
TYPE_ConstantName TYPE_CONSTANTNAME
Operators
An operator is a symbol or word that represents an operation to perform on one or more values. The table below shows the operators:
Operator symbols +, -, *, / Numeric Unary Relational Boolean Bitwise AND Bitwise OR Concatenate String Operator type
unary =, !=, >, <, >=, <= AND, OR, NOT & | ||
Expressions
An expression is a combination of constants, variables, and operators that yields a single value. An expression can be: The result of a function A variable A constant Two or more expressions connected with an operator
SQLWindows uses these precedence rules to evaluate expressions: Evaluate expressions with AND, OR, and NOT from left to right Stop evaluating AND/OR as soon as the result is known Evaluate expressions in parentheses first
Examples
nSalary[grade] + .1*nSal[3] bQueryOn MAXNO
SAL statements
1 + 1 SalDateCurrent( )
SAL statements
You use SAL statements to code actions that you want the application to execute. The sections on the next pages explain each SAL statement: Break Call If, Else, and Else If Loop On Return Select Case Set When SqlError While
Break
Ends a Loop statement. If you specify a loop name, that loop ends. This lets you break out of more than one level of loop. If you do not specify a loop name, the statement breaks out of the nearest level of loop.
Syntax
Break [loopname]
Example
This example fetches rows and breaks out of one level of the loop when SqlFetchNext returns FALSE.
Loop If NOT SqlFetchNext (hSql, nInd) Break If nInd = FETCH_EOF
Developing with SQLWindows
7-21
Chapter 7
Call
Executes a function.
Syntax
Call FunctionName( parameters )
Examples
Call SalStrUpper(fldName, fldName) Call SqlImmediate('delete from cust where name = :fldName')
Syntax
If expression1 statement1 Else If expression2 statement2 Else statement3
SQLWindows evaluates expression1. If expression1 is TRUE, SQLWindows executes statement1. If expression1 is FALSE, SQLWindows evaluates expression2. If expression2 is TRUE, SQLWindows executes statement2. If expression2 is FALSE, SQLWindows executes statement3.
Examples
If Fldb = 'M' Call ProcessMale(fldSex) Else If Fldb = 'F' Call ProcessFemale(fldSex) Else Call ProcessOther(fldSex)
You can nest If statements. You can rewrite the example above as:
SAL statements
If Fldb = 'M' Call ProcessMale(fldSex) Else If Fldb = 'F' Call ProcessFemale(fldSex) Else Call ProcessOther(fldSex)
Loop
Repeats statements indented under it until a Break or Return statement.
Syntax
Loop [loopname]
Example 1
Loop If count = 100 Break Set count = count + 1
Example 2
Set y = 0 Set z = 0 Loop Outer If z > 10 Break Loop Inner If y > 10 Break If GetData = 10 Break Outer Set GetData = ValCheck( ) Set y = y + 1 Set z = z + 1
On
Relates a message to SAL statements indented under it that execute when that message is received. You code On statements only in the Message Actions and Application Actions sections. Messages are identified with a message number or with a constant that represents the message number.
7-23
Chapter 7
Syntax
On message
Example
When the Application Actions section receives the SAM_AppStartup message, the SAL statements that are under the On statement execute:
Application Actions On SAM_AppStartup Call SalModalDialog (LogBox, hWndNULL)
Return
Breaks the flow of control and returns a value to a caller. Use this statement to end a: Function Message action Menu action
Syntax
Return expression
Example
Message Actions On SAM_KillFocus Return SalIsNull(fldName)
Select Case
Tests a series of conditions. The value of an expression is successively compared against the Case constants. Both the expression and the constants must be number data types. The Break statement terminates the Select Case statement. You must have a Break at the end of every Case statement unless you want the application to continue execution through to the next Case statement. The Default case is optional and is executed if the value of the expression does not match any of the Case constants. You can add as many Case constants as you want, but there can only be one Default section.
Syntax
Select Case (expression) Case constant1
SAL statements
SQLWindows evaluates expression. If expression matches constant1, then SQLWindows executes statement1; if expression matches constant2, then SQLWindows executes statement2. If no Case constant matches expression, then SQLWindows executes the statements under Default.
Example
Select Case ( SalDateQuarter( dtDate ) ) Case 1 Set strQuarter = 'First Quarter' Break Case 2 Set strQuarter = 'Second Quarter' Break Case 3 Set strQuarter = 'Third Quarter' Break Case 4 Set strQuarter = 'Fourth Quarter' Break Default Set strQuarter = 'Error'
Set
Assigns a value to a variable.
Syntax
Set VariableName = Expression
Examples
Set Set Set Set MsgTxt = 'Not a valid number' Errno = SqlError (hSql) fldName = 'Washington' fldName = GetName( )
7-25
Chapter 7
When SqlError
By default, when a SQL function fails, SQLWindows displays a dialog that contains an error number, error description, and error position. You can override this default error processing at a local level using the When SqlError statement in any outline section. You must code the When SqlError statement: Before the Sql* function At the same indent level as the Sql* function
You can also control SQL error handling at a global level by processing SAM_SqlError in the application actions section. For more, read SQL error handling on page 12-17.
While
The While statement repeats until the expression being evaluated becomes FALSE.
Syntax
While expression statement
SQLWindows evaluates expression. If expression is TRUE, SQLWindows executes statement and re-evaluates expression. When expression becomes FALSE, SQLWindows executes the next statement after the While statement.
Example
Set n=0 While n < 10 Set nArray [n] = 0 Set n = n + 1
Comments
A line that starts with an exclamation point (!) is a comment. If you put an exclamation point anywhere except at the beginning of a line, the rest of the line is a comment.
Example
! Ask for destination Call SalModalDialog (OutBox, hWndForm)
Comments
Text style
SQLWindows displays comments in gray by default. You can change this to a different color or style. For more, read Preferences on page 4-32.
Collapsible comments
You can create collapsible comments. For example, you can have a one-line summary description for a section of code with several lines of detailed explanation at the next level. When collapsed, the details are hidden. Here is how to create collapsible comments: 1. 2. 3. 4. Add a comment line that is the one-line summary and press Enter. Display Coding Assistant. There is an exclamation point in the Add Next Level list. Double-click the exclamation point to add a line at the next level. Enter the comment text and press Enter. When a nested comment line is selected, Coding Assistant displays an exclamation point in both the Add Same Level and Add Next Level lists. You can continue adding to the current comment at the same level or the next level or you can start a new comment.
Here is an example of a collapsible comment with nested levels (shown without the diamonds):
! Short pithy description ! Some details ... ! More details ... ! More details ... ! Even more details ... ! Even more details ... ! Even more details ... ! More details ... ! More details ...
7-27
Chapter 7
Reserved words
Some words cause compile errors when used as function names or variable names in SAL. Note that the words listed below are case-sensitive. Using a word with a different case may work, although using any of these words as function names or variable names is not recommended.
Word this new Break Call Else If Loop On Return Select Set When While Used as function name Not allowed Not allowed Allowed Allowed Allowed Allowed Allowed Allowed Allowed Allowed Allowed Allowed Allowed Used as variable name Allowed Not allowed Not allowed Not allowed Allowed Not allowed Not allowed Allowed Not allowed Allowed Not allowed Not allowed Not allowed
Functions
A function performs a specific task. There are five types of functions: System functions External functions Internal functions Window functions Class functions
You write internal functions, window functions, and class functions. In some cases, you write external functions.
Functions
System functions
SQLWindows has built-in system functions that you can call in an application: Functions with names that begin with Sal perform tasks such as handling windows, validating fields, managing files, managing lists, and manipulating strings Functions with names that begin with Sql perform database operations
The SQLWindows Function Reference explains the system functions. Chapter 12, SQL Programming, also explains the Sql* functions.
External functions
In a SQLWindows application, you can call external functions in a DLL (Dynamic Link Library). For more, read Chapter 21, Calling External Functions in DLLs.
Internal functions
You write internal functions in the Internal Functions section under Global Declarations.
Window functions
You write window functions in top-level windows (form windows, dialog boxes, and table windows) and in MDI windows. Within the function definition, you can access all variables and objects defined by the window without qualification.
Class functions
You write class functions in the Class Definitions section under Global Declarations. Chapter 8, Object-Oriented Programming, explains class functions.
Writing functions
This section shows how to code internal, window, and class functions. The next sections explain the parts of the outline for a function.
Function Name
This is the name of the internal function. You refer to this name when you call the function.
Description
What the function does.
7-29
Chapter 7
Returns
If the function returns a value, enter the data type and name of the return value. Leave this blank if the function does not return a value. If the result of the function is assigned to a variable, the data type of the variable and the data type of the function return value must match.
Parameters
A list of the parameters that a caller passes to the function. You declare each parameter in the same way as a variable, specifying a variable name and a data type. The caller of a function must pass data that matches parameter's data type. Receive data types. If a function changes the value of the parameter, you must prefix the data type of the parameter with the keyword Receive. For example:
Parameters Receive Number: nVarContainsNumber
Receive data types are passed by reference which means that SQLWindows passes the variable's storage address, and the function can change the value of the variable and that change is visible after the function returns. If you do not code the Receive keyword, the parameter is passed by value which means that SQLWindows only passes a copy of the variable. If the function changes the parameter, the change is not visible after the function returns.
Static Variables
Static variables have values that persist between calls to a function. Their scope is the function where they are defined. You access them in the same way as local variables in a function.
Local Variables
This section contains local variables available to this function only. SQLWindows creates local variables when you call the function and destroys local variables when the function returns. You declare each local variable with a variable name and a data type.
Important: Never use a local variable for a bind or into variable if the SQL statement is prepared in the function and is then executed/fetched outside the function.
Actions
This section contains statements that execute when you call the function. You can code any SAL statements in this section.
The function terminates when: A Return statement executes. The value of the Return expression is returned to the caller. The last statement executes.
Example
Function: DoQuery Description: Prepare and open a SQL query and fetch 1 row Returns Boolean: Parameters ! Sql Handle Sql Handle: hSql ! Sql statement Receive String: strSql Static Variables Local Variables Actions Call SqlPrepare(hSql, strSql) Call SqlOpen(hSql, 'QUERY') Return SqlFetchNext( hSql )
Unqualified reference
Only call a window function with an unqualified reference in: The window object that defines the function A child window contained in the window, regardless of its depth of nesting
Use the same syntax that you use to call an internal function:
Call WindowFunction( parameters )
Object-qualified reference
To call a window function defined by a child of the current window, use an objectqualified reference that qualifies the function name with the object name of the child:
Call childWndName.WndFunc( parameters )
You can also use this syntax to call a function: Defined in the current window
7-31
Chapter 7
Defined in a window unrelated to the current window if the window name is a top-level window or MDI window and only one instance has been created Defined or inherited by the object's class, if the named object is an instance of a class
You can use this type of qualification to call a function for a window with multiple instances.
For example:
Call hWnd.cls..function( parms )
where strAppName is the application to start and strParameters is the command line arguments. A space in strParameters marks the end of one argument (token) and the start of the next (if any). For example, if you pass this string in strParameters:
SalLoadApp( 'example.exe', 'one two three' )
then strArgArray[1-3] contains one, two, and three respectively and nArgCount contains 4. SQLWindows does not pass the spaces to the application. To pass a space in an argument, place a double quote character before and after it. For example, to pass the string Hello there in strArgArray[1] and SQLWindows in strArgArray[2]:
SalLoadApp( 'example.exe', 'Hello" "there ' || 'SQLWindows' )
Those are double quote characters before and after the space between Hello and there. Also, there is a space after there which tells SQLWindows that this is the end of this token and the start of the next.
Clipboard functions
You use the SQLWindows functions in the table below to cut and paste with the Clipboard.
Function name SalEditCut SalEditCanPaste SalEditPaste SalEditPasteString SalTblPasteRows Description Cuts selected text from a data field, multiline field, or table window cell and puts it on the Clipboard. Returns TRUE if there is anything on the Clipboard to paste. Pastes text from the Clipboard to the text insertion point. Pastes text from the Clipboard to a string. Pastes text from the Clipboard to one or more table window rows. The text to be pasted must have tabs separating each column and an end-of-line character at the end of each row. Copies selected text from a data field, multiline field, or table window cell and puts it on the Clipboard. Copies a string to the Clipboard as text. Copies one or more table window rows to the Clipboard. Tabs are placed between columns and an end-of-line character is placed at the end of each row.
7-33
Chapter 7
Resources
You can specify bitmaps, icons, or cursors in the Global Declarations and refer to them with the SalPicSet or SalCursorSet functions. Resources appear in Coding Assistant. This is an example of the Resources section in Global Declarations:
Global Declarations ... Resources Bitmap: Bm1 File Name: bm1.bmp Icon: Icon1 File Name: icon1.ico Cursor: Cur1 File Name: cur1.cur
When you go into run mode at designtime, SQLWindows must be able to find the resources in external files. When you make an *.EXE version of the application, SQLWindows copies the resources from the external files into the application. You do not need to distribute the external files with production versions of an application.
Yielding
Yielding is the ability of an object to give control to another object. SQLWindows has two types of yielding that you can control: Intra-application: between objects in the same SQLWindows application Interapplication: between a SQLWindows application and other Windows applications
Yielding
In the example above, the SAM_Click processing for the pbStart push button calls SalYieldStartMessages for the pbStop push button and then goes into a simple loop. When you run this example, you can click pbStop after clicking pbStart to end the loop. When you click pbStop, SQLWindows suspends the loop for pbStart and executes the SAM_Click processing for pbStop, which sets the bStopped variable to TRUE. After the SAM_Click processing for pbStop completes, SQLWindows
Developing with SQLWindows
7-35
resumes executing the loop for pbStart. Since pbStop set the bStopped variable to TRUE, pbStart breaks the loop and processing ends. When you specify hWndNULL as the parameter for SalYieldStartMessages, SQLWindows lets all other objects receive messages:
Call SalYieldStartMessages( hWndNULL )
If you specify hWndNULL as the parameter, be sure to call SalDisableWindow for any user interface object that you do not want users to access. You can call SalYieldStopMessages to stop yielding to the object specified in the earlier call to SalYieldStartMessages.
When you run this example and click the pbNoYield push button, the application never yields to other applications. You can verify this by starting Microsoft CLOCK.EXE, setting it to analog mode with a second hand, and then running the example above. While the loop above executes, the second hand on the clock does not move because CLOCK.EXE never gets control. Also, if you press Ctrl+Alt+Del while the loop above executes, Windows displays the message this Windows application has stopped responding to the system because not even Windows can get control. Call SalYieldQueryState to find if autoyielding is set to TRUE or FALSE.
Chapter 8
Object-Oriented Programming
This chapter shows how to use SQLWindows object-oriented programming features and covers these topics: Classes, inheritance, and objects Defining classes Creating objects Message actions Instance variables Class variables Class functions
8-1
Chapter 8
Object-Oriented Programming
An object can represent: A tangible concept such as a window An intangible concept such as a checking account
An object is an instance of a class. An object has the data and behavior of its class. Objects that are instances of classes are called user-defined because you specify their behavior in classes.
Class
A class is a blueprint for making objects. In a class, you define a shared data structure and behavior for objects that you later create as instances of the class. You define the same data and behavior for a set of objects without duplicating the code for that data and behavior in each object. The objects of a class share a common data structure and common behavior, but each object in a class has its own private data values.
8-2
Inheritance
Inheritance lets you define new classes in terms of existing classes. A new class that you derive from a base class inherits data and behavior from its base class. As well, a derived class can: Extend the base class by adding new data and behavior. New data and behavior that you add becomes part of the derived class in addition to the data and behavior inherited from the base class. Modify the base class' behavior by redefining inherited behavior.
SQLWindows uses the extended or modified data and behavior for the derived class, but the original data and behavior remain valid for the base class. All of a derived class' data and behavior-new, modified, or inherited-is inherited in turn by its derived classes.
Class inheritance
You can define classes in terms of other classes. One class inherits behavior from one or more other classes. There are two types of inheritance: Single inheritance Multiple inheritance
8-3
Chapter 8
Object-Oriented Programming
Single inheritance
With single inheritance, you derive a class from another class called the base class: Base class
Derived class
The word single in single inheritance means that a class has only one direct base class. Multiple levels of inheritance are allowed. In other words, you can use inheritance to create a class hierarchy: Indirect base class of C; direct base class of B
In the diagram above, class A is a base class of classes B and C: Class A is a direct base class of class B and an indirect base class of class C Class C is directly derived from class B and indirectly derived from class A
8-4
Types of classes
Multiple inheritance
With multiple inheritance, a class has more than one direct base class. In the diagram below, class D inherits behavior from two direct base classes, B and C:
Types of classes
SQLWindows has three types of classes: Functional class Window class General window class
Functional classes
A functional class supplies behavior through its functions. You use functional classes to: Create user-defined variables Define behavior that is shared by more than one window class
8-5
Chapter 8
Object-Oriented Programming
A functional class can be: A base class of another functional class A base class of a window class Derived from another functional class, but not from a window class
Functional class
Functional class
Functional class
Window class
If behavior needs to be shared by more than one window type, you can place the behavior in a functional class and then derive window classes from that functional class. The derived classes inherit the common behavior as well as behavior appropriate to their window type.
Window classes
There is a class for each standard window type. A window class can be: A base class only of the same window class type. For example, a data field class can be the base class only of another data field class Derived from another window class of the same type or from a functional class
Functional class
Window class
Window class
Window class
8-6
Types of objects
These are the inheritance rules for general window classes: A general window class can be a base class of any window class, including other general window classes A general window class can be derived from functional classes or another general window class Multiple inheritance is supported
A general window class cannot be a base class of a functional class You cannot create an instance of a general window class. You can only use a general window class as a base class of a concrete window class.
Types of objects
SQLWindows has three types of objects: Standard window objects User-defined window objects User-defined variables
8-7
Chapter 8
Object-Oriented Programming
You use classes and inheritance to create two types of user-defined objects: Visual objects are user-defined windows A non-visual object is a user-defined variable (UDV)
Objects
Standard window
User-defined window
User-defined variable
User-defined windows
You create a user-defined window as an instance of a window class: Window class
User-defined window
A user-defined window object is like a standard window object because it: Has visual properties (you can see it, unless it is hidden or invisible) Is associated with a window handle that identifies it Can receive Windows messages and SAM_* messages
8-8
Defining classes
User-defined variables
You create a user-defined variable (UDV) as an instance of a functional class: Functional class
User-defined variable
User-defined variables are non-graphic objects. User-defined variables are different from other variables because the only way you can access a user-defined variable is through functions defined in its class. These functions are the user-defined variable's public interface. You can place a user-defined variable in any variables section in the outline. A user-defined variable: Does not have a handle like a user-defined window Cannot respond to messages Has no value and cannot be used in an expression
Defining classes
You define classes in the class definitions section near the bottom of the global declarations in the outline. The example below shows six collapsed classes: cls1, clsMDIFrame1, clsDataEntryForm , clsDlgStandard, and clsDatabaseField.
Global Declarations ... Class Definitions Functional class: cls1 MDI Window Class: clsMDIFrame1 Form Window Class: clsDataEntryForm Dialog Box Class: clsDlgStandard Data Field Class: clsDatabaseField
Later sections explain details about functional classes and window classes.
8-9
Chapter 8
Object-Oriented Programming
Later sections in this chapter explain class functions, class variables, and instance variables. Functional classes cannot inherit from window classes, so functional classes do not have a message actions section.
Attributes
Attributes that you set are inherited by: Derived classes Objects of the class
You can redefine inherited window properties in a derived class or in an object you create as an instance of the class.
For multiple inheritance with conflicting attributes, SQLWindows uses the first nondefault setting it finds and ignores other non-default settings.
Window position
You do not specify position information for a window class. You specify position information when you create a window that is an instance of the class.
Window size
For most class types, you can define the Initial Width and Height of objects. This sets the initial size of an object when created on a form window or dialog box using the Controls palette or Coding Assistant. However, setting the initial width and height does not prevent you from resizing the object with the mouse. Once you resize an object, it no longer inherits the initial width and height from its base class (for example, subsequent changes to the objects base class initial width and height do not affect the objects size). Classes have two additional properties that you can use to control the sizing behavior of objects: Width Editable and Height Editable: Setting these to Yes before creating an object prevents that object from being sized differently than the class definition Setting these to Yes after creating an object forces the size of all existing object to the Initial Height or Initial Width defined by the class
8-11
Chapter 8
Object-Oriented Programming
Later sections in this chapter explain class functions, class variables, instance variables, and message actions.
Window class
Dialog box
Child
There is separate class for each type of window. The definition for each type of window class is almost the same, but there are a few differences.
Outline items
The outline items for child window classes are:
<class type>: <class name> Description: <text> Derived From Class Variables Instance Variables Functions Message Actions
Outline items
These are the outline items for form window, top-level table window, and MDI window classes:
<class type>: <class name> Description: <text> Derived From Menu Toolbar Class Variables Instance Variables Functions Message Actions
8-13
Chapter 8
Object-Oriented Programming
The table below describes the outline items that are unique to these types of window classes:
Item Menu Toolbar Description Default menu definition for window objects which are instances of the class Default toolbar definition for windows which are instances of the class
Later sections in this chapter explain class functions, class variables, instance variables, and message actions.
Menu
If you do not define a menu in the class, then it inherits the complete menu definition of its base class. If you define a menu in an application window class, then it completely overrides an inherited menu definition. With multiple inheritance, if a derived class inherits a menu from more than one direct base class, SQLWindows uses the menu of the first class that defines a menu in the Derived From list and ignores the other menus.
Toolbar
If you do not define a toolbar in the class, then it inherits the complete toolbar definition of its base class. If you define a toolbar in an application window class, then it completely overrides an inherited toolbar definition. With multiple inheritance, if a derived class inherits a toolbar from more than one direct base class, you get an error when you compile unless you define a toolbar in the derived class.
Status bar
Use the Attribute Inspector to specify whether the window has a status bar. The setting that you specify is inherited by derived classes and objects of the class. You can redefine an inherited status bar setting in a derived class or in an objects of the class. With multiple inheritance, if a derived class inherits conflicting settings for the status bar from its base classes, you get an error when you compile. If this happens, use the the Attribute Inspector to clarify the ambiguity in the derived class.
A child item defined in the contents of a class or in a class toolbar is called a class child.
Class children
Add class children to a class definition by: Editing the outline with Coding Assistant OR Editing the outline directly by typing
8-15
Chapter 8
Object-Oriented Programming
A class child can be a standard SQLWindows object or an instance of a class. You can use the Attribute Inspector to change class child attributes. Classes that you derive from a parent class inherit the class children. When you edit a class derived from a base class with class children, SQLWindows displays the class children of the base class. You can edit the attributes of inherited class children. When you add or change a class child, objects that are instances of the parent class are affected immediately. For example, when you add a class child, SQLWindows updates all windows that are instances of the class. You can define the tab order of class children by selecting Layout, Tab Order. SQLWindows uses this tab order when you create an object that is an instance of the class. However, later changes to the tab order in the class definition do not affect an object that is an instance of the class. You must use the Tab Order command on the object. You refer to a class child by its name. For example, this statement is valid for a class child called df1:
Set df1 = 'abc'
SQLWindows uses the same rules for default names for class children as for other objects.
ClassChildName is the name of the class child as declared in the base class (such as df1). ClassName is the name of the class (such as clsForm). ObjectName is the name of the class child instance. By default, ObjectName is the same as the ClassChildName.
You cannot edit ClassName and ClassChildName. You can edit ObjectName. For example, you can change ObjectName when it is a duplicate symbol. You refer to a class child instance by its name. For example, this statement is valid for a class child instance called df1:
Set df1 = 'abc'
Example
In this example, the Class Definitions section of the outline has two classes: A data field class named CdfDateTime. A form window class named CForm1 with two class children. The push button (pb1) is a standard SQLWindows object and the data field (df1) is an instance of the class CdfDateTime.
Class Definitions Data Field Class: CdfDateTime ... Form Window Class: CForm1 ... Contents Pushbutton: pb1 ... CdfDateTime: df1 ...
When you create an instance of the form window class, it appears in the outline as:
CForm1: frm2 ... Contents pb1 from CForm1: pb1 ... df1 from CForm1: df1 ...
8-17
Chapter 8
Object-Oriented Programming
SQLWindows does not propagate child object name changes to existing derived classes or instances. For example if you already have this hierarchy:
CBase
Base class
CDerived
Derived class
frm1
Instance
and you add a data field to CDerived, its default name is df1 in both CDerived and frm1. If you rename the data field in CDerived, the change does not propagate down to frm1 where its name if still df1. If you then add a data field to CBase, its default name is df1 in CBase, CDerived, and frm1. If you rename the data field in CBase, its name does not change in CDerived and frm1. The result is two data fields in frm1 with the same name.
In the example above: Data Field is the type of standard object df1 is the name of the standard data field object
In the example above: ClassDbField is the name of a class. The class name is also called a type. dbField1 is the name of the user-defined object.
When you define an object, you need to specify the object's name and other properties. The next sections describe the properties that you need to specify when you create an object that is an instance of a class.
You can insert a user-defined variable in any variables section of the outline. User-defined variables are specified completely by their classes. The only properties you specify in the outline are the name of its class and the name of the object. This outline fragment is for a user-defined variable (buf1) that is an instance of functional class (ClassBuffer):
Form Window: frmMain ... Window Variables ClassBuffer: buf1 ...
A user-defined variable does not have a value. This means that you cannot use a user-defined variable: As the source or target of a Set statement In any other expression
The only interface for a user-defined variable is through the functions defined in its class. A later section discusses how to call class functions. You can access variables defined in a user-defined variable with object-qualified references:
If emp.salary > 2000
8-19
Chapter 8
Object-Oriented Programming
...
In the SAM_Create action below, a class named ClassBuffer has defined or inherited a function called insert that accepts a number and string as arguments:
Form Window: frmMain ... Window Variables ClassBuffer: buf1 ... Message Actions On SAM_Create Call buf1.insert( 37, 'Hello' )
Passed by reference
SQLWindows always passes user-defined variables by reference. A called function or top-level window can both read and write the user-defined variables instance variables.
The form window declares an array of Employee objects in its Window Variables section:
Form Window: frm1 ...
You access instance variables or functions defined or inherited by a class of a userdefined variable by indexing the array name and qualifying it with a period and the instance variable name. For example:
emp[1].Name emp[2].ChangeSalary( 100000 )
You can also make qualified references and qualified function calls:
hWnd.frm1.emp[1].Name hWnd.frm1.emp[2].ChangeSalary( 100000 )
Assigning UDVs
You can assign one UDV to another using the standard syntax:
Set functionalClassVar2 = functionalClassVar1
functionalClassVar2 and functionalClassVar1 must be the same type, or functionalClassVar2 is of a type from which the type of functionalClassVar1 derives.
Important: Functional class variables are references, not actual values. After you perform an assignment, both variables refer to the same object and changes made through one variable changes the object itself and that change is visible in any other variable that refers to that object.
Example
Assume this class/object hierarchy in the code below: fClassBase1 fClassBase2 fClassDerived1 fClassDerived2
vBase1
vDerived1
vBase2
vDerived2
Functional Class: fClassBase1 ... Functional Class: fClassBase2 ... Functional Class: fClassDerived1 ... Derived From Class: fClassBase1
8-21
Chapter 8
Object-Oriented Programming
This assignment is legal only if vBase1 has most recently been assigned to a value of type vDerived1:
Set vDerived1 = vBase1
If vBase1 is actually a reference to an object of type fClassBase1, the assignment fails at runtime.
If you want to force release of an object safely, assign OBJ_Null to an object variable. This causes the same sequence as going out of scope and causes the referenced object to be freed if there are no other references to it in your application.
Dynamic instantiation
When you declare a UDV, SQLWindows creates it at runtime and you can refer to it. However, you can re-initialize it at any time using the new keyword:
Set functionalClassVar = new functionalClassName
The new keyword takes as an argument the type of object being created and returns a reference to an object of that type. functionalClassVar must be a variable of type functionalClassName.
Object destructors
SQLWindows maintains reference counts on UDVs, destroying them when their count drops to zero. If you want to perform some cleanup operation before an object is destroyed, then you must define a destructor for it. Define a method in the class with the name ObjectDestructor. This method must not have a return type and must not have any parameters, local variables, or static variables. Otherwise, the compiler displays an error message.
Developing with SQLWindows
8-23
Chapter 8
Object-Oriented Programming
SQLWindows destroys objects in three different ways: 1. 2. When the reference count of the object drops to zero. When an object goes out of scope during execution (such as a local variable going out of scope when a function exits) and as execution terminates (this is relevant only to global objects and the objects to which they refer). When the runtime system for the process or thread is terminating.
3.
Warning: When objects are destroyed in either of the first two cases, there is a SAL execution environment in which the ObjectDestructor function (if one exists) can be called. However, objects which are leaked (that is, there are no application references to them during shutdown) are only detected after the SAL execution environment has terminated, and so it is not possible to run the ObjectDestructor function. The memory used by these leaked objects will be freed, but the destructors are not executed.
Warning: Do not refer to globals in an ObjectDestructor method. The order in which globals are destroyed is unpredictable and a global that you refer to can no longer exist. You can control the order that globals are destroyed somewhat by assigning OBJ_Null to them.
SalObj* functions
You can use these SalObj* functions with UDVs.
Function SalObjCreateFromString SalObjGetType SalObjIsDerived SalObjIsNull Description Creates an instance of a functional class name that you specify. Gets the class name of a UDV that you specify. Determines if a UDV is an instance of a specified class. Determines if a UDV is null. For more, read Checking for null objects on page 8-23.
OR Choose a user-defined window in Coding Assistant OR Choose a user-defined window from the Controls palette OR Type a user-defined window directly into the application outline
For child window types, the Controls palette displays the names of child window classes in a list box. For example, when the data field tool is selected, the Controls palette displays Standard for a standard data field and displays the class name for each data field class. Click on one of the names in the list before you place the object. The most-recently selected name is at the top of the list.
Components
A user-defined window object definition has the same components as a standard window definition for the same window type. For example: A user-defined form window and a user-defined data field have message actions sections and you can set their window attributes A user-defined form window has a contents section and a menu section like a standard form window
8-25
Chapter 8
Object-Oriented Programming
A user-defined data field does not have contents or menu sections because a standard data field does not
Data Field Class: cls_df2 Derived From Class: cls_df1 ... Message Actions ...
Data Field Class: cls_df2 Derived From Class: cls_df1 ... Message Actions On SAM_Create ...
An action here for a given message overrides one inherited from the base class
8-27
Chapter 8
Object-Oriented Programming
Data Field Class: cls_df2 Derived From Class: cls_df1 ... Message Actions On SAM_Create ... Call SalSendClassMessage( SAM_Create,...) ...
You usually call SalSendClassMessage in a derived class' own definition of the same message action (as shown in the diagram). This is an example of how a derived class adds behavior to its base class behavior. Normally, this is all that you need because the closest base class usually invokes its own base class' version of the message action. If you need to, you can invoke a message action in a distant base class with SalSendClassMessageNamed:
SalSendClassMessageNamed( clsName, wMessage, wParam, lParam )
SalSendClassMessageNamed is used more often with multiple inheritance. SalSendClassMessage and SalSendClassMessageNamed are synchronous (they send the message directly to the receiving object). There are not corresponding asynchronous (post) calls (which send the message to the Windows message queue).
Data Field Class: cls_df3 Derived From Class: cls_df1 Class: cls_df2 ... Message Actions ...
8-29
Chapter 8
Object-Oriented Programming
Data Field Class: cls_df3 Derived From Class: cls_df1 Class: cls_df2 ... Message Actions On SAM_Create ... On SAM_SetFocus ...
Actions here for messages override those inherited from base classes
If more than one direct base class defines or inherits a message action, you get an error when you compile. You must redefine the message action in the derived class to avoid ambiguity. If a message action is implemented by more than one direct base class, you get an error when you compile Data Field Class: cls_df1 ... Message Actions On SAM_SetFocus ... Data Field Class: cls_df2 ... Message Actions On SAM_SetFocus ...
Data Field Class: cls_df3 Derived From Class: cls_df1 Class: cls_df2 ... Message Actions ...
If you redefine the conflicting message in the derived class and invoke the message in the base class, you can avoid getting an error when you compile. This technique is described in the next section.
8-31
Chapter 8
Object-Oriented Programming
Data Field Class: cls_df3 Derived From Class: cls_df1 Class: cls_df2 ... Message Actions On SAM_Create ... SalSendClassMessageNamed( cls_df2, SAM_Create,...) ...
You usually specify the name of a direct base class and the SalSendClassMessageNamed function finds the closest base class of the specified class that defines the message action. You can also use this function to invoke a message action of a distant base class. You usually call SalSendClassMessageNamed in a derived class' own definition of the same message action (as shown in the diagram). This is an example of how a derived class adds behavior to its base class behavior. SalSendClassMessageNamed is synchronous (it sends the message directly to the receiving object). There is not a corresponding asynchronous (post) call (which sends the message to the Windows message queue).
8-33
Chapter 8
Object-Oriented Programming
Data Field Class: cls_df1 ... Message Actions On SAM_Validate ... Class Object cls_df1: df1 ... Message Actions On SAM_Validate ...
Is not invoked
An action here for a given message overrides one inherited from the base class
You usually call SalSendClassMessage in an object's own definition of the same message action. This is an example of how an object adds behavior to its class behavior. SalSendClassMessage and SalSendClassMessageNamed are synchronous (they send the message directly to the receiving object). There are not corresponding asynchronous (post) calls (which send the message to the Windows message queue).
8-35
Chapter 8
Object-Oriented Programming
Instance variables
Instance variables in a class are replicated for each object that you create. Each object has its own private copy of an instance variable. The diagram below shows three user-defined data fields (df1, df2, and df3) that are instances of the data field class cls_df1. Each instance has its own copy of the instance variable str1.
Data Field Class: cls_df1 ... Instance Variable String: str1 ... Class Object cls_df1: df1 str1 cls_df1: df2 str1 Each object has its own private copy of an instance variable If you define child objects with an instance variable, each child object has its own copy. For example, if you place a data field with an instance variable in a form and then create multiple instances of the form, each instance of the data field has its own copy of the instance variable. cls_df1: df3 str1
Inheritance
An instance variable defined in a derived class hides one with the same name defined or inherited by a base class. If you hide an inherited instance variable, you can still access the base class' version by qualifying the name of the instance variable with the name of the base class. With multiple inheritance, if more than one base class defines or inherits the same instance variable, you get an error when you compile if you refer to the instance variable. Eliminate the ambiguity by qualifying the name of the instance variable with the name of a class.
Internal references
In an object that operates on itself, you can access an instance variable with an unqualified reference.
8-37
Chapter 8
Object-Oriented Programming
SQLWindows searches an objects class for variables before searching the containing object or globals. The search of the objects class includes the classs base classes. Internal References to Instance Variables Form Window Class: cls_fw1 ... Functions Function: cls_func1 ... Set str1 = 'test1' ... Instance Variables String: str1 ...
Form Window Class: cls_fw2 Derived From Class: cls_fw1 Functions Function: cls_func2 ... Set str2 = 'test2' ... Instance Variables String: str2 ... Class Object cls_fw2: frm1 ... Window Functions Function: frm_func3 ... Set str1 = 'test3' Set str2 = 'test4' ...
Unqualified references
Normally, when you refer to a variable within a class you do not need to qualify the reference because the variable is in scope. However, if a method defines a variable with the same name as a variable with class scope (such as an instance variable), the class-scope variable is hidden by the method-scope variable. A hidden variable can be accessed in the method by preceding its name with the keyword this and the dot operator as in this.x. For example:
Functional Class: fTest ... Instance Variables String: str1 String: str2 Functions Function: f1 ... Parameters String: str1 String: str2 ... Actions Set this.str1 = str1 Set this.str2 = str2 ...
In the example above, the objects str1 and str2 variables are set with the values of the methods str1 and str2 parameters respectively.
External references
An object that operates on another object must identify the other object to access one of its instance variables. You can use: An object-qualified reference A fully class-qualified reference
8-39
Chapter 8
Object-Oriented Programming
Object-qualified reference
If one object contains another object, then the containing object can refer to an instance variable in the contained object (target object). Qualify the instance variable name with the name of the target object and a period:
Set obj.var = 'test'
Data Field Class: cls_df1 ... Instance Variables String: str3 ...
Form Window: frm1 ... Window Functions Function: frm1_func1 ... Set df1.str3 = test ... Contents cls_df1: df1 ...
Object-qualified reference
An object-qualified reference tells the compiler to look inside the named object for the instance variable. The compiler searches for an instance variable with the specified name in the these places and in this order: 1. 2. 3. The target object The class of the target object A base class of the target object
You can also use an object-qualified reference to access an instance variable in a containing object. In the diagram on the next page, col1 uses: An object-qualified reference:
Set tbl1.str4 = 'test4'
This tells the compiler to look in its containing object (tbl1) for the variable defined in the class MyTable. An unqualified reference:
Set str4 = 'test4'
This sets the variable defined in the containing object (frm1). An object-qualified reference:
Set frm1.str4 = 'test4'
Child Table Class: MyTable ... Instance Variables String: str4 ...
Form Window: frm1 ... Window Variables String:str4 ... MyTable: tbl1 ... Column: col1 ... ! Sets MyTables variable Set tbl1.str4 = 'test4' ! Sets frm1s variable Set str4 = 'test4' ! Sets frm1s variable Set frm1.str4 = 'test4'
8-41
Chapter 8
Object-Oriented Programming
At runtime, SQLWindows searches for the instance variable in these places and in this order: 1. 2. 3. The object identified by hWnd The object's class A base class of the object's class
If the window is an instance of a class, and both the window and the class define variables with the given name, then SQLWindows accesses the window variable instead of the class variable. If the object you specify does not define or inherit the variable you specify, you get an error when you compile.
Class variables
Class variables are: Allocated only once for a class Shared by all objects in the class
A class variable is like a global variable, but it is only visible to the defining class, derived classes, and objects of the class.
Class variables
The diagram below shows three user-defined data fields (df1, df2, and df3) that are instances of the data field class cls_df1. Each instance shares the same copy of the class variable str1. Data Field Class: cls_df1 Class Variables String: str1 Class Object cls_df1: df1 cls_df1: df2 cls_df1: df3
str1 Each object shares the same copy of a class variable If you define child objects that have class variables, they all share the same copy. For example, if you place a data field with a class variable in a form and then create multiple instances of the form, all instances of the data field share the same value of the class variable.
Inheritance
A class variable defined in a derived class hides one with the same name defined or inherited by a base class. If you hide an inherited class variable, you can still access the base class version by qualifying the name of the class variable with the name of the base class. With multiple inheritance, if more than one base class defines or inherits the same class variable, you get an error when you compile if you refer to the class variable. Eliminate the ambiguity by qualifying the name of the class variable with the name of a class.
8-43
Chapter 8
Object-Oriented Programming
Form Window Class: cls_fw2 Derived From Class: cls_fw1 Functions Function: cls_func2 ... Set str2 = 'test2' ... Class Variables String: str2 ... Class Object cls_fw2: frm1 ... Window Functions Function: frm_func3 ... Set str1 = 'test3' Set str2 = 'test4' ...
Unqualified references
Class functions
Class functions
Functions in classes (along with message actions) determine the behavior of an object of the class. The outline syntax for a class function is the same as an internal function in the global declarations. You can use class functions in both functional classes and in window classes.
Inheritance
A class function defined in a derived class overrides one with the same name defined or inherited by a base class. If you override an inherited class function, you can still access the base class version by qualifying the name of the class function with the name of the base class. With multiple inheritance, if more than one base class defines or inherits the same class function, you get an error when you compile if you refer to the class function. Eliminate the ambiguity by qualifying the name of the class function with the name of a class.
Internal references
In an object that operates on itself, you can use: An unqualified reference A class-qualified reference
8-45
Chapter 8
Object-Oriented Programming
References to Class Functions Form Window Class: cls_fw1 ... Functions Function: cls_func1 ... Function: cls_func2 ... Call cls_func1(...) ...
Form Window Class: cls_fw2 ... Derived From Class: cls_fw1 Functions Function: cls_func3 ... Call cls_func1(...) ... Class Object cls_fw2: frm1 ... Window Functions Function: frm_func4 ... Call cls_fw1.cls_func1(...) Call cls_fw2.cls_func3(...) ...
Unqualified references
Class-qualified references
Unqualified reference
Only use an unqualified reference in: The class that defined the function A class derived from the defining class
Use the same syntax that you use to call an internal function:
Call classFunction( parms )
Class-qualified reference
Use a class-qualified reference: When you normally use an unqualified reference, but you need to eliminate ambiguity. You get an error when you compile if more than one direct base class defines or inherits the same function. When you normally use an unqualified reference, but you need to access an overridden function. In an object that is an instance of the class. In an object that is an instance of a class that is derived from the class.
Qualify the function name with the name of a class and a period:
Call className.classFunction( parms )
Warning: Late binding adds flexibility, but it is significantly slower, so only use it when necessary.
8-47
Chapter 8
Object-Oriented Programming
Form Window Class: cls_fw1 ... Functions Function: cls_func1 ... Call ..cls_func2(...) ... Function: cls_func2 ...
Late-bound unqualified reference: invokes cls_func2 defined in cls_fw2 below, not cls_func2
Form Window Class: cls_fw2 ... Derived From Class: cls_fw1 Functions Function: cls_func2 ... Class Object cls_fw2: frm1 ...
In the example below, ClassA defines the functions F1 and Print. The F1 function calls Print.
If the current object's class is ClassB (derived from ClassA) and it makes the unqualified reference F1(), then the F1 function defined in ClassA executes because ClassB inherits F1 from ClassA. F1 calls ClassB's Print function and not ClassA's because F1 uses a late-bound reference, ..Print():
Form Window Class: ClassA ... Functions Function: F1 ... Actions ... ! Print the current object. If a derived class ! or the current object defines a function ! called Print, call it instead of the one ! defined in this class. Call ..Print() ... Function: Print ... Actions ! Print ClassA's contents. ... Form Window Class: ClassB Derived From Class:ClassA ... Functions Function: Print ... Actions ! Print ClassB's contents. ...
External references
An object that operates on another object must identify the other object to call one of its functions. You can use: A fully object-qualified reference An object-qualified reference A fully class-qualified reference
8-49
Chapter 8
Object-Oriented Programming
Use this syntax when the calling object does not contain the target object. The compiler searches for a function with the specified name in the these places and in this order: 1. 2. 3. The target object The class of the target object A base class of the target object
You do not need to know whether the object defines the function or inherits it. However, within a class you do not usually know the object name, so you can use a fully class-qualified reference (explained later).
Form Window: frm1 ... Window Functions Function: frm1_func1 ... Call df1.cls_func1( ) ... Contents cls_df1:df1 ...
Objectqualified reference
An object-qualified reference tells the compiler to look inside the named object for the function. The compiler searches for a function with the specified name in the these places and in this order: 1. 2. 3. The target object The class of the target object A base class of the target object
You can also use an object-qualified reference to call a function in a containing object. In the diagram on the next page, col1 uses: An object-qualified reference:
Call tbl1.F()
This tells the compiler to look in its containing object (tbl1) for the function defined in the class MyTable. An unqualified reference:
Call F()
This calls the function defined in the containing object (Form1). An object-qualified reference:
Call Form1.F()
Form Window: Form1 ... Function: F ... MyTable: tbl1 ... Column:col1 ... ! Calls MyTables function Call tbl1.F( ) ! Calls Form1s function Call F( ) ! Calls Form1s function Call Form1.F( )
8-51
Chapter 8
Object-Oriented Programming
This reference is more efficient than the late-bound references in the next sections.
For example:
Call hWnd.cls..function( parms )
At runtime, SQLWindows searches for the function in this order: 1. 2. 3. 4. The object identified by hWnd The class (cls2) of the object identified by hWnd, assuming cls2 is derived from cls Class (cls) A base class of cls
This is the least-efficient reference and is significantly slower than the other types of references.
8-53
Chapter 8
Object-Oriented Programming
For SAL statements in a class, an object name is not available so you can use MyValue instead of an object name. For example:
Data Field Class: ClassStringField ... Functions SetValue ... Parameters String: strValue Actions Set MyValue = strValue ...
SalObjIsValidClassName
Call SalObjIsValidClassName to determine if the specified class name exists in the outline.
SqlVarSetup
Before Gupta performs a SQL execute or fetch operation, it compiles the bind and into variables which is looking up the symbols and generating the code that gets the values (for bind variables) or that fetches the values (for an into variable). By default, Gupta compiles: Bind variables at execute time Into variables at fetch time
You can change this default behavior by calling SqlVarSetup which saves the current execution context. When you execute or fetch later, Gupta uses that execution context to resolve references to bind variables and into variables. This means that you can use bind and into variables in a different context than where you call Sql* functions. You must call SqlPrepare for the Sql Handle before you call SqlVarSetup. Use this function to write: Global functions that store bind and into variables in local variables
SqlVarSetup
A hierarchy of classes where a base class can prepare and fetch and a derived class can specify the into variables
This function does not affect the lifetime of the bind and into variables and does not guarantee that the variables will exist when you execute or fetch. You must ensure that the variables are still valid when you use them.
8-55
Chapter 9
Messages
This chapter explains: Types of messages How you process messages Each SAM_* message
9-1
Chapter 9
Messages
About messages
SQLWindows sends a message to an object when an event happens. An application processes a message by taking an action. Messages drive a SQLWindows application. Actions are associated with objects (such as dialog boxes, push buttons, and check boxes). At runtime, actions execute based on the messages that the objects receive. Messages are triggered by: Keyboard actions Mouse actions A timer The application
Types of messages
There are three types of messages: SQLWindows Application Messages (SAM_*) Windows Messages (WM_*) Application-defined messages
Application-defined messages
For a complete list of the SAM_* messages that each object receives, read SAM_* summary on page 9-44
Application-defined messages
The application itself can also send messages to its objects or to other applications by calling SalSendMsg, SalPostMsg, and SalSendMsgToChildren. Messages can be posted or sent: Posted (queued) messages are placed in an application's message queue. If there are other messages in the application's queue, the object does not receive the message until the application processes the messages ahead of it. Sent (nonqueued) messages are sent to an object directly. You send a nonqueued message when you want the application to do something immediately.
SalPostMsg queues the message and returns immediately. SalSendMsg sends the message directly to an object and returns only after the receiver processes the message. For more about these functions, read the SQLWindows Function Reference or the online help. Define values for application-defined messages in the User part of Constants in Global Declarations. Constants you define with the PM_* or PAM_* prefix appear automatically in Coding Assistant. (PM means Program Message and PAM means Program Application Message.)
9-3
Chapter 9
Messages
Constants that you define for messages must be greater than the SAM_User constant. Define message constants like this:
Global Declarations System ... User Number: PAM_Ok = SAM_User + 2 Number: PAM_Cancel = SAM_User + 4
Processing messages
Most objects have a Message Actions section where you code statements to process messages. For example, a SAM_Validate messagesent when the user changes a value in a field and then clicks or tabs out of itcan invoke field validation actions in the Message Actions section under an On SAM_Validate statement. An event can cause several messages to be sent, but not all of them are relevant to an application. For example, when the user moves the input focus after editing a data field or table window column, SAM_Validate, SAM_KillFocus, and SAM_SetFocus are all sent, although an application does not process all of them. You code On statements in the Application Actions section and in Message Actions sections.
9-4
System variables
The statements under an On statement process a message. The example below shows how the On statement processes the SAM_Click message in the Message Actions section of a push button. Each time the user clicks the push button, the actions under SAM_Click execute:
Data Field: df1 ... Pushbutton: pb1 ... Message Actions On SAM_Click Set df1= Hello World
For more about the On statement, read On on page 7-23 For some SAM_* messages, SQLWindows expects you to Return a value to control processing. After executing a Return statement, message processing ends. In other words, SQLWindows ignores any statements after a Return statement.
System variables
You use these system variables to process messages: hWndForm hWndItem hWndMDI wParam lParam MyValue
hWndForm
This system variable contains the handle of the top-level window (form window, dialog box, or table window) that received the message. You can use this variable to pass a window handle to a function.
hWndItem
This system variable contains the handle of the child object that received the message. For example, when an application processes the SAM_Click message for a push button, hWndItem contains the handle of the push button. You can use this variable to pass a window handle to a function.
9-5
Chapter 9
Messages
SAM reference
The sections on the following pages describe each SAM_* message.
SAM_Activate
Sent to Event Top-level windows and MDI windows When the window is activated or deactivated. The wParam indicates whether the window is being activated or deactivated.
Message Variables
hWndForm hWndItem wParam Handle of top-level window Object handle Whether the window is being activated or deactivated: TRUE FALSE lParam Not used = Activated = Deactivated
Example
None
SAM_AnyEdit
Sent to Event Processing Data field, combo box, multiline field, and table window column The user changes the field's value. For example, an editable data field receives one SAM_AnyEdit message for each keystroke as the user enters data. Check the value of the field as the user enters it.
9-6
SAM_AppExit
Example
Data Field: dfCompanyId ... Message Actions On SAM_AnyEdit ! Check if last character the user entered is a valid number. ! If not valid, strip it off and let user re-enter the character. If SalIsValidInteger( dfCompanyId ) = FALSE ! StripLastCharacter is an internal function that ! discards any invalid characters that the user entered. Call StripLastCharacter( dfCompanyId )
SAM_AppExit
Sent to Event Application Actions section of the outline After all of the application's windows have been destroyed (closed). When the user exits an application or you go from user mode to design mode, the application's form windows, table windows, and dialog boxes are destroyed. After the windows are destroyed, SQLWindows sends SAM_AppExit. This is the last message SQLWindows sends to an application. Processing Perform cleanup tasks such as disconnecting from the database.
Important: SQLWindows sends SAM_AppExit after destroying all windows. Do not refer to windows in the message processing statements.
Message Variables
hWndForm hWndItem wParam lParam Not used Not used Not used Not used
9-7
Chapter 9
Messages
Example
Application Actions On SAM_AppExit ! Leaving application. Disconnect Sql Handle. Call SqlDisconnect( hSql )
SAM_AppStartup
Sent to Event Application Actions section of the outline Before the application's windows are created, including those created automatically at runtime. This is the first message SQLWindows sends to an application. Processing Perform initialization tasks such as displaying a dialog box where the user logs on to a database.
Message Variables
hWndForm hWndItem wParam lParam Not used Not used Not used Not used
Example
Application Actions On SAM_AppStartup Set SqlDatabase = 'CLIENTS' Set SqlUser = 'SYSADM' Set SqlPassword = 'SYSADM' When SqlError Call SalMessageBox( 'Could not connect to database', 'Customer List', MB_Ok ) Return FALSE If NOT SqlConnect( hSql ) Call SalQuit
SAM_CacheFull
Sent to Table window A table window receives SAM_CacheFull when a user scrolls if Maximum Rows in Memory is less than the number of rows to display and Discardable is No. The minimum value for rows in memory is 78, regardless of the setting of Maximum Rows in Memory. Event A row is to be fetched, but the table window cache is full and no rows can be discarded.
9-8
SAM_CaptionDoubleClick
Processing
The meaning of SAM_CacheFull depends on whether the table window has a discardable cache: If the cache is not discardable, SAM_CacheFull means that no more data can be loaded in the table window If the cache is discardable, SAM_CacheFull means that there are too many rows of modified data and that they must be saved
Message Variables
hWndForm hWndItem wParam lParam Handle of table window Not used Not used Not used
Example
Table Window: twTabWinEmployee ... Message Actions On SAM_CacheFull ! Cache is full! User cannot change any more rows in ! the table window. Call SalMessageBox( 'Please save changes to Table Window.', 'Customer List', MN_Ok | MB_IconHand ) Return FALSE
SAM_CaptionDoubleClick
Sent to Event Processing Table window and column The user double-clicks a column title. Retrieve the window handle of the column in the wParam with SalNumberToWindowHandle.
9-9
Chapter 9
Messages
For a column:
hWndForm hWndItem wParam lParam Handle of table window Column handle Column handle Not used
Example
Table Window: tbl1 ... Message Actions On SAM_CaptionDoubleClick Set hWndCol = SalNumberToWindowHandle( wParam ) Call SalTblSetColumnFlags( hWndCol, COL_Selected, TRUE ) Set nMaxLength = 15 Set nColLength = SalTblGetColumnTitle( hWndCol, sColTitle, nMaxLength ) Call SalMessageBox( 'You double-clicked the title ' || sColTitle, 'Info', MB_Ok ) Call SalTblSetColumnFlags( hWndCol, COL_Selected, FALSE )
SAM_Click
Sent to Table window, table window column, push button, radio button, check box, option button, combo box, list box, and picture
List Box
SQLWindows sends SAM_Click to a list box when a user: Clicks an entry, even if the list box entry is already selected Double-clicks it; the list box receives SAM_Click followed by a SAM_DoubleClick
SAM_Click
SQLWindows does not send SAM_Click when a user clicks: An empty list box A part of the list box that contains no entries
Combo Box
SQLWindows sends SAM_Click to a combo box when a user clicks an entry in the list box, even if the entry is already selected. SQLWindows does not send SAM_Click to a combo box when a user clicks the: Data field part of a combo box The down arrow that displays the list box
Radio Button
SQLWindows sends SAM_Click to a currently-unselected radio button when a user clicks it. If the radio button is already selected, SQLWindows does not send SAM_Click. Event The user clicks the object with the mouse or performs a keyboard action (such as pressing an arrow key) that simulates a mouse click.
For a picture:
hWndForm hWndItem wParam lParam Handle of form window or dialog box Handle of item receiving message X coordinate in the picture where the user clicked Y coordinate in the picture where the user clicked
For a push button, radio button, list box, option button, or combo box:
hWndForm hWndItem wParam lParam Handle of form window or dialog box Handle of object receiving message Not used Not used
Example
Developing with SQLWindows
9-11
Chapter 9
Messages
Pushbutton: pbAddNewCustomer ... Message Actions On SAM_Click ! Push button to add a new customer to the database Call SqlImmediate( 'INSERT INTO company (name,address,phone ) VALUES ( :CompanyName, :CompanyAddress, :PhoneNumber ) ' ) Call SalMessageBox( 'Customer has been added!', Customer List', MB_Ok )
SAM_Close
Sent to Event Form window, dialog box, top-level table window, and MDI window The user chooses the Close command from the window's system menu or doubleclicks the window's system menu. A form window, dialog box, or top-level table window receives SAM_Close when the user closes it with the Close item in the system menu. A child table window does not receive SAM_Close. SQLWindows does not send SAM_Close when you call SalQuit, SalEndDialog, or SalDestroyWindow. Processing Warn the user or perform other tasks. For example, check a form window or table window to see if there is data that needs to be saved in a database. Call SalMessageBox when a modal or system modal dialog box receives SAM_Close to prevent a user from accidentally closing the dialog box. Default processing closes the dialog box. If a user selects the Close menu item in a dialog boxs system menu and the application does not process SAM_Close, SQLWindows implicitly calls SalEndDialog( hWnd, 0 ). Message Variables
hWndForm hWndItem wParam lParam Handle of current window Not used Not used Not used
SAM_ColumnSelectClick
Example
Dialog Box: dlgEmployees ... Contents Data Field: dfCompanyName ... Message Actions On SAM_Close Set nRetValue = SalMessageBox( 'Are you sure you want to close this window?', 'Customer List', MB_YesNo ) If nRetValue = IDNO ! Return FALSE to prevent the window from being destroyed Return FALSE
SAM_ColumnSelectClick
Sent to Event Table window and column The user selects or deselects a column by clicking the column title. To receive this message, you must set TBL_Flag_SelectableCols to TRUE by calling SalTblSetTableFlags (it is FALSE by default). Processing Retrieve the window handle of the column in wParam with SalNumberToWindowHandle.
Message Variables
hWndForm hWndItem wParam lParam Handle of table window Table window handle in table window message actions, column handle in column message actions Column handle Not used
Example
Table Window: tbl1 ... Message Actions On SAM_ColumnSelectClick Set hWndCol = SalNumberToWindowHandle( wParam ) Set nMaxLength = 15 Set nColLength = SalTblGetColumnTitle( hWndCol, sColTitle, nMaxLength ) Call SalMessageBox( 'You selected the title ' || sColTitle, 'Info' , MB_Ok )
9-13
Chapter 9
Messages
SAM_ContextMenu
Sent to Event Window The user right-clicks a top-level or child window, or presses Shift+F10. Note: Most applications do not need to process this message. Instead, call SalContextMenuSetPopup to define a popup menu that displays automatically when a window receives SAM_ContextMenu. Process this message by calling SalTrackPopupMenu to display a popup menu. Use the TPM_ContextMenu flag with SalTrackPopupMenu for this purpose. Message Variable
hWndForm hWndItem wParam lParam Handle of table window Handle of table window X coordinate in screen pixels relative to the upper left corner of the screen Y coordinate in screen pixels relative to the upper left corner of the screen
No Example
SAM_CornerClick
Sent to Event Table window The user clicks the title of a row header. The row header is a non-editable column on the left side of a table window.
Message Variable
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Table window context row (first row is 0, second row is 1, and so on)
Example
Table Window: tbl1 ... Message Actions On SAM_CornerClick Set nContextRowLength = SalNumberToStr( lParam, 0, sContextRow ) Call SalMessageBox( 'You clicked the row header title context row: ' || sContextRow ,'Info' , MB_Ok )
SAM_CornerDoubleClick
Sent to Table window
SAM_CornerDoubleClick
Event
The user double-clicks the title of a row header. The row header is a non-editable column on the left side of a table window.
Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Table window context row (first row is 0, second row is 1, and so on)
9-15
Chapter 9
Messages
Example
Table Window: tbl1 ... Message Actions On SAM_CornerDoubleClick Set nContextRowLength = SalNumberToStr( lParam, 0, sContextRow ) Call SalMessageBox( 'You doubled-clicked the row header title context row: ' || sContextRow ,'Info' , MB_Ok )
SAM_CountRows
Sent to Event Processing A table window with a dynamic scroll range The user scrolls to the last row in a table window (such as by pressing the End key). Return the number of rows in the table window. For example, count the number of rows in the result set. If the application does not process this message, SAM_FetchRow messages are used to determine the last row in the table with a TBL_NoMoreRows return from the message. However, the application performs better if you process SAM_CountRows. Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Not used
Example
Table Window: tblEmployee ... Message Actions On SAM_Create Call SqlPrepare( hSqlPrimary, strSqlTableWindow ) Call SqlExecute( hSqlPrimary ) Call SalTblReset( hWndForm ) Call SalTblSetRange( hWndForm, 0, TBL_MaxRow ) On SAM_CountRows ! Count the number of rows in the result set. Call SqlGetResultSetCount( hSqlPrimary, nRowCount ) Return nRowCount
SAM_Create
SAM_Create
Sent to Event Top-level window and its children; MDI window After the top-level window and its children have been created, but before the windows are made visible. For example, SQLWindows follow these steps to create a form window that has data fields: 1. 2. Create the form window Create each of its data fields
After SQLWindows creates all the windows, but before making them visible, SQLWindows sends SAM_Create to the objects in this order: 1. 2. The form window Each of the form's data fields
After SQLWindows sends the SAM_Create messages, SQLWindows makes the form window and data fields visible. Processing Perform initialization tasks such as setting data fields or populating table windows and list boxes with data from a database.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object being created Not used Not used
Example
Data Field: dfCompanyName ... Message Actions On SAM_Create ! Fill company name data field when window is created Set dfCompanyName = 'Gupta Technologies LLC'
SAM_CreateComplete
Sent to Event Processing Windows with contents: top-level windows and child table windows After creating the windows children and displaying the window and its children. Perform initialization tasks such as setting data fields or populating table windows and list boxes with data from a database.
9-17
Chapter 9
Messages
Message Variables
hWndForm hWndItem wParam lParam Handle of parent window Handle of object being created Not used Not used
Example
None
SAM_CustControlCmd
Sent to Event Processing Custom control When the parent window receives a notification message (WM_COMMAND) from the custom control. SQLWindows ignores any value that you Return when you process this message.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of custom control. Notification message number Not used
Example
None
SAM_Destroy
Sent to Event Top-level window and its children; MDI window Just before the windows are destroyed. SQLWindows sends SAM_Destroy messages after sending SAM_Close to the toplevel window. For example, if a form window has data fields, SQLWindows sends the messages to the objects in this order: 1. 2. 3. SAM_Close to the form window SAM_Destroy to the form window SAM_Destroy to each of the form window's child windows
After sending the SAM_Destroy messages, SQLWindows destroys the top-level window and child windows.
SAM_Dock
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object being destroyed Not used Not used
Example
Table Window: twTabWinEmployee ... Message Actions On SAM_Destroy ! Set a global Boolean variable informing the ! application this window is no longer active Set bEmployeeWinDestroyed = TRUE
SAM_Dock
Sent to Event MDI window, form window, top-level table window Sent to a top-level window just before a child dialog box changes its current docking orientation to the parent window. This message precedes SAM_DockChange, which is sent to the dialog box. None.
Processing
Message Variables
hWndForm hWndItem wParam lParam Handle of dialog box whose docking orientation is changing. Contains two items. The low-order word of lParam contains the dialogs current docking status/orientation and the high-order word of lParam contains the new docking status/orientation. Handle of top-level window.
See also
For detailed discussions of docking capabilities and orientations, read the SQLWindows Function Reference manual, referring to functions SalDlgSetDockStatus and SalWindowGet DockSettings. Also read about the docking attributes of top-level windows in Chapter 5, SQLWindows Objects.
SAM_DockChange
Sent to Event Dialog box This message is only sent to a dialog box if that dialog box has attribute "docking enabled" TRUE. Sent to a dialog box after a docking change orientation is completed.
9-19
Chapter 9
Messages
Processing
Message Variables
hWndForm hWndItem wParam lParam Handle of dialog box whose docking orientation is changing. Handle of dialog box whose docking orientation is changing. Not used. Contains two items. The low-order word of lParam contains the current docking status/orientation and the high-order word of lParam contains the new docking status/orientation.
Note: When processing the actions of this message, do not call SalModalDialog or SalSetWindowSize. Calls to these functions will cause an event loop that will freeze your application.
See also
For detailed discussions of docking capabilities and orientations, read the SQLWindows Function Reference manual, referring to functions SalDlgSetDockStatus and SalWindowGetDockSettings. Also read about the docking attributes of top-level windows in Chapter 5, SQLWindows Objects.
SAM_DoubleClick
Sent to List box, combo box, table window, column, and picture SQLWindows only sends SAM_DoubleClick to a combo box when you set its Always Show List property to Yes in the Attribute Inspector. Event The user double-clicks the object. When the user double-clicks a row in a table window or list box, SQLWindows sends the messages in this order: 1. 2. 3. Processing Two SAM_Click messages SAM_DoubleClick to the table window column or list box SAM_DoubleClick to the table window
A double-click can select a row in a list box or table window and then start an action for that row. For example, a list box can contain a list of file names. When the user double-clicks a name in the list box, the application opens the file.
SAM_DragCanAutoStart
wParam lParam
For a picture:
hWndForm hWndItem wParam lParam Handle of form window or dialog box Handle of picture receiving message X coordinate in the picture where the user clicked Y coordinate in the picture where the user clicked
Example
List Box: lbEmployee ... Message Actions On SAM_DoubleClick ! When user double-clicks a row, get the index of that ! row and put row text in dfEmployeeName Set nIndex = SalListQuerySelection( lbEmployee ) Call SalListQueryText( lbEmployee, nIndex, dfEmployeeName )
SAM_DragCanAutoStart
Sent to Event Processing Top-level window, data field, multiline field, list box, combo box, and picture SQLWindows sends this message to ask a window whether it wants auto dragging. Return TRUE to enable auto dragging. If you do not process this message or you return FALSE, then SQLWindows does not enable auto dragging. SQLWindows starts drag mode automatically when the application returns TRUE from SAM_DragCanAutoStart. This is the minimum that an application does to let a
9-21
Chapter 9
Messages
user drag from a window. However, you must write additional code to do something when the user drops in a window. Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message X coordinate in the window Y coordinate in the window
Example
List Box: lb1 ... Message Actions On SAM_DragCanAutoStart If SalListQuerySelection( hWndItem ) != LB_Err Return TRUE Else Return FALSE
SAM_DragDrop
Sent to Event Top-level window, data field, multiline field, list box, combo box, and picture The user drops the mouse on a target window.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Handle of a source window. Not used
Example
Data Field: df1 ... Message Actions On SAM_DragDrop Set hWndSrc = SalNumberToWindowHandle( wParam ) If hWndSrc != hWndItem AND SalParentWindow( hWndSrc ) = hWndForm Call SalGetWindowText( hWndSrc, sSource, 1000 ) Call SalSetWindowText( hWndItem, sSource )
SAM_DragEnd
Sent to Event Top-level window, data field, multiline field, list box, combo box, and picture Drag mode has ended.
SAM_DragEnter
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Not used Not used
Example
None
SAM_DragEnter
Sent to Event Processing Top-level window, data field, multiline field, list box, combo box, and picture The user moved the mouse into this target window while in drag mode. Change the mouse pointer to an appropriate symbol.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Handle of a source window Not used
Example
None
SAM_DragExit
Sent to Event Top-level window, data field, multiline field, list box, combo box, and picture The user moved the mouse out of this target window while in drag mode.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Handle of a source window Not used
Example
None
9-23
Chapter 9
Messages
SAM_DragMove
Sent to Event Top-level window, data field, multiline field, list box, combo box, and picture The user moved the mouse within this target window while in drag mode.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Handle of a source window Not used
Example
None
SAM_DragNotify
Sent to Event Top-level window, data field, multiline field, list box, combo box, and picture A mouse action happened in drag mode.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Handle of a target window One of these constants: SAM_DragEnter SAM_DragDrop SAM_DragExit SAM_DragMove The user moved the mouse into a target window The user dropped the mouse in a target window The user moved the mouse out of a target window The user moved the mouse within a target window
Example
Global Declarations ... Class Definitions Picture Class: clsDragPict ... Message Actions On SAM_DragNotify Set hWndTarget = SalNumberToWindowHandle( wParam ) Select Case lParam Case SAM_DragEnter If SalGetType( hWndTarget ) = TYPE_Picture Call SalDragDropEnableDrop( ) Else
SAM_DragStart
Call SalDragDropDisableDrop( ) Break Case SAM_DragDrop If hWndTarget != hWndItem AND SalGetType( hWndTarget ) = TYPE_Picture Set nColorSource = SalColorGet( hWndItem, COLOR_IndexWindow ) Set nColorTarget = SalColorGet( hWndTarget, COLOR_IndexWindow ) Call SalColorSet( hWndTarget, COLOR_IndexWindow, nColorSource ) Call SalColorSet( hWndItem, COLOR_IndexWindow,nColorTarget ) Break
SAM_DragStart
Sent to Event Top-level window, data field, multiline field, list box, combo box, and picture Drag mode has started.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Y coordinate in the window X coordinate in the window
Example
List Box: lb1 ... Message Actions On SAM_DragStart ! Store the current selection as window text so we can ! use it on the drop Call SalListQueryText( hWndItem, SalListQuerySelection( hWndItem ), sList ) Call SalSetWindowText( hWndItem, sList )
9-25
Chapter 9
Messages
SAM_DropDown
Sent to Event Combo box The user clicks the down arrow. SQLWindows sends this message before the list box of the combo box drops down.
Message Variables
hWndForm hWndItem wParam lParam Handle of form window or dialog box Handle of combo box Not used Not used
Example
None
SAM_DropFiles
Sent to Column, data field, multiline field, list box, combo box, picture, and custom control SQLWindows only sends this message to windows that have enabled file dropping. Event Processing The user dropped a file or files from Explorer or File Manager on the object. Call the SalDropFilesQueryFiles function to get the names of the files dropped on the object. SalDropFilesQueryFiles returns the number of files that were dropped or 0 if the function fails. You can only call SalDropFilesQueryFiles during SAM_DropFiles message processing. Call the SalDropFilesQueryPoint function to get the location of the mouse in the window where the user dropped the file or files. By default, file dropping is enabled for editable picture objects. To avoid this default processing, execute a Return statement in the SAM_DropFiles message processing for a picture object and do not perform any other processing. For example, when a user drops on a picture, you can call SalDropFilesQueryFiles or SalDropFilesQueryPoint in the SAM_DropFiles message processing and decide whether to process what the user is dropping or to ignore it by executing a Return statement with no other processing. You can completely disable file dropping for an editable picture by calling the SalDropFilesAcceptFiles function. The default for editable picture windows is TRUE. The default for all other window types is FALSE.
SAM_EndCellTab
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Not used Not used
Example
None
SAM_EndCellTab
Sent to Event Processing Table window The user tries to tab past the last editable cell. You can use this message to automate row insertion. When the table window receives this message, add a blank row. By default, if you do not explicitly return a value, SQLWindows returns FALSE and selects the row. Return TRUE to prevent this behavior. Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Table window context row that the user is trying to tab away from (first row is 0, second row is 1, and so on)
Example
On SAM_EndCellTab If IDYES = SalMessageBox(Move to next row?, What Do You Want to Do?, MB_IconQuestion | MB_YesNo ) Set nNewRow = SalTblInsertRow( hWndTbl, TBL_MaxRow ) Call SalTblSetFocusCell( hWndTbl, nNewRow, col1, 0, 0 ) Return TRUE Else ! Null leg: ! If we dont explicitly return a value, SQLWindows returns ! FALSE and selects the current row.
9-27
Chapter 9
Messages
SAM_FetchDone
Sent to Event Table window SalTblPopulate, using the TBL_FillAllBackground population method, has completed populating the table window.
Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Not used
Example
None
SAM_FetchRow
Sent to Event Table window Before a row must be copied into the table window cache. When you populate a table window, SQLWindows sends SAM_FetchRow for every row in the table window that needs to be displayed. When the user scrolls the table window, SQLWindows sends more SAM_FetchRow messages to the table window for rows not in the cache that need to be displayed.
Note: SQLWindows sends SAM_FetchRow before populating the row and SAM_FetchRowDone after populating the row.
Processing
You usually call SqlFetchRow to fetch the row into the table window based on the row number in lParam.
Note: Setting a breakpoint on a statement that executes while processing SAM_FetchRow can cause incomplete painting of a table window.
SAM_FetchRowDone
Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Row number of row to be affected
Example
Table Window: twTabWinEmployee ... Message Actions On SAM_FetchRow ! The table window needs a row from the database If SqlFetchRow( hSql, lParam, nFetch ) If nFetch = FETCH_Delete Return TBL_RowDeleted Else Return TBL_RowFetched Else Return TBL_NoMoreRows
SAM_FetchRowDone
Sent to Event Table window After SQLWindows has populated a row.
Note: SQLWindows sends SAM_FetchRow before populating the row and SAM_FetchRowDone after populating the row.
Processing
Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Row number that was populated
Example
None
9-29
Chapter 9
Messages
SAM_FieldEdit
Important: Use SAM_Validate instead of SAM_FieldEdit. SAM_FieldEdit is provided for compatibility with earlier SQLWindows versions.
Sent to Event
A table window, column, data field, combo box, and multiline field The user changes the value and then moves the focus away from the item. For example, if a user enters a value in a data field and then presses the Tab key or clicks the mouse to move to another field, SQLWindows sends SAM_FieldEdit to the data field. SAM_FieldEdit is different from SAM_AnyEdit: SAM_AnyEdit is sent for every change that the user makes to an object SAM_FieldEdit is sent once when the user tries to leave an object that has been changed
Processing
Example
None
SAM_Help
Sent to Event Processing Top-level window and MDI window The user pressed the F1 key. Call SalWinHelp to start an application help system that you created. The wParam contains the handle of the child object that has the focus that you can use for a context-sensitive help system.
SAM_KillFocus
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of top-level window Handle of child object with the focus Not used
Example
None
SAM_KillFocus
Sent to Table window, data field, multiline field, push button, radio button, check box, option button, combo box, list box, column, and horizontal and vertical scroll bar When the focus changes, SQLWindows first sends SAM_KillFocus to the object losing the focus and then sends SAM_SetFocus to the object getting the focus. For focus changes in table windows: Event The wParam of SAM_KillFocus is the window handle of the column getting the focus and the lParam is the row number getting the focus The wParam of SAM_SetFocus is the window handle of the column losing the focus and the lParam is the row number losing the focus
As the user moves the focus off an object. SQLWindows sends this message whether or not the used changed data in the object.
Warning: You cannot call SalSetFocus in SAM_KillFocus processing because of a Windows limitation.
Handle of top-level window Handle of object receiving message Handle of object getting focus Not used
9-31
Chapter 9
Messages
Example
Data Field: dfHireDate ... Message Actions On SAM_KillFocus ! When user exits this data field, disable push button ! pbPartialSearch Call SalDisableWindow( pbPartialSearch )
SAM_Print
Sent to Event Processing Form window, data field, multiline field, combo box, and push button SQLWindows is printing the object. Some applications supplement window painting by drawing on the display. To perform the same drawing when printing an object, call SalPrtExtractRect to draw on the object that is printing. SQLWindows does not have window painting functions. You must define the Windows DLL GDI32.EXE as an external library and call its functions. Message Variables
hWndForm hWndItem wParam lParam Form window handle Handle of the object printing Printer HDC (display context handle) Rectangle that is printing
Example
This example draws a diagonal line when a form window is printing. The MoveTo and LineTo functions are in the DLL GDI.EXE.
On SAM_Print Call SalPrtExtractRect( hWndForm, lParam, nLeft, nTop, nRight, nBottom ) Call MoveTo( wParam, nLeft, nTop ) Call LineTo( wParam, nRight, nBottom )
SAM_ReportFetchInit
Sent to Event Top-level window or MDI window that started a report When Report SQLWindows is ready to format the first page of a report. Report SQLWindows sends SAM_ReportFetchInit after sending SAM_ReportStart. SAM_ReportFetchInit means that Report SQLWindows is ready to receive data from the application. Processing If the report contains data from a database, call SqlExecute. If SqlExecute returns TRUE, then Return TRUE.
SAM_ReportFetchNext
If you Return FALSE, the report stops. If you do not Return a value, or you do not process the message, the report continues. Message Variables
hWndForm hWndItem wParam lParam Not used Not used Handle of the window that started the report Not used
Example
Form Window: frmMain ... Message Actions On SAM_ReportFetchInit If NOT SqlPrepare( hSql, SQL_Select ) Return FALSE Else If NOT SqlExecute( hSql ) Return FALSE Else Return TRUE
SAM_ReportFetchNext
Sent to Event Processing Top-level window or MDI window that started a report When Report SQLWindows is ready for the next row of data from the application. Report Builder sends SAM_ReportFetchNext after SAM_ReportFetchInit. If an application fetches data from a database for a report, call SqlFetchNext to get the next row. If the fetch is successful, return TRUE. If there is no more data, return FALSE.
Message Variables
hWndForm hWndItem wParam lParam Not used Not used Handle of the window that started the report Not used
9-33
Chapter 9
Messages
Example
Form Window: frmMainForm ... Message Actions On SAM_ReportFetchNext ! Get next row from database and ! send it to Report Builder If SqlFetchNext( hSql, nRetVal ) Return TRUE Else Return FALSE
SAM_ReportFinish
Sent to Event Processing Top-level window or MDI window that started a report Report Builder sends SAM_ReportFinish when the report is finished. Perform cleanup tasks. Report Builder ignores any value you Return in SAM_ReportFinish processing. Message Variables
hWndForm hWndItem wParam lParam Not used Not used Handle of the window that started the report Not used
Example
Form Window: frmMainForm ... Message Actions On SAM_ReportFinish Call SqlDisconnect( hSql )
SAM_ReportNotify
Sent to Event Processing Top-level window or MDI window that started a report Report Builder is ready to format a part of a report. Check the lParam to find the part of the report Report Builder is ready to format. For more, read RPT_Err* constants on page 14-9. Report Builder ignores any value that you return during SAM_ReportNotify processing.
SAM_ReportStart
Message Variables
hWndForm hWndItem wParam lParam Not used Not used Handle of the window that started the report RPT_Before* constant (see table above)
Example
This example checks the lParam to find if Report Builder is ready to process the first break header:
On SAM_ReportNotify If lParam = RPT_BeforeBreakHeader1 ! strPic contains an image. Set the report variable ! named PICTURE to the contents of strPic. Call SalReportSetObjectVar( frmMain, 'PICTURE', strPic )
SAM_ReportStart
Sent to Event Top-level window or MDI window that started a report Report Builder sends SAM_ReportStart after the application calls SalReportView or SalReportPrint. SAM_ReportStart means that the report is starting. Report Builder sends SAM_ReportStart before the report prints or displays. Perform initialization tasks that are needed before the application can send data to Report Builder. Report Builder ignores any value that the application returns. Message Variables
hWndForm hWndItem wParam lParam Not used Not used Handle of the window that started the report Not used
Processing
Example
Form Window: frmMainForm ... Message Actions On SAM_ReportStart ! Prepare SQL statement for Report Builder Call SqlPrepare( hSql, 'SELECT name, address, phone from customer into :CompanyName, :Address, :phone' )
9-35
Chapter 9
Messages
SAM_RowHeaderClick
Sent to Event Table window The user clicks a row header. SQLWindows only sends this message when TBL_RowHdr_Visible is TRUE (which is the default). If TBL_RowHdr_Visible is FALSE, you can set it to TRUE by calling SalTblDefineRowHeader. Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Table window context row (first row is 0, second row is 1, and so on)
Example
Table Window: tbl1 ... Message Actions On SAM_RowHeaderClick Set nContextRowLength = SalNumberToStr( lParam, 0, sContextRow ) Call SalMessageBox( 'You clicked the row header Context row: ' || sContextRow ,'Info' , MB_Ok )
SAM_RowHeaderDoubleClick
Sent to Event Table window The user double-clicks a row header. SQLWindows only sends this message when TBL_RowHdr_Visible is TRUE (which is the default). If TBL_RowHdr_Visible is FALSE, you can set it to TRUE by calling SalTblDefineRowHeader. Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Table window context row (first row is 0, second row is 1, and so on)
SAM_RowValidate
Example
Table Window: tbl1 ... Message Actions On SAM_RowHeaderDoubleClick Set nContextRowLength = SalNumberToStr( lParam, 0, sContextRow ) Call SalMessageBox( 'You double-clicked the row header Context row: ' || sContextRow ,'Info' , MB_Ok )
SAM_RowValidate
Sent to Event Table window The user tries to move the focus off a row. SQLWindows only sends this message when the user tries to change the row focus within the table window, not when the user moves the focus off the table window. SQLWindows sends SAM_RowValidate regardless of the row flag and cell-edit flag settings. Processing
Constant VALIDATE_Cancel VALIDATE_Ok
Validate the contents of the row and return one of these values:
Description The application detected an error in the row data. The focus stays on the row. The row data is valid. The focus changes to a different row.
Message Variables
hWndForm hWndItem wParam lParam Handle of table window Handle of table window Not used Table window context row (first row is 0, second row is 1, and so on)
Example
Table Window: tbl1 ... Message Actions On SAM_RowValidate If SalIsNull( col1 ) Call SalMessageBox( 'You must enter a value', 'Validation Error', MB_Ok ) Return VALIDATE_Cancel Else Return VALIDATE_Ok
9-37
Chapter 9
Messages
SAM_ScrollBar
Sent to Event Processing
Constant SB_Bottom SB_Top SB_PageDown SB_PageUp SB_ThumbTrack SB_LineUp SB_LineDown SB_ThumbPosition Scrolled to maximum. Scrolled to minimum. User clicked in scroll box area; scroll box scrolled down one page. User clicked in scroll box area; scroll box scrolled up one page. Scroll box moved to new position. Use SB_ThumbTrack when you want the client area updated each time the user drags the scroll box. Scrolled up one line. Scrolled down one line. Scroll box dragged to new position. If you want to repaint the client area when the user releases the thumb, use SB_ThumbTrack.
Horizontal and vertical scroll bar The user scrolls using the mouse or keyboard. To find the scrolling action, check the wParam:
Description
Important: Avoid processing SAM_ScrollBar when wParam is SB_ThumbTrack, since tracking is dynamic and can send many messages.
Message Variables
hWndForm hWndItem wParam lParam Handle of form window or dialog box Scroll bar handle One of the SB_* constants (see above) Scroll bar value
Example
Vertical Scroll Bar: sbScrollBar ... Message Actions On SAM_ScrollBar ! Show scroll bar position in data ! field 'dfScrollBarPos' If wParam = SB_ThumbTrack Set dfScrollBarPos = lParam
SAM_SetFocus
SAM_SetFocus
Sent to Table window, data field, multiline field, push button, radio button, check box, option button, combo box, list box, column, and scroll bar When the focus changes, SQLWindows first sends SAM_KillFocus to the object losing the focus and then sends SAM_SetFocus to the object getting the focus. For focus changes in table windows: Event Processing The wParam of SAM_KillFocus is the window handle of the column getting the focus and the lParam is the row number getting the focus The wParam of SAM_SetFocus is the window handle of the column losing the focus and the lParam is the row number losing the focus
The user moves the focus to the object. Start actions which take place when the user enters an object.
Important: Do not call functions that can change the focus (such as SalMessageBox, SalModalDialog, and SalSendMsg) while processing SAM_SetFocus.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of the object receiving the message Handle of object getting focus Not used
Example
PushButton: pbPartialSearch Data Field: dfDate ... Message Actions On SAM_SetFocus ! When user enters this field, enable push button ! pbPartialSearch Call SalEnableWindow( pbPartialSearch )
SAM_SqlError
Sent to Event Processing Application Actions section of the outline A SQL function fails. Control how the application responds to SQL errors on a global level instead of using the default error processing which displays a dialog with the error number and error text.
9-39
Chapter 9
Messages
Call SqlExtractArgs to get the error code, error position, and Sql Handle from the wParam and lParam. You can also use When SqlError in any actions section of the outline to process an error at a local level. For more, read SQL error handling on page 12-17. Message Variables
hWndForm Handle of top-level window that executed the Sql* statement that failed except when code in applications actions calls a Sql* function and it fails when hWndForm is null (hWndNULL) Unused Sql Handle SQL error code and position
Example The code below shows the SAM_SqlError processing in the Application Actions section. These statements are only executed when the When SqlError statements for local processing do not return a value: SqlExtractArgs gets the error number (nErr). SalNumberToStr converts nErr to a displayable string. SqlGetErrorText gets the error message text for nErr. The code displays a message box with the error number, error message, and a message saying to report the error. The user clicks the OK push button to quit the application. The code returns a value to tell SQLWindows not to invoke the default error processing.
Application Actions On SAM_SqlError ! ! If processing gets to here on a SQL error, there is ! little to do except report the error and gracefully quit ! Call SqlExtractArgs( wParam, lParam, hSqlError, nErr, nPos ) Call SqlGetErrorText( nErr, strErrmsg ) Call SalNumberToStr( nErr, 0, strNum ) ! Call SalMessageBox( strNum || ' - ' || strErrmsg || '. Please report to your system administrator. Click OK to quit the application.', 'Database Error', MB_Ok | MB_IconStop ) ! ! The Return statement tells SQLWindows **not** to invoke
SAM_Timer
SAM_Timer
Sent to Event Processing Application Actions, top-level window and its children; MDI window Every n milliseconds, as specified by SalTimerSet. Check the wParam to find the identifier of the timer that sent the message. This way, one object can process SAM_Timer messages from more than one timer.
Important: Timers are a limited resource in Windows, so use as few of them as possible.
Message Variables
hWndForm hWndItem wParam lParam Handle of top-level window Handle of object receiving message Timer identifier Not used
Example
Form Window: frmMainForm ... Contents Data Field: dfDateTime ... Message Actions On SAM_Timer ! Use SalTimerSet to set timer to send SAM_Timer ! messages once every minute. Update time display ! on screen. Set dtDateTime = SalDateCurrent( )
SAM_Validate
Sent to Event Data field, multiline field, combo box, and column The user changes the value of the object and then moves the focus away from the object. The user can move the focus by several actions such as tabbing to another object, clicking another object, or using a mnemonic or accelerator to activate another object. When a user changes one of these objects, the object's field edit flag changes to TRUE. You can get and set the field edit flag using SalQueryFieldEdit and SalSetFieldEdit.
9-41
Chapter 9
Messages
Processing
Validate the data that the user entered or changed. Whenever the user changes an object, SQLWindows sends SAM_Validate. If an object is valid, return VALIDATE_Ok (this resets the field edit flag to FALSE). The value you return from SAM_Validate processing controls whether the focus changes. SQLWindows does not send SAM_Validate when the user selects a menu item (a menu selection does not change the focus). You can force SQLWindows to send SAM_Validate by calling SalSendValidateMsg in the menu actions of a menu item. This forces field validation before processing a menu selection (without changing the focus). SalSendValidateMsg returns the value that the SAM_Validate message processing returns. To control the action that happens, return one of these values:
Description Does not let the attempted action take place and returns the focus to the current edited item if the item has lost the focus (validation failed). Lets the attempted action take place. This is the default action if you do not process SAM_Validate or do not Return a value when processing SAM_Validate. Lets the attempted action take place and sets the field-edit flag to FALSE.
VALIDATE_OkClearFlag
Note: Unless you return VALIDATE_Cancel, SQLWindows also sends SAM_FieldEdit to the object.
SAM_Validate
lParam
Not used
Example
Data Field: dfName ... On SAM_Validate If SalIsNull( dfName ) Call SalMessageBox( 'You must enter a value', 'Data Error', MB_Ok ) Return VALIDATE_Cancel Else Return VALIDATE_Ok
9-43
Chapter 9
Messages
SAM_* summary
In the table below: Y means that SQLWindows sends the message to the object A blank entry means that SQLWindows does not send the message to the object
Application Actions
Custom control
Message Activate AnyEdit AppExit AppStartup CacheFull CaptionDoubleClick Click Close ColumnSelectClick ContextMenu CornerClick CornerDoubleClick CountRows Create CreateComplete CustControlCmd
Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Option button
Table window
Form window
Multiline field
Radio button
Push button
MDI window
Combo box
Dialog box
Check box
Scroll bar
Data field
List box
Column
Picture
SAM_* summary
Application Actions
Custom control
Message Destroy DoubleClick DragCanAutoStart DragDrop DragEnd DragEnter DragExit DragMove DragNotify DragStart DropDown DropFiles EndCellTab FetchDone FetchRow FetchRowDone FieldEdit Help KillFocus Print ReportFetchInit
Y Y
Y Y Y Y Y Y Y Y Y Y
Y Y
Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y
Table window
Form window
Multiline field
Radio button
Push button
MDI window
Combo box
Dialog box
Check box
Scroll bar
Data field
List box
Column
Picture
Chapter 9
Messages
Application Actions
Custom control
Message ReportFetchNext ReportFinish ReportNotify ReportStart RowHeaderClick RowHeaderDoubleClick RowValidate ScrollBar SetFocus SqlError Timer Validate
Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y
Y Y Y Y
Y Y Y Y Y Y Y
Y Y
Y Y
Option button Y
Table window
Form window
Multiline field
Radio button
Push button
MDI window
Combo box
Dialog box
Check box
Scroll bar
Data field
List box
Column
Picture
Chapter 10
Debugging
Debugging is an important part of developing an application. SQLWindows has many features you can use to debug an application. This chapter covers: Run mode Debug menu Animation Breakpoints Debug toolbar Debugging windows Tips Writing custom debugging code
10-1
Chapter 10
Debugging
Run mode
SQLWindows lets you run an application at designtime in run mode. Besides testing the application, you can use animation, breakpoints, the Debug toolbar, and the debugging windows to analyze an applications behavior. Select Project, Execute or press F7 to enter run mode. To exit run mode, select Debug, Stop Debugging or press Shift+F7.
Animation
Animation displays an application's code as it executes. As SQLWindows executes a statement, it highlights the next statement in the Outline tab so that you can follow the application's progress. You can see which branch of an If, Else, or Else If statement executes, how many times a loop repeats, whether an error is processed locally or globally, and so on. The Debug menu has three items that control animation. You can only check one at a time: No Animate turns off animation (default) Slow Animate turns on slow animation Fast Animate turns on fast animation
For Slow Animate, you can set the time interval (in seconds) between the execution of each statement. Select Tools, Preferences, General. By default, slow animation executes a statement once a second:
Breakpoints
A breakpoint is a statement in an application where SQLWindows suspends execution and displays the Debug toolbar where you can: Examine the values of variables and expressions Track messages Check the call stack Execute the next SAL statement Resume normal application execution
Breakpoints
The Debug menu's cascading Breakpoints menu has items you use to manage breakpoints.
Setting breakpoints
You can set breakpoints in design mode or run mode. To set a breakpoint: 1. Select the statement you want to make a breakpoint. In design mode, click the diamond at the beginning of the statement. In run mode, click anywhere in the statement. Select Breakpoints, Toggle or press F9.
2.
If multiple statements are highlighted when you select Toggle, only the first statement becomes a breakpoint. You can only set breakpoints on SAL statements. If the line of code highlighted when you select Toggle is not a SAL statement, SQLWindows sets a breakpoint on the next SAL statement. By default, breakpoints are red on color monitors and are highlighted on monochrome monitors. Instead of displaying breakpoints in color, you can display them with bold, italic, or underline styles, or without a style. Select Tools, Preferences. For more, read Preferences on page 4-32.
Clearing breakpoints
Select Breakpoints, Toggle or press F9 to turn off the breakpoint on the selected statement. Select Debug, Breakpoints, Clear All to permanently remove all breakpoints in the application.
10-3
Chapter 10
Debugging
Select Breakpoints, Disable All to temporarily turn off all breakpoints in the application. Later, select Breakpoints, Enable All to turn on all breakpoints in the application.
Immediate breakpoints
You can cause an immediate breakpoint while an application is running by selecting Debug, Break.
Debug toolbar
The Debug toolbar lets you: Resume execution of the application Execute the application one statement at a time Cause the application to break at its current point Evaluate expressions Display a stack trace Examine the values of an application's variables Monitor messages
The buttons on the Debug toolbar execute commands and display debugging windows. Both the commands and windows are explained below. To display the Debug toolbar: Run an application with one or more breakpoints. SQLWindows stops at each breakpoint and displays the Debug toolbar. Select Debug, Break at any time while in run mode. The application does not have to be stopped at a breakpoint.
Debug toolbar
At a breakpoint, SQLWindows displays the word (Break) in its title bar. When the application is running, SQLWindows displays the word (Run) in its title bar.
Commands
You can also execute these commands by selecting their items in the Debug menu.
Go
Resumes executing the application until the next breakpoint, if there is one, or until you exit the application.
Step Into
Executes the next statement and returns control to the Debug toolbar. If the application calls a function, SQLWindows takes you to the function and you can step through the function a statement at a time before returning to the statement after the function call.
Step Over
Executes the next statement and returns control to the Debug toolbar. If the application calls a function, SQLWindows executes all the function's statements in one step and returns to the statement after the function call.
Break
Causes an immediate break.
Debugging windows
You use the debugging windows to analyze an applications behavior. You can also display these windows in run mode from the Tools menu. Each debugging window can be a dialog or a pane. You dock and undock them the same as you do toolbars. For more, read Docking toolbars, palettes, and the menu bar on page 2-5. To change the width or height of a docked debugging window, move the mouse pointer to an inner edge and drag after the splitter appears.
10-5
Chapter 10
Debugging
Expressions window
Evaluates an expression you type in the dropdown at the top of the window. After typing the expression, either click Eval or press Return.
You can use this window with Step Into and Step Over to evaluate a variable's value before and after a statement uses or changes the variable's value. This window remembers all the expressions you entered for this instance of SQLWindows. You can evaluate any expression that results in a number or string. For example, you can evaluate expressions like these:
SalDateCurrent( ) 2+2
Messages window
Displays every message sent in an application. Each line displays a message name or number, the handle of the window receiving the message, and the wParam and lParam values.
Click SAM messages only to display only SQLWindows messages (SAM_*). The values displayed under the Message heading are SQLWindows message names. Click Stop Watching to end the message tracking.
Variables windows
Displays the names and values of variables. SQLWindows updates the variable values at each breakpoint. There are three kinds of variable windows. The illustration below shows all three displayed at once, during a breakpoint in an application.
Debug toolbar
The Variables window can be invoked by the Debug toolbar button that is noted with 1 in the illustration above. It can also be invoked from the Tools, Variables menu item, or by hot key Alt+5. By default, it initially contains a few global variable names, as shown in the illustration. In addition, you can add other variables of your choice to this window. There are two ways to do this. You can simply click in a blank line at the bottom of the Variables window, then type the name of a variable into the left cell of that line. (Or delete the variable name in a cell to stop monitoring that variable.) You can also click the +/- button in the window to bring up a more full-featured dialog for choosing variables, as shown below.
10-7
Chapter 10
Debugging
To add a watch variable: 1. Select a section name in the outline from the top list in Select Watch Variables on the left side of the dialog. You can type the first few characters of the name in the data field to scroll to the section that starts with that prefix. SQLWindows displays the variables defined in the selected section in the lower list. Select a variable by double-clicking it or by selecting it and clicking Add. Click Add All to add all the variables in the section. After you make a selection, SQLWindows adds the variables to Current Watch Variables on the right side of the dialog.
2.
To remove a watch variable, double-click it in Current Watch Variables or select it and click Clear. Click Clear All to remove all variables from the list. You can use Edit Watch Variables in the lower right side of the dialog to: Type variable names. Add qualifiers to variable names. Enter expressions to add to the watch variables list. SQLWindows evaluates the expression and displays the result when you display the Watch Variables window. (This is like entering an expression in the Expressions window.)
Click OK to save your selections and return to the Variables window. Click Cancel to return to the Variables window without saving your selections.
Debug toolbar
Locals variable window. This window is invoked by clicking the Debug toolbar button denoted with 2 in the application full-screen illustration above. You cannot control which variables are displayed in this window. It automatically shows only those variables that are in local scope at the time of the breakpoint. Auto variable window. This window is invoked by clicking the Debug toolbar button denoted with 3 in the application full-screen illustration above. You cannot control which variables are displayed in this window. It automatically shows only those variables that are present in the current line of code (the breakpoint line) and the line of code preceding the current line.
All three variable windows are capable of displaying the values of complex datatypes such as user-defined variables (UDVs). In its most basic form, a UDV is either considered Null or Not Null. You can click on the + icon to expand the UDV to its more detailed parts, to inspect or change the values of those parts. Color formatting in variable windows. In all three variable windows, the value of a variable may display in a color different from the default. This indicates that the value of the variable has changed since the last breakpoint. In the case of the Auto variable window, it indicates a value that changed between the preceding line of code and the current line of code. Changing the value of variables. The Expressions window, described earlier in this chapter, allows you to evaluate any line of SAL code. This includes lines beginning with Set, which can change the value of variables at runtime. All three of the variable windows also permit you to change the value of variables. Simply click in the cell that displays the current value, and type a new value.
10-9
Chapter 10
Debugging
Quick Info
Quick Info is an automatic feature that works at runtime. If you hover your mouse cursor over the name of a variable or other object, after a short time a tooltip appears with the definition (datatype) and the value of that variable or object. This works for simple datatypes, but not for complex datatypes such as UDVs.
Debugging DLLs
To debug DLLs that you write, read Using Visual Studio with DLLs on page 21-33.
Tips
Test SQL statements
Run SQL statements that you plan to use in a SQLWindows application in Database Explorer first. This lets you verify that the SQL statements work correctly and produce the intended results. You can then copy and paste the SQL statements to the outline. This prevents typing errors.
SalCompileAndEvaluate
This function lets you access the value of a variable without specifying its name until runtime. SalCompileAndEvaluate evaluates an expression (strExpression) and returns the expression's value in the nReturn, strReturn, dtReturn, or hWndReturn parameter as appropriate for the value's data type:
nType = SalCompileAndEvaluate ( strExpression, nError, nErrorPos, nReturn, strReturn, dtReturn, hWndReturn, bInhibitErrors, strContext)
10-11
Chapter 10
Debugging
In strContext, you supply the handle to an execution context returned by SalContextBreak or SalContextCurrent. The execution context is only meaningful to SQLWindows. The nType return value is one of the these values if the function succeeds: EVAL_Date EVAL_Handle EVAL_If EVAL_Number EVAL_Set EVAL_String EVAL_Template
If this function does not succeed, it returns an error number in nError and the position in strExpression at which the error occurred in nErrorPos. If you set bInhibitErrors to FALSE, SQLWindows reports compile and evaluation errors by displaying a message box. If you set bInhibitErrors to TRUE, SQLWindows does not report compile or evaluation errors. Set bInhibitErrors to TRUE when the application handles error processing.
SalContextBreak
This function retrieves the context of the most-recently executed Break statement. Pass strContext as the last parameter of SalCompileAndEvaluate.
strContext = SalContextBreak ( )
SalContextCurrent
This function retrieves the current execution context. Pass strContext as the last parameter of SalCompileAndEvaluate.
strContext = SalContextCurrent ( )
Chapter 11
11-1
Chapter 11
About formatting
You can apply a format to objects such as data fields and table window columns. The format determines how the data is displayed. After the user enters data, the application displays in the format that you set. Formatting is related to validation. Validation, the process of ensuring that data the user enters fulfills certain conditions, is explained on page 11-7. The formats that you can apply depend on the data type of the object. You format string and long string data types differently than number and date/time data types.
Setting a format
Select Format in the Attribute Inspector to display the formats available for the object. The default format for all objects is unformatted.
Picture formats
Picture formatting is the recommended method. For number or date/time data types, you can: Select a built-in picture format Enter a custom picture format Select a profile-driven format
You can format date/time or number data types in different ways. For example, you can format a date/time data type so that the date is displayed as 7/1/91 or July 1, 1991. You can format a number data type as a decimal, percentage, or currency.
Picture formats
Picture formats are a visual template of the formatted data. They look like the data after the data is formatted. For example, the date/time picture format m/d/yy formats a date as 7/1/91, and a number picture format #.## formats a number as 1234.56. These same types of formats are used in Excel and COBOL. You can only use picture formats for date/time or number data types. You can use a built-in picture format, or you can create a custom picture format.
11-3
Chapter 11
Month: 1-12 (without leading zero) Month: 01-12 (with leading zero) Month: Jan-Dec (abbreviated name) Month: January-December (full name) Day: 1-31 (without leading zero) Day: 01-31 (with leading zero) Day: Sun-Sat (abbreviated name) Day: Sunday-Saturday (full name) Year: 2-digit Year: 4-digit Hour: 12 hour clock Hour: 24-hour clock Minute: 0-59 Second: 0-59 Microseconds: 000000-999999 International AM or PM string
Zero fill. SQLWindows adds extra zeros if the value has fewer digits on either side of the decimal point than there are zeros on either side of the decimal point in the format. If the number has more digits to the right of the decimal point than there are zeros to the right of the format, SQLWindows rounds the number to as many decimal places as there are zeros to the right. If the number has more digits to the left of the decimal point than there are zeros to the left of the format, SQLWindows displays the extra digits.
Profile-driven formats
Character
Description Thousands separator. Commas must be three positions to the left of the decimal point. For example, '#,###, ##0.00' is legal but '#,##,##0.00' is not. Percentage. SQLWindows multiplies the number by 100 and adds the % character if the percent character is immediately after the last zero. Fixed or floating dollar sign. A fixed dollar sign is always in the same position at the start of a field; a floating dollar sign is next to the most significant digit. You cannot put the $ symbol to the right of a 0, #, or decimal point. When a dollar sign appears by itself, it means formatting for international currency.
, % $
E+ e+ Ee.
Scientific notation (exponential). If a format has a 0 or # to the right of an E-, E+, e-, or e+, SQLWindows displays the value in scientific format and adds an E or e. The number of digits (#'s or 0's) sets the exponent's number of digits. E- or e- places a minus sign by negative exponents. E+ or e+ places a plus sign by positive exponents You must start this format with '0' and a period, followed by '0' and/or '#' characters. Place a '+', '-', '#', or '0' after the 'E' or 'e'. 0.00E+00 and 0.00###e-00# are examples. Decimal point. The number of digits (#'s or 0's) to display to the right and left of the decimal point. If the format has only #'s to the left of the decimal point, SQLWindows begins values less than 1 with a decimal point. To avoid this, use 0 as the first format character to the left of the decimal point instead of #.
* ; _
Character fill. Repeat the next character enough times to fill the field width. Place this character before the first # or 0 character. For example, $*, ###0.00 results in a fixed dollar sign. Separator. Separates positive and negative formats. For example, ##0.00; -##0.00. There can only be one ; character in a format. If there is no ; character and the value is negative, SQLWindows adds a - to the value. Alignment. Leaves a space for the character that follows the _ (underscore). This is useful for aligning fields. If this character is used at the end of a number, place the _<some character> as the last two characters in the format. For example, $#,##0.00_); ($#,##0.00) ensures that positive values align with negative values that contain parentheses.
Profile-driven formats
Warning: The profile-driven formats have been deprecated. The code that enables this functionality is still present in SQLWindows but only for the purpose of backwards compatibility. Gupta recommends using the SQLWindows Picture formats instead. For more, read Picture formats on page 11-3.
You can use profile-driven formats for Date/Time and Number data types.
Developing with SQLWindows
11-5
Chapter 11
Profile-driven formats use Microsoft Windows country profiles. The formatting used depends on the settings in the International control panel in Windows NT or the Regional Settings control panel in Windows 95. For more, read Country profiles on page 11-6. The data type of the field determines its possible formats. For example, you can format a number field as currency, decimal, percentage, or unformatted. The table below lists data types that you can use with each profile-driven format:
Format Date Date/Time Time Unformatted Invisible Currency Decimal Percentage Data type Date/Time Date/Time Date/Time Date/Time or Number Date/Time or Number Number Number Number Description Formats data with the date specified in the profile Formats data with the date/time specified in the profile Formats data with the time specified in the profile Leaves data as is Hides data Formats the data with the currency specified in the profile Converts the number to the decimal value specified in the profile Converts the number to a percentage
Country profiles
Since countries use different ways to express formatted data (such as the currency symbol), SQLWindows associates a format with a country profile. The country item specifies the country profile to use to format table window columns and data fields. A country profile is a collection of format specifications for different countries. SQLWindows has internally-defined profiles for certain countries. When you set Country, SQLWindows uses the format characteristics from the associated profile. For example, when you select USA as the country for a formatted currency field, SQLWindows uses two decimal places to the right of the decimal point and the dollar sign ($) currency symbol. These currency parameters are defined in the USA profile.
About validation
iDigits
iLZero
Whether to use a leading zero with decimal values less than 1.0 and greater than -1.0. Set to 0 for no leading zero (.7); set to 1 for a leading zero (0.7). Date picture for the long date format, such as d MMMM, yyyy. Negative currency format. Set to 0 for ($1), 1 for -$1, 2 for $-1, 3 for $1-, 4 for (1$), 5 for -1$, 6 for 1-$, and 7 for 1$-. Date picture for the short date format, such as M/d/yy. Whether hours have a leading zero. If set to 0, a leading zero is not used. Thousands separator character. Time format: 0 is a 12-hour clock, 1 is a 24-hour clock. Time-separator character. For example, (:) is the time separator in (9:25). Trailing string for times from 0:00 to 11:59 (AM). This string can up to 3 characters. Trailing string for times from 12:00 to 23:59 (PM). This string can up to 3 characters.
About validation
Validation is the process of ensuring that data the user enters meets certain requirements.
11-7
Chapter 11
Validation is related to, but separate from, formatting. Formatting determines how data is displayed after it is entered; validation ensures that data meets conditions before it is accepted and displayed. There are three types of validation you can use in SQLWindows applications: Default validation (for Number and Date/Time data types) Input masks Custom validation that you write
Default validation
SQLWindows performs default validation for number and date/time data types. SQLWindows performs default validation as soon as the focus leaves the object. If an entry is invalid, SQLWindows does not let the user move the focus away from the object until the entry is correct or the entry is blank.
Custom validation
If the entered data matches any of the formats above, the data is valid. 4. If the data does not match any of the formats above and the object has a date/time picture format, SQLWindows checks the entry against the picture format. If the entered data matches the picture format, the data is valid.
If the entered data does not match any of the above, then the data fails validation and SQLWindows displays an invalid data message.
Custom validation
You can replace the SQLWindows default validation with custom validation. For custom validation, you process the SAM_Validate message for an object. Whenever the user changes an object, SQLWindows sends SAM_Validate. Usually, you Return VALIDATE_Cancel if validation fails or VALIDATE_Ok (this resets the field edit flag to FALSE) if validation succeeds. If you do not return a value when processing SAM_Validate, SQLWindows performs its default validation. The value you return from SAM_Validate processing controls whether the focus changes. For example:
Data Field: dfName ... On SAM_Validate If SalIsNull( dfName ) Call SalMessageBox( 'You must enter a value', 'Data Error', MB_Ok ) Return VALIDATE_Cancel Else Return VALIDATE_Ok
SQLWindows does not send SAM_Validate when the user selects a menu item (a menu selection does not change the focus). You can force SQLWindows to send SAM_Validate by calling SalSendValidateMsg in the menu actions of a menu item. This forces validation before processing a menu selection (without changing the focus). SalSendValidateMsg returns the value that the SAM_Validate message processing returns. For a table window, process the SAM_RowValidate message to check the contents of a row:
Table Window: tbl1 ...
11-9
Chapter 11
Message Actions On SAM_RowValidate If SalIsNull( col1 ) Call SalMessageBox( 'You must enter a value', 'Validation Error', MB_Ok ) Return VALIDATE_Cancel Else Return VALIDATE_Ok
Input masks
An input mask validates data as a user enters it. You use an input mask to specify a criteria for a value. These are the criteria that you can specify: Alphabetic or numeric characters. If the user types a character that is invalid, SQLWindows beeps. Uppercase or lowercase characters. SQLWindows automatically converts the character if the user enters it in the wrong case. Constants. SQLWindows inserts a constant (such as a hyphen) in a position automatically without the user typing it.
You can set an input mask for any data type. You define an input mask for a field using the Attribute Inspector. You can choose an existing input mask or define a new one. The existing input mask formats are in the Formats section (under Global Declarations) with the Date/Time and Number picture formats. SQLWindows adds new input masks that you define to the Formats section.
Input masks
All other characters (including spaces) in an input mask are a constant that SQLWindows inserts automatically. These are examples of input masks:
Example 999-99-9999 (999) 999-9999 AA-9999 99/99/99 AAA !!!!!!!!!!!!! Social Security number Telephone number Code: two uppercase letters, a dash, and four numbers Date Code: three uppercase letters, a blank, and any other uppercase characters Explanation
This lets you to create both a mask for input and a format for display (such as for currency).
11-11
Chapter 11
You can change this behavior by calling SalFmtKeepMask (see the next section).
Input masks
SalFmtGetInputMask
This function returns the input mask of field hWnd in strMask:
bOk = SalFmtGetInputMask( hWnd, strMask )
SalFmtSetInputMask
This function sets the input mask of the field hWnd to the value in strMask:
bOk = SalFmtSetInputMask( hWnd, strMask )
SalFmtIsValidInputMask
This function validates the input mask in strMask and returns TRUE if the mask is valid:
bOk = SalFmtIsValidInputMask( strMask )
SalFmtKeepMask
By default, SQLWindows removes input mask characters when you copy the value in a data field, table window column, or combo box. For example, if you create a data field with the input mask AA-AA and copy its value to another data field, SQLWindows removes the hyphen. You can call SalFmtKeepMask to change the default behavior and include input mask characters when you copy the value in a field:
bRet = SalFmtKeepMask( bKeep )
If bKeep is FALSE (default), SQLWindows removes input mask characters when you copy a value. If bKeep is TRUE, SQLWindows keeps the input mask characters when you copy a value. This function returns the value you specified in bKeep. If a field has a ^ character in its input mask (see above), it overrides the setting you make with this function.
SalFmtUnmaskInput
This function unmasks the contents of hWnd and puts the result in strInput:
bOk = SalFmtUnmaskInput( hWnd, strInput )
11-13
Chapter 11
SAM_Validate processing
You can process SAM_Validate messages for fields that have input masks. You can call SalFmtUnmaskInput in the SAM_Validate processing to get the value the user entered without the input mask constants.
SalIsNull
SalIsNull works the same for a field that has an input mask as for other fields. If the field is empty, SalIsNull returns TRUE, even if the input mask has constants.
Chapter 12
SQL Programming
This chapter shows how to access a SQL database from a SQLWindows application and covers these topics: Database access cycles Error handling Database parameters Multiuser techniques
12-1
Chapter 12
SQL Programming
The Sql* functions in SQLWindows are a language interface that you use to access a database with SQL statements. You can combine SQL statements with the power and flexibility of SAL. You can access database servers such as SQLBase with a SQLWindows application. SQLBase has a complete implementation of SQL that is compatible with IBM's DB2. In addition, SQLBase has extensions to DB2. The Sql* functions are database-independent. You can use the Sql* functions with Guptas connectivity components to access IBM DB2, Oracle, Microsoft SQL Server, Sybase, Informix, and other databases. The applications that you write with SQLWindows are client (or front end) applications. The database (such as SQLBase or DB2) is the server (also called backend or engine).
The examples in this chapter use SQLBase SQL. Also, this chapter shows examples of setting database parameters for SQLBase. If you are using a different database, check Connecting Gupta Objects to Databases to find the parameters supported for your database.
Multistep interface
With the multistep interface, you must connect to a database before you perform any database operations. For each operation you perform, you compile and execute a SQL statement. For SELECTs, you must also fetch. When you complete the database operations, you disconnect from the database. Connect
Execute
Fetch (for a SELECT) Disconnect In the multistep interface, you can fetch rows from a result set created with a SELECT statement. The multistep interface is more flexible and gives you more control over database parameter settings than the single-step interface.
Single-step interface
With the single-step interface, you can perform a database operation in one function call. The single-step interface is easier to use, but SELECTs can only return one row. Every function call using this interface requires a database connect and disconnect, which may impact performance.
12-3
Chapter 12
SQL Programming
the multistep interface has the advantages of faster performance, lower resource usage, more graceful error recovery, and better control of locking and concurrency. It is generally worth the extra effort to use the multistep interface.
Multistep interface
Connecting and disconnecting
You must connect to a database before you can perform database operations. You must disconnect from the database before you exit from the application. The table below shows the functions you call to connect to and disconnect from a database:
Function SqlConnect SqlDisconnect Connects to a database Disconnects from a database Description
Calling SqlConnect
To connect to a database, you need to: Specify the database you want to connect to Specify the user name and password to use in the connection Call the SqlConnect function which returns a Sql Handle
Database name, user name, and password. SQLWindows has three system variables that identify the database, user name, and password: SqlDatabase SqlUser SqlPassword
You can set these in the Application Actions section. For example:
On SAM_AppStartup Set SqlDatabase = 'SPA' Set SqlUser = 'username' Set SqlPassword = 'userpswd'
The table below shows the default values for these system variables:
System variable SqlDatabase SqlUser DEMO SYSADM Default value
Multistep interface
Default value
Sql Handles. The SqlConnect function returns a Sql Handle that identifies a specific connection to a database. A Sql Handle is opaque and you do not care about its actual value, but you use it to identify the connection in functions you call later. A Sql Handle is also called a cursor. The term Sql Handle refers to three things in SQLBase: A name that identifies a database connection A row position in a result set A work space in memory used to process a SQL statement
You must declare a variable with the Sql Handle data type for each connection you make to a database:
Global Declarations ... Variables Sql Handle: hSqlFetch Sql Handle: hSqlChange
Before you call SqlConnect, a Sql Handle does not have a valid value. Example. In the example below, the code connects two Sql Handles:
Set bConnect = SqlConnect( hSqlFetch ) If bConnect Set bConnect = SqlConnect( hSqlChange )
When you call SqlConnect, it allocates these resources on the client and server: Sql Handle work space Input message buffer and output message buffer (this chapter explains these later)
Calling SqlDisconnect
Call the SqlDisconnect function after you perform all database operations. Always disconnect all Sql Handles before exiting an application:
On SAM_AppExit If bConnect Call SqlDisconnect( hSqlFetch ) Call SqlDisconnect( hSqlChange )
When you call SqlDisconnect, it frees resources on the client and server.
12-5
Chapter 12
SQL Programming
Always call SqlDisconnect for all Sql Handles that you connected with SqlConnect. The last SqlDisconnect for a database causes an implicit COMMIT.
You can compile a SQL statement once and execute it repeatedly with a new set of input values each time. You cannot use constants for bind variables. INTO variables. Use INTO variables for the output of a SQL SELECT statement. The INTO clause specifies the variables defined in the application where SQLWindows returns query data. Bind variable and INTO variable names. You must prefix each bind variable and INTO variable in a SQL statement with a colon (:). Maximum number of bind variables and INTO variables. The maximum number of bind variables in a SQL statement is 255; the maximum number of INTO variables in a SQL statement is 255. These limits apply to SQL statements that you refer to in these functions: SqlImmediate SqlPrepare SqlPrepareAndExecute
Multistep interface
SqlRetrieve SqlStore
Example. This example shows how to code bind variables and INTO variables in SQL statements: strSelectByName contains INTO variables (:dfGuestName, :dfInWeight, :dfTargetWeight, and :dfROWID) and one bind variable (:dfGuestName). This chapter explains the ROWID column later. strInsert only contains bind variables (:dfGuestName, :dtCheckIn, :dfInWeight, and :dfTargetWeight). strUpdateByName only contains bind variables (:dfInWeight, :dfTargetWeight, and :dfGuestName).
Global Declarations ... Variables String: strSelectByName String: strInsert String: strUpdateByName ... Application Actions On SAM_AppStartup Set strSelectByName = 'select name, in_weight, target_weight, rowid into :dfGuestName, :dfInWeight, :dfTargetWeight, :dfROWID from guest where name = :dfGuestName' Set strInsert = 'insert into guest(name, check_in, in_weight, target_weight ) values( :dfGuestName, :dtCheckIn, :dfInWeight, :dfTargetWeight )' Set strUpdateByName = 'update guest set in_weight = :dfInWeight, target_weight = :dfTargetWeight where name = :dfGuestName'
12-7
Chapter 12
SQL Programming
The SqlPrepare function compiles a SQL statement. When you call SqlPrepare, SQLWindows checks the INTO clause (for a SELECT statement) and verifies bind variables. Then, SQLWindows sends the statement to the server where SQLBase: 1. 2. 3. 4. Parses the statement, detects syntax errors, and verifies that the database objects exist. Checks security. Determines how to access the data. Finds the indexes (if any) that provide the best path to the data. This information is called the execution plan. Translates the statement into a series of executable modules.
SQLBase stores the compiled statement in the Sql Handle work space. After you compile a statement, you execute it with the SqlExecute function which sends the bind variable values to the server. You can also prepare and execute SQL statements in one step by calling SqlPrepareAndExecute. SqlPrepare SqlPrepareAndExecute
SqlExecute Once you prepare a SQL statement, you can call SqlExecute as many times as you need. However, these actions destroy a compiled statement: Compiling another statement on the same Sql Handle A COMMIT or ROLLBACK if DBP_PRESERVE is off (for more, read Transaction scope on page 12-24)
SELECTs (queries)
You follow these steps to perform a SELECT: 1. 2. 3. Prepare (compile) the SELECT statement Execute the SELECT statement Call a SqlFetch* function to fetch the row data to the INTO variables
Multistep interface
12-9
Chapter 12
SQL Programming
the Sql Handle is positioned, later fetches start from that row. You can also call the SqlFetchPrevious function in result set mode to fetch backward. Result set You can set a row position and start fetching from that row with SqlFetchNext
Result set
Example
This example shows how to perform a SELECT statement: Declare a Sql Handle, a Boolean for return values, a string to hold the SELECT statement, and a number for the fetch indicator. Assign the SELECT statement. The form window has two push buttons that let the user fetch the next and previous rows. The SAM_Create actions for the form window disable the push buttons. The push buttons are enabled later after a successful fetch. Compile the SELECT statement with SqlPrepare. The first parameter is the Sql Handle returned by SqlConnect. The second parameter is the variable that contains the SQL statement. Execute the SELECT statement with SqlExecute. The SqlExecute function executes the previously-compiled statement. In this example, you can replace these two lines:
Set bOk = SqlPrepare( hSqlFetch, strSelect ) Set bOk = SqlExecute( hSqlFetch )
with:
Set bOk = SqlPrepareAndExecute( hSqlFetch, strSelect )
Call SqlFetchNext to get the first row. After calling SqlFetchNext, check the fetch indicator. The table below lists
Multistep interface
Global Declarations ... Variables Sql Handle: hSqlFetch Boolean: bOk String: strSelect Number: nFetch ... Application Actions On SAM_AppStartup Set strSelect = 'select name, in_weight, target_weight, rowid into :dfGuestName, :dfInWeight, :dfTargetWeight, :dfROWID from guest' ... Form Window: frmMain Contents ... Pushbutton: pbPreviousRow ... Pushbutton: pbNextRow ... Message Actions On SAM_Create Call SalDisableWindow( pbPreviousRow ) Call SalDisableWindow( pbNextRow ) ... Set bOk = SqlPrepare( hSqlFetch, strSelect ) Set bOk = SqlExecute( hSqlFetch ) Set bOk = SqlFetchNext( hSqlFetch, nFetch ) If nFetch = FETCH_Ok Call SalEnableWindow( pbNextRow )
After successfully fetching the first row, the code enables the pbNextRow push button. The user can then click pbNextRow to fetch other rows. The examples below show the SAM_Click actions for the pbNextRow and pbPreviousRow push buttons.
Developing with SQLWindows
12-11
Chapter 12
SQL Programming
Pushbutton: pbNextRow ... On SAM_Click Set bOk = SqlFetchNext( hSqlFetch, nFetch ) If nFetch = FETCH_Ok Call SalEnableWindow( pbPreviousRow ) Else If nFetch = FETCH_EOF Call SalDisableWindow( pbNextRow ) Pushbutton: pbPreviousRow ... On SAM_Click Set bOk = SqlFetchPrevious( hSqlFetch, nFetch ) If nFetch = FETCH_Ok Call SalEnableWindow( pbNextRow ) Else If nFetch = FETCH_EOF Call SalDisableWindow( pbPreviousRow )
After you execute a DML statement, you can call SqlGetModifiedRows to find the number of rows that the INSERT, UPDATE, or DELETE changed.
Global Declarations ... Variables Sql Handle: hSqlChange ... String: strUpdate On SAM_AppStartup Set strUpdateByName = 'update guest set in_weight = :dfInWeight, target_weight = :dfTargetWeight where name = :dfGuestName' ... ! The code below can be in any actions section ...
Multistep interface
Set bOk = SqlPrepare( hSqlChange, strUpdateByName ) Set bOk = SqlExecute( hSqlChange ) If bOk Call SqlCommit( hSqlChange )
Other operations
You perform DDL (Data Definition Language) statements such as CREATE or DROP and database administration statements such as GRANT or REVOKE in the same way you perform DML statements.
12-13
Chapter 12
SQL Programming
not to the work done for other connected databases or other user names. For more, read Transaction scope on page 12-24.
Example
This example shows how to use two Sql Handles connected to the same database to SELECT and UPDATE. One Sql Handle is for a SELECT statement and the other Sql Handle is for an UPDATE statement. After a row is fetched with the first Sql Handle, the UPDATE is executed with the second Sql Handle. Declare two Sql Handles. Declare variables for the SELECT statement and the UPDATE statement. Assign values to the variables that hold the SELECT statement and the UPDATE statement. Perform two SqlConnect functions. Both connections are to the same database, but each connection is associated with a different Sql Handle. Compile and execute the SELECT statement with SqlPrepare and SqlExecute. The SELECT statement is associated with the first Sql Handle. Fetch a row of data with SqlFetchNext. Compile and execute the UPDATE statement with SqlPrepare and SqlExecute. The UPDATE statement is associated with the second Sql Handle. Before exiting the application, disconnect both Sql Handles.
Global Declarations Variables Sql Handle: hSqlFetch Sql Handle: hSqlChange String: strSelect String: strUpdate ... Application Actions On SAM_AppStartup Set strSelect = 'select name, in_weight, target_weight, rowid into :dfGuestName, :dfInWeight, :dfTargetWeight, :dfROWID from guest' Set strUpdate = 'update guest set name = :dfGuestName, in_weight = :dfInWeight, target_weight = :dfTargetWeight where rowid =:dfROWID' On SAM_AppExit If bConnect Call SqlDisconnect( hSqlFetch )
Single-step interface
Call SqlDisconnect( hSqlChange ) ... ! The code below can be in any actions section ... Set bConnect = SqlConnect( hSqlFetch ) If bConnect Set bConnect = SqlConnect( hSqlChange ) ... Call SqlPrepare( hSqlFetch, strSelect ) Call SqlExecute( hSqlFetch ) Call SqlFetchNext( hSqlFetch, nFetch ) ... ! User changes row data ... Call SqlPrepare( hSqlChange, strUpdate ) Set bOk = SqlExecute( hSqlChange ) If bOk Call SqlCommit( hSqlChange )
Single-step interface
The single-step interface has two functions:
Function SqlImmediate SqlClearImmediate Description Connects an internal Sql Handle and prepares and executes a SQL statement Disconnects the Sql Handle created with SqlImmediate
SqlImmediate executes SqlConnect, SqlPrepare, SqlExecute, and (for a SELECT) SqlFetchNext: SqlConnect SqlPrepare SqlExecute SqlFetchNext (for a SELECT)
SqlImmediate
The first time you call SqlImmediate, SQLWindows performs all of these functions. On later calls, SQLWindows does not perform the SqlConnect if the Sql Handle is still connected. For the SqlConnect, SQLWindows uses the current values of the system variables SqlDatabase, SqlUser, and SqlPassword. You can use SqlImmediate to: SELECT one row from a database
Developing with SQLWindows
12-15
Chapter 12
SQL Programming
Perform Data Manipulation Language (DML) statements that INSERT, UPDATE, or DELETE COMMIT or ROLLBACK the current transaction Perform Data Definition Language (DDL) statements Perform Data Control Language (DCL) statements
SQLWindows manages the Sql Handle internally and you cannot refer to it in a later Sql* function. If you call SqlImmediate twice for different databases, SQLWindows reuses the internal Sql Handle by disconnecting and reconnecting. SqlClearImmediate disconnects the internal Sql Handle and frees resources. SqlClearImmediate causes an implicit COMMIT if it disconnects the last Sql Handle connected to a database.
Example
The example below SELECTs and UPDATEs a row using two calls to SqlImmediate:
Global Declarations Variables String: strSelectByName String: strUpdateByName ... Application Actions On SAM_AppStartup Set strSelectByName = 'select name, in_weight, target_weight, rowid into :dfGuestName, :dfInWeight, :dfTargetWeight, :dfROWID from guest where name = :dfGuestName' Set strUpdateByName = 'update guest set in_weight = :dfInWeight, target_weight = :dfTargetWeight where name = :dfGuestName' ... ! The code below can be in any actions section ... Set bSelect = SqlImmediate( strSelectByName ) ... ! User changes row ... Set bOk = SqlImmediate( strUpdateByName ) If bOk Call SqlImmediate( 'commit' )
Long Strings
Long Strings
Use the Long String data type for bind and INTO variables for SQL database columns that are longer than 254 bytes, as the table below shows:
Database AS/400 DB2 Informix-Online Informix-SE Ingres Oracle SQLBase SQL Server Sybase CHAR, VARCHAR LONG VARCHAR CHAR, VARCHAR, BYTE, TEXT CHAR CHAR, VARCHAR, TEXT, C CHAR, VARCHAR, LONG, LONG RAW LONG VARCHAR TEXT, IMAGE Data types
Internally, SQLWindows uses the SQL/API functions sqlrlo and sqlwlo to read and write these column data types.
12-17
Chapter 12
SQL Programming
The dialog has two push buttons: If the you click Continue, the application continues to run and the Sql* function that caused the error returns FALSE If you click Halt, the application ends
Important: The default error dialog is for development use. Design production applications so that they handle all SQL errors and that the default error handling never takes places. For most production applications, the default error dialog is not appropriate.
The flowchart below summarizes how you can use When SqlError, SAM_SqlError, and default error handling. Start SQL Error Handling
No If a user clicks Halt, the application ends; if a user clicks Continue, the Sql* function returns FALSE and the application continues.
End The flowchart shows the steps that SQLWindows follows when a Sql* function fails:
12-19
Chapter 12
SQL Programming
1.
SQLWindows looks for When SqlError in the local actions section. You must code When SqlError statements: before the Sql* function and at the same indent level as the Sql* function. If there is a When SqlError, SQLWindows performs its statements: If When SqlError has a Return statement, the Return value becomes the return value of the failed Sql* function and there is no further error handling If When SqlError does not have a Return statement, SQLWindows looks for the On SAM_SqlError statement in the Application Actions section
If there is not a When SqlError in the local section, SQLWindows looks for On SAM_SqlError in the Application Actions section. 2. SQLWindows looks for On SAM_SqlError in the Application Actions section if there is not a local When SqlError statement or if the local When SqlError did not return a value. If there is an On SAM_SqlError statement, SQLWindows performs its statements: If On SAM_SqlError has a Return statement, the Return value becomes the return value of the failed Sql* function and there is no further error handling If On SAM_SqlError does not have a Return statement, SQLWindows performs its default error handling
If there is not an On SAM_SqlError in the application actions, SQLWindows performs its default error handling. For the default error handling, if a user clicks the Halt push button, the application ends. If a user clicks the Continue push button, the Sql* function that caused the error returns FALSE and the application continues.
Description Gets the message text for a SQL error number. Returns the database rollback flag. The rollback flag is set to TRUE after a deadlock or system failure, but not set after a user-initiated ROLLBACK.
If nErr was not 805, the code does not return a value to tell SQLWindows to invoke the handling for SAM_SqlError in the Application Actions (this is shown in the next section).
12-21
Chapter 12
SQL Programming
Application Actions ... On SAM_AppStartup ... Set strInsert = 'insert into guest( name, check_in, in_weight, target_weight ) values( :dfGuestName, :dtCheckIn, :dfInWeight, :dfTargetWeight )' ... Menu ... Popup Menu: Insert ... Menu Item: Insert Row ... Menu Actions When SqlError Call SqlExtractArgs( wParam, lParam, hSqlError, nErr, nPos ) Call SalNumberToStr( nErr, 0, strNum ) Call SqlGetErrorText( nErr, strErrmsg ) ! ! A "normal" error on an INSERT is a duplicate key value If nErr = DB_ERR_Dup_Key Call SalMessageBox( strNum || ' - ' || strErrmsg || '. Enter a unique value and try again.', 'Insert Error', MB_Ok | MB_IconExclamation ) ! ! The Return statement tells SQLWindows **not** to invoke ! SAM_SqlError handling (Application Actions) or ! default error handling Return FALSE ! ! If we get to here, do not Return a value to tell SQLWindows ! to invoke the SAM_SqlError handling in the Application Actions Set dtCheckIn = SalDateCurrent( ) Call SqlPrepare( hSqlChange, strInsert ) Set bOk = SqlExecute( hSqlChange ) If bOk Call SqlCommit( hSqlChange )
SqlGetErrorText gets the error message text for nErr. The code displays a message box with the error number, error message, and a message saying to report the error. The user clicks the OK push button to quit the application. The code returns a value to tell SQLWindows not to invoke the default error handling.
Application Actions On SAM_SqlError ! ! If handling gets to here on a SQL error, there is ! little to do except report the error and gracefully quit ! Call SqlExtractArgs( wParam, lParam, hSqlError, nErr, nPos ) Call SqlGetErrorText( nErr, strErrmsg ) Call SalNumberToStr( nErr, 0, strNum ) ! Call SalMessageBox( strNum || ' - ' || strErrmsg || '. Please report to your system administrator. Click OK to quit the application.', 'Database Error', MB_Ok | MB_IconStop ) ! ! The Return statement tells SQLWindows **not** to invoke ! default error handling ! Return FALSE
ERROR.SQL
All error messages are stored in a common error message file called ERROR.SQL. ERROR.SQL contains all error codes that the Sql* functions can cause. ERROR.SQL must be on the client computer. SQLBase servers also use ERROR.SQL.
12-23
Chapter 12
SQL Programming
As the diagram below shows, for each error message there is: Error message text Error reason Error remedy
00353EXE NSY Not a synonym Reason:Attempting to execute a DROP SYNONYM and the named synonym is not a synonym but a table name. Remedy:Modify the DROP SYNONYM statement to use a synonym name or if you really want to drop a table then use a DROP TABLE statement.
The lines with the error message text contain the error code, a mnemonic, and the message text for that code. When an application detects an error, it uses the error code to look up the error message. Error Code Message Text
Search path
SQLWindows looks for ERROR.SQL in these places in this order: 1. 2. 3. 4. 5. As specified by the SQLBASE environment variable (if the variable exists) Current directory \SQLBASE directory The root directory As specified by the PATH environment variable
Transaction scope
Each database maintains its own transaction and ROLLBACK information. The scope of a transaction is all Sql Handles that the application has connected to a database for a given user name. This means that a COMMIT or ROLLBACK (implicit or explicit) applies to the work done for all Sql Handles connected to that
Multi-connection transactions
database for that user name, but not to the work done for other connected databases or other user names. If cursor-context preservation ( DBP_PRESERVE) is off, a COMMIT destroys all compiled statements and results sets for all Sql Handles that the application has connected to the database. The COMMIT can be explicit or implicit, including implicit by autocommit ( DBP_AUTOCOMMIT) or by change in isolation level. If DBP_PRESERVE is on, compiled statements and results sets remain after a COMMIT for that Sql Handle. If DBP_PRESERVE is off, a ROLLBACK destroys all compiled statements and results sets for all Sql Handles that the application has connected to the database. The ROLLBACK can be implicit or explicit, including a ROLLBACK caused by a deadlock. If DBP_PRESERVE is on, compiled statements and results sets remain after a ROLLBACK if both of the following are true: The application is in the Release Locks (RL) isolation level A DDL operation was not performed
If you change isolation levels, it causes an implicit COMMIT for all Sql Handles that the application has connected to the database. In turn, an implicit COMMIT destroys all compiled statements and results sets for all Sql Handles that the application has connected to the database. However, changing to an isolation level that is the same as the current isolation level does not cause an implicit COMMIT. When you are connected to an OLE DB data source, setting autocommit ON forces a rollback of any existing uncommitted work. For this reason, be certain to do an explicit COMMIT before setting autocommit to ON, or risk unexpected data loss. The last SqlDisconnect for a database causes an implicit COMMIT. SqlClearImmediate also causes an implicit COMMIT if it disconnects the last Sql Handle for a database.
Multi-connection transactions
You can have multiple database connections in a single transaction by using the Session Handle data type and these functions: SqlCreateSession SqlCreateStatement SqlCommitSession SqlRollbackSession SqlFreeSession SqlGetSessionParameter
12-25
Chapter 12
SQL Programming
SqlSetSessionParameter
Using these functions, you create a session and then associate one or more Sql Handles to it. You then perform normal SQL operations and rollback or commit all work done for all Sql Handles in the session. Internally, SQLWindows uses sqlcch to create the session. When connected to SQLBase, or when using an OLE DB connection, a call to SqlCreateSession will create a new database connection. When connected to other databases, Gupa first checks the combination of database name, user ID, and password. For each new combination, a new database connection is created. However, if the combination has already been used in the application, only a new cursor is created, not a new database connection.
Note: The functions above are part of the OLE DB consumer interface, but they can be used independently of OLE DB. For more, read Chapter 13, OLE DB Consumer.
To use multiple connections in a transaction: 1. The function SqlCreateSession has a second parameter that you must set to null if you are not connecting to the database through OLE DB:
Set strSessionProperties = ''
2.
3.
4.
5. 6.
Use the Sql Handle as normal. Commit or rollback work done in the session as needed:
Call SqlCommitSession( Session_Handle )
OR
Call SqlRollbackSession( Session_Handle )
7.
Table windows
Table windows
Use the functions below to display and change database data in table windows. Chapter 12, Table Windows, explains these functions.
Function SalTblDoDeletes SalTblDeleteSelected SalTblDoInserts SalTblDoUpdates SalTblFetchRow SalTblPopulate Description Applies a DELETE statement for specified rows. Applies a DELETE statement for all selected rows. Applies an INSERT statement for all new rows. Applies an UPDATE statement for all changed rows. Sends a SAM_FetchRow message to a table window. Populates a table window with a result set: prepares a SELECT statement, executes it, and fetches the rows. If the statement is already prepared, only executes the statement and fetches the rows.
12-27
Chapter 12
SQL Programming
To fill a list box or combo box many times using the same SELECT statement, but with different WHERE criteria. You do not supply a SELECT statement for SalListPopulate, but you do supply a Sql Handle that has a prepared SELECT already (call SqlPrepare or SqlRetrieve first). SalListPopulate binds (for the new criteria), executes, fetches, and fills the list box or combo box. This avoids recompiling the SELECT.
These are the steps that SalListPopulate follows if you specify a non-null string in the strSelect parameter: SqlPrepare Bind (gets the current values of bind variables) SqlExecute Fills list box or combo box
These are the steps that SalListPopulate follows if you specify a null string in the strSelect parameter: Bind (gets the current values of bind variables) SqlExecute Fills list box or combo box
Is it not efficient to call SqlPrepareAndExecute and then call SalListPopulate with a null strSelect parameter. Instead use SqlPrepare (or SqlRetrieve) because SalListPopulate performs the bind and execute before fetching. For more about SalListPopulate, see the SQLWindows Function Reference.
Database parameters
This section explains the parameters you can set to control data operations: Functions you call to get and set parameters The DBP_* parameters
Database parameters
System variables Input message buffer Output message buffer Isolation levels SQL.INI
The difference between these sets of functions is how you identify parameters: When you call SqlGetParameter and SqlSetParameter, identify a parameter with a DBP_* constant (see below) When you call SqlGetParameterAll and SqlSetParameterAll, identify a parameter with a SQLP* constant value defined in SQL.H, not a DBP_* constant
12-29
Chapter 12
SQL Programming
The SQLP* parameters are a superset of the DBP_* parameters and include parameters not only for SQLBase but also for other servers. For more information, see the SQLBase C/API Reference Manual (Chapter 7) or the documentation for the connectivity product that you are using.
Important: A set of the SQLP* constants in SQL.H have the same values as the DBP_* constants, but the values identify different parameters. Be sure to specify the correct number.
DBP_* parameters
You can get and set these parameters with SqlGetParameter and SqlSetParameter:
DBP_BRAND (get)
This parameter shows the brand of the database:
Constant DBV_BRAND_AS400 DBV_BRAND_DB2 DBV_ BRAND_INFORMIX DBV_BRAND_INFORMIX-ONLINE DBV_BRAND_ORACLE DBV_BRAND_ORACLE7 DBV_BRAND_SQL DBV_BRAND_SYBASE IBM AS/400 IBM DB2 Informix Informix Online Oracle Oracle v. 7 SQLBase SQL Server Database
Database parameters
When fetchthrough is off (FALSE), SQLBase fetches rows from the client's input message buffer when possible. When fetchthrough is on (TRUE), SQLBase always fetches data from the server, ensuring the most up-to-date data. Only one row is fetched from the server at a time. There is no multi-row buffering when fetchthrough is on. Fetchthrough slows response time. Only use fetchthrough when you need the most up-to-date row. The default setting is off (FALSE). This setting applies only to the specified Sql Handle. If the result set was created with a SELECT statement that contains DISTINCT, GROUP BY, HAVING, UNION, ORDER BY, an aggregate function, or a complex view, then SQLBase creates a virtual table. In these cases, rows in the result set cannot be mapped to the rows in the database. If you UPDATE in this situation and later fetch an UPDATEd row, the row does not reflect the UPDATE even if fetchthrough is on.
12-31
Chapter 12
SQL Programming
The default setting is 300 seconds. This setting applies only to the specified Sql Handle. The time-out remains in effect until you change it with SqlSetLockTimeout, SqlSetParameter, or SqlSetParameterAll. This parameter is not meaningful for a single-user database. You can also set this parameter with SqlSetLockTimeout.
This setting applies only to the specified Sql Handle. The default setting is off (FALSE).
This setting applies only to the specified Sql Handle. For fetch operations, locks are kept on pages required to maintain the fetch position. This can block other applications that are trying to access the same data. Also, locks can prevent other applications from doing DDL operations. This feature can be on with or without result set mode. If the result set was created with a SELECT statement that contains DISTINCT, GROUP BY, HAVING, UNION, ORDER BY, an aggregate function, or a complex 12-32 Developing with SQLWindows
Database parameters
view, then SQLBase creates a virtual table. In these cases, rows in the result set cannot be mapped to the rows in the database. If you UPDATE in this situation and later fetch an UPDATEd row, the row does not reflect the UPDATE even if cursorcontext preservation is on. The default setting is off (FALSE).
DBP_VERSION (get)
This is the version number of the connectivity software.
System variables
These system variables contain parameters that apply to later connections you make to databases.
SqlDatabase
This system variable sets the database name to use to connect. For more, read Calling SqlConnect on page 12-4.
SqlInMessage
This system variable contains the size of the input message buffer. For more, read Input message buffer on page 12-34.
SqlIsolationLevel
This system variable contains the isolation level. For more, read Isolation levels on page 12-37.
SqlNoRecovery
If this system variable is off (FALSE), transaction logging is performed. Changes that the application makes to a database before a COMMIT can be rolled back, and the database can recover from a system failure. If this system variable is on (TRUE), transaction logging is not performed. Changes to the database before a COMMIT cannot be rolled back if the transaction fails, and the database cannot be recovered if it is damaged by a user error, media failure, or power failure.
12-33
Chapter 12
SQL Programming
Important: In most situations, you should leave recovery turned on. However, when recovery is off, there is less file I/O (and a corresponding increase in performance). You can turn off recovery when loading large amounts of data.
After you set this system variable to TRUE, you can only connect to a database if no other user is connected to the database. Any other user must set SqlNoRecovery to TRUE before connecting to the database. If other users try to connect later without setting SqlNoRecovery to TRUE, they get an error. If you turn off recovery, SQLWindows resets these parameters to their default settings: DBP_AUTOCOMMIT DBP_LOCKWAITTIMEOUT DBP_PRESERVE DBP_ROLLBACKONTIMEOUT Isolation level Result set mode
SqlOutMessage
This system variable contains the size of the output message buffer. For more, read Output message buffer on page 12-36.
SqlPassword
This system variable sets the password to use connect to databases. For more, read Calling SqlConnect on page 12-4.
SqlResultSet
This system variable turns result set mode on and off for the next connection to a database. For more, read Result set mode on page 12-9.
SqlUser
This system variable sets the user name to use to connect to databases. For more, read Calling SqlConnect on page 12-4.
Database parameters
The input message buffer is allocated on both the client computer and on the database server. The database server builds an input message in this buffer on the database server computer and sends it to a buffer of the same size on the client. It is called an input message buffer because it is input from the client's point of view. There is one input message buffer for each Sql Handle on the client computer. On the server, there is one input message buffer that is the size of the largest input message buffer on the client computer. Application 1 hSql1 hSql2 hSql3 Input Message Buffer Input Message Buffer Input Message Buffer Output Message Buffer Application 2 hSql1 hSql2 Input Message Buffer Input Message Buffer Input Message Buffer Output Message Buffer Output Message Buffer Output Message Buffer Input Message Buffer Database Server
You can set a different size for each input message buffer, even if more than one Sql Handle is connected to the same database. The input message buffer receives data fetched by the client that the server has sent. While fetching data from the database, SQLBase compacts as many rows as possible into one input message buffer. Most query data does not exceed the default input message buffer size, but if it does, you can use this parameter to increase the size of the input message buffer. A large input message buffer can improve performance while fetching data from the database because it reduces the number of network messages. Note that a large input message buffer can affect system throughput because of concurrency. Any row currently in the input message buffer can have a shared lock on it (depending on the isolation level) preventing other users from changing that row. Therefore, a large input message buffer can cause more shared locks to remain than are necessary.
12-35
Chapter 12
SQL Programming
A large input message buffer improves performance when reading LONG VARCHAR columns. You can also improve overall system performance by decreasing the size of the input message buffer when an application does not need to fetch data. SQLBase automatically maintains an input message buffer large enough to hold at least one row of data. Despite the specified input message size, SQLBase dynamically allocates more space if necessary. See the explanation of isolation levels in the SQLBase SQL Reference (SET ISOLATION) for more about how each isolation level uses the input message buffer. The default setting is 1,024 bytes. The maximum setting is 32,767 bytes. The actual size of a row of SELECTed data is not the same as the sum of the column lengths. SQLBase converts row data to a computer-independent format before sending it to the client. Also, there are overhead bytes in each message.
A large output message buffer can allocate space unnecessarily on the both the client and the server. Rows are always inserted and sent one row at a time. A large output message buffer does not reduce network traffic.
Database parameters
SQLBase automatically maintains an output message buffer large enough to hold any SQL statement or a row to insert of any length (given available memory). Despite the specified output message buffer size, SQLBase dynamically allocates more space for the output message buffer if needed. The default setting is 1,000 bytes. The maximum setting is 32,767 bytes.
Isolation levels
The SqlSetIsolationLevel function or the SqlIsolationLevel system variable sets the isolation level for the application when accessing a multi-user SQLBase database server. The isolation level controls the effect that changes made by one user have on another user accessing the same tables. SQLBase has these isolation levels: Read Repeatability (RR) (default) Cursor Stability (CS) Read Only (RO) Release Locks (RL)
Choose an isolation level based on the application's requirements for consistency and concurrency. The isolation level you set applies to all the Sql Handles for that user name that the application connects to the database. If you change isolation levels, it causes an implicit COMMIT for all Sql Handles that the application has connected to the database. In turn, an implicit COMMIT destroys all compiled statements and results sets for all Sql Handles that the application has connected to the database. However, changing to an isolation level that is the same as the current isolation level does not cause an implicit COMMIT. Read the explanation of isolation levels in the SQLBase SQL Reference (SET ISOLATION) for more.
SQL.INI
SQLWindows reads SQL.INI to determine the database servers that the application can access. SQLWindows looks for SQL.INI in this order: 1. 2. 3. 4. Current directory \SQLBASE (in current drive) Root directory (in current drive) As specified by the PATH environment variable
12-37
Chapter 12
SQL Programming
For more about SQL.INI, see the SQLBase Database Administrator's Guide.
ROWID validation
Each row in a SQLBase database has a hidden column called ROWID (row identifier) that uniquely identifies the row. A ROWID changes when the row is updated. With ROWID validation, an application can ensure that another application did not UPDATE or DELETE a SELECTed row while the user was browsing the data. If another application updates a row after your application reads it, you can detect it by the changed ROWID. The flowchart on the next page shows the steps in ROWID validation: 1. 2. If an UPDATE or DELETE is not successful, check the SQL error code to find if it is a ROWID error If it is a ROWID error, perform the changed-row processing, which depends on the nature of the application
The example after the flowchart shows one type of changed-row processing. ROWID Validation Start Prepare and execute a SELECT Include the ROWID in the SELECT list
Fetch rows
User changes a row Prepare and execute a DML statement UPDATE WHERE ROWID = or DELETE WHERE ROWID =
Successful
No
? Yes COMMIT ROWID valid ? Yes Changed-row processing When SqlError or SAM_SqlError End No
Error processing
12-39
Chapter 12
SQL Programming
Example
In the example on the next page, if the SQL error is an invalid ROWID, the When SqlError statements: Turn on DBP_FETCHTHROUGH to tell SQLWindows to fetch from the database server and not the input message buffer Compile and execute a SELECT statement Fetch the row Turn off DBP_FETCHTHROUGH
Global Declarations ... Constants ... User Number: DB_ERR_Row_ID = 806 ... Menu Item: Update ... Menu Actions When SqlError Call SalNumberToStr( nErr, 0, strNum ) Call SqlExtractArgs( wParam, lParam, hSqlError, nErr, nPos ) Call SqlGetErrorText( nErr, strErrmsg ) ! If nErr = DB_ERR_Row_ID ! ! An invalid row ID can happen if a second user UPDATEs ! a row after the first user retrieves it or the user ! UPDATEs a row once and then UPDATEs it ! again without refetching it ! Call SalMessageBox('You or another user have updated this row. Click OK to retrieve the row again. You will need to enter your changes again.', 'Update Error', MB_Ok | MB_IconExclamation ) Call SqlSetParameter( hSqlFetch2, DBP_FETCHTHROUGH, TRUE, strNull ) Call SqlPrepareAndExecute( hSqlFetch2, strSelectByName ) Set bOk = SqlFetchNext( hSqlFetch2, nFetch ) Call SqlSetParameter( hSqlFetch2, DBP_FETCHTHROUGH, FALSE, strNull ) ! Return FALSE !
Stored commands
Set bOk = SqlPrepare( hSqlChange, strUpdate ) Set bOk = SqlExecute( hSqlChange ) If bOk Call SqlCommit( hSqlChange )
Stored commands
Call these functions to use SQLBase stored commands:
Function SqlStore SqlRetrieve SqlDropStoredCmd Description Compiles and stores a statement Retrieves a stored statement Removes a stored statement
You can store compiled SQL statements in a database (in the SYSCOMMANDS system catalog table) with the SqlStore function and retrieve them with the SqlRetrieve function. You do not call SqlPrepare before you call SqlStore. SqlStore compiles the SQL statement before storing it. When you store a statement with SqlStore, you: Do not specify an INTO clause Specify bind variables with numeric names instead of actual variable names
When you retrieve a stored statement with SqlRetrieve, you specify: An INTO clause to use when executing it A list of variable names to use as bind variables
When you retrieve the statement, you supply the bind variables that replace :1 and :2, such as :dfLastName and :dfAge. After you retrieve a statement with SqlRetrieve, execute it with SqlExecute. Once you retrieve a statement, a COMMIT or ROLLBACK does not destroy it. If you are not the creator of the stored statement, you must qualify the statement name with the creator name and a period. For example, if SYSADM created the statement:
SYSADM.statement-name
12-41
Chapter 12
SQL Programming
When you store a statement, SQLBase creates an optimized execution plan based on the data in the database at that time. If the data later changes (for example, if the distribution of values in index columns changes), then the execution plan is no longer optimal. For production applications where data changes often, drop stored statements and restore them on a scheduled basis to keep the execution plans up-todate. If you change the structure of a table that a stored command uses, you get an error when you try to retrieve the stored command. These are examples of actions that change the structure of a table: ALTERing columns Adding or removing columns Dropping tables Dropping indexes
Chained commands
You can retrieve several stored commands with one call to SqlRetrieve and execute them with one SqlExecute. To do this, specify a list of stored command names separated by commas when you call SqlRetrieve. When using UPDATE in a chained command, you can specify the CHECK EXISTS clause to return an error if at least one row is not updated. You can use a SELECT statement in a chained command with the following restrictions: Only one SELECT statement can be in a chained command The SELECT statement must be the last statement in the chain
Call SqlRetrieve( hSql, 'mystoredfunction, 'build', ':tbl1.col1') ... Call SalTblPopulate( tbl1, hSql, '', TBL_FillNormal)
SqlVarSetup
Call SqlVarSetup to change the default behavior:
bOk = SqlVarSetup( hSql )
SqlVarSetup saves the current execution context. When you execute or fetch later, SQLWindows uses that execution context to resolve references to bind variables and into variables. Use this function to write: Global functions that store bind and into variables in local variables A hierarchy of classes where a base class can prepare and fetch and a derived class can specify the into variables
For new applications, call SqlVarSetup instead of these functions: SqlContextSet SqlContextClear SqlContextSet SqlContextSetToForm SqlImmediateContext
12-43
Chapter 12
SQL Programming
Sql* functions you call after SqlContextSet behave as if they are in the window identified by hWndForm. Call SqlContextSet in a class to perform SQL processing for the current window without fully qualifying bind and into variables. This function is also useful for internal functions. This function is like SqlContextSet, but you explicitly set the context to a specified window:
bOk = SqlContextSetToForm ( hSql, hWndMyForm)
After you call SqlContextClear, SQLWindows evaluates the bind and into variables associated with the specified Sql Handle in the local context. This function prepares and executes a SQL statement, and evaluates any bind or into variables in the context of the window identified by SqlContextSet or SqlContextSetToForm:
bOk = SqlImmediateContext( strSqlStatement )
Call this function to perform SQL processing for the current window without fully qualifying bind and into variables. If you call functions in this order: 1. 2. 3. 4. SqlContextSet SqlPrepare SqlContextClear SqlExecute
You may get a runtime error (such as <identifier> is defined by more than one form, dialog, or table window. Must qualify the reference.) when you call SqlExecute because SQLWindows compiles bind variables at execute time. The example above clears the context before the execute. To change the code so that it runs without errors, call SqlContextClear after the execute (or after the first fetch).
Character conversion
Character conversion
PCs use two different character sets: DOS command line applications (character mode) use an OEM character set Windows applications use the ANSI character set
The first 128 characters are the same in both character sets, but the characters above 128 are different. If you enter data in one character set and then read it with the other character set, the data does not display properly. For example, if you enter data with SQLTalk/ Character and then display the same data with SQLTalk/Windows, the characters above 128 are different. To avoid this problem, always maintain data in one environment. If you need to maintain data in both the Windows and DOS command-line environments, you can call functions in the Windows DLL KEYBOARD.DRV that convert between the character sets. The functions are called AnsiToOem and OemToAnsi.
Named cursors
Function SqlOpen SqlClose Description Names a cursor and executes a SQL statement Frees a named cursor
The cursor name that you specify in SqlOpen you also use in the: WHERE CURRENT OF clause for an UPDATE or DELETE statement ADJUSTING clause of an INSERT statement
Named cursors lock pages in the database. Instead, use the Release Locks isolation level, ROWID validation, and DBP_FETCHTHROUGH to maximize performance and concurrency. For more, read ROWID validation on page 12-38. You cannot use named cursors with chained commands.
Database Explorer
The Database menu contains items that let you browse database objects and prototype SQL statements. For more, read Database Explorer on page 4-39.
SQL troubleshooting
This section explains common SQL problems and their solutions. 12-45
Developing with SQLWindows
Chapter 12
SQL Programming
Q1: I get Cannot open the database message (401) on a SqlConnect. A1: There are two common causes: The database (*.DBS) files are incompatible with the version of SQLWindows. The section called [DBWINDOW] contains the DBDIR keyword that tells DBWINDOW.EXE where to look for the database files. If the database files are not in the directory that DBDIR points to, you get the error message. Q2: I call SqlPrepare and SqlExecute, but data fields are not being populated. A2: SqlPrepare compiles the SELECT statement and SqlExecute executes the query, but does not populate the data fields. To populate the data fields, you must call SqlFetchRow or SqlFetchNext. SalTblPopulate and SalListPopulate perform all three functions. SqlPrepareAndExecute combines the SqlPrepare and SqlExecute in one function. Q3: I use one Sql Handle in an application to call SqlPrepare, SqlExecute, and SqlFetchNext to build a result set and fetch data into data fields. Using the same Sql Handle, I call SqlPrepare and SqlExecute after this to INSERT data. I then try to fetch another row from the result set, and I get a Not a SELECT command message (202). A3: A single Sql Handle is associated with only one compiled statement at a time. Calling SqlPrepare and SqlExecute again on the same handle destroys the previous result set. To perform the INSERT without destroying the result set, you need to use two separate Sql Handles, one for each compiled statement. Q4: I have two Sql Handles in an application. I call SqlPrepare, SqlExecute, and SqlFetchNext for the first Sql Handle. Then I call SqlCommit for the second Sql Handle. Finally, I perform another SqlFetchNext for the first Sql Handle and I get a No compiled command message (201). A4: A COMMIT, ROLLBACK, or change in isolation level destroys the compiled statements associated with Sql Handles connected to the same database. COMMITting on the second Sql Handle destroys the result set built by the first Sql Handle, since both Sql Handles are connected to the same database. To preserve the result set so that it is not destroyed by COMMITs, ROLLBACKs, or changes in isolation level, call SqlSetParameter on the Sql Handle for the result set and set DBP_PRESERVE to TRUE. This turns on cursor-context preservation and preserves the result set. Q5: I have a table window with data in it. I change information in one row and then call SalTblDoUpdates to make the changes in the database. Later, when I try to update the same row again, I get an Invalid ROWID message (806). A5: The problem is that the ROWID has changed. SQLBase automatically defines ROWIDs. SQLBase uses ROWIDs to identify a particular version of a row in a
SQL troubleshooting
database table. Each time you change a row, its ROWID changes. The example builds a result set that contains ROWIDs which match the ROWIDs in the database. However, once you UPDATE, the ROWID in the database changes. At this point, the ROWID in the result set and the ROWID in the database are different. If you try to refer to that row again using the result set ROWID, SQLBase is not be able to find that row in the database. Handle this problem by calling SqlSetParameter to turn on DBP_FETCHTHROUGH. Then, call SqlFetchRow immediately after each UPDATE. The row, along with its new ROWID, is fetched from the database into the result set. Later, when you UPDATE that row again, the ROWID in the result set and the ROWID in the database match, and SQLBase is able to find the row. For best performance, turn on DBP_FETCHTHROUGH immediately after the UPDATE, perform the fetch, and then turn off DBP_FETCHTHROUGH after the fetch. Otherwise, you always fetch rows from the database instead of from the input message buffer, which degrades performance.
12-47
Chapter 13
OLE DB Consumer
This chapter discusses how to access relational and non-relational data sources from SQLWindows. It describes: When to use the OLE DB consumer Session Handle data type How to access OLE DB data sources Sql* functions OLE DB stored procedures SAL/OLE DB mapping
13-1
Chapter 13
OLE DB Consumer
SQLWindows as a consumer
SQLWindows is an OLE DB consumer that can work with any OLE DB provider to access both relational databases using existing SQL language statements and access functionality. This diagram shows the OLE DB architecture: SQLWindows application Sql* function calls
OLE DB consumer
OLE DB provider
OLE DB provider
OLE DB provider
ODBC driver
Relational DBMS
Relational DBMS
Relational DBMS
An OLE DB provider responds to queries and returns data in a usable form; an OLE DB consumer accesses a data source. To learn more about OLE DB, read Microsoft OLE DB 2.0 Programming Reference and Data Access SDK.
transaction as a separate identity so there is a one-to-one association with a session and a transaction. You also use a Sql Handle to identify individual statements. You call SqlCreateSession and SqlFreeSession to create a session and free a session. These functions let you create multiple concurrent transactions in a straightforward manner. To execute SQL statements as part of a transaction call SqlCreateStatement to create cursor (statement) handles.
Determine the progID or provider name for the provider. Each provider you own has a provider name. For example, the provider name for the Microsoft SQL Server OLE DB provider is SQLOLEDB. For more, read Sql* functions on page 13-4. If you want to set optional session properties at the creation of a session itself, you can do it by adding the keyword and its value after the provider name keyword/ value pair in the strSessionProperties variable. For example, to set the initial catalog (database) for Microsoft SQL Server, set it like this:
Set strSessionProperties = "Provider=SQLOLEDB;" Set strSessionProperties = strSessionProperties || "Initial Catalog=pubs;"
2.
Set the server name, user ID, and password for the session:
Set SqlDatabase = 'SQL70' Set SqlUser = 'sa' Set SqlPassword = 'sa'
For example, for Microsoft SQL Server 7.x, the server name can be SQL70, the user ID can be sa, and the password can be sa. (For SQLBase, the server name can be ISLAND, user ID can be SYSADM , and the password can be SYSADM .) 3. Create a session using SqlCreateSession to acquire an individual Session Handle:
Set bOk = SqlCreateSession ( Session_Handle, strSessionProperties)
13-3
Chapter 13
OLE DB Consumer
To support multiple connections or transactions, you identify a transaction as a separate identity. You use the Session Handle to create a one-to-one association between a session and a transaction. 4. Call SqlCreateStatement to acquire a Sql Handle:
Set bOk = SqlCreateStatement ( Session_Handle, Sql_Handle )
You can use this Sql Handle (cursor) with most SAL functions that take a Sql Handle as a parameter.
Note: You can also use SqlCreateSession and SqlCreateStatement to connect to SQLBase for multi-connection transactions without the access going through OLE DB. For more, read Multiconnection transactions on page 12-25.
5. 6.
Perform tasks using SAL functions. Free the session and release the Session Handle using SqlFreeSession.
Sql* functions
The following Sql* functions, listed in alphabetical order, support SQLWindows as a consumer. Refer to the SQLWindows Function Reference or the online help for details.
SqlCloseAllSPResultSets (hSql)
This function closes any result sets generated by the execution of a stored procedure. This function is useful when you want to retrieve the return status of the stored procedure without having to go through all the result sets and close them individually.
SqlCommitSession (hSession)
This function commits the current transaction associated with the specified session. The SQL operations currently active on all the statements belonging to this session commit.
Sql* functions
SqlFreeSession (hSession)
This function frees the session. If there are any open statements belonging to this session, they are closed before the session is freed.
13-5
Chapter 13
OLE DB Consumer
SqlRollbackSession (hSession)
This function rolls back the current transaction associated with the specified session. The SQL operations currently active on all the statements belonging to this session roll back.
The following are supported: Input parameters. All SAL data types are supported as input parameters to a stored procedure. Output parameters are support for the Oracle OLE DB provider, except for array parameters. Output parameters for Miscrosoft SQL Server OLE DB provider are not supported. Return values. Multiple result sets.
Note: If you are using an OLE DB connection to SQL Server, and you are executing a stored procedure that returns a result set, do not set SqlResultSet to TRUE. SQL Server does not support scrollable result sets for stored procedures.
13-7
Chapter 13
OLE DB Consumer
SAL functions SqlDisconnectWithoutCursor SqlDropStoredCmd SqlExists SqlGetCursor SqlGetError SqlGetErrorText SqlGetErrorTextX SqlImmediate SqlImmediateContext SqlPLSQLCommand SqlSetIsolationLevel SqlStore Syb* functions
Supported or deprecated Use SqlGetCmdOrRowsetPtr or SqlGetDSOrSessionPtr Not supported for OLE DB connections Not supported for OLE DB connections Use SqlGetCmdOrRowsetPtr or SqlGetDSOrSessionPtr Use SqlGetSessionErrorInfo Use SqlGetSessionErrorInfo Use SqlGetSessionErrorInfo Not supported for OLE DB connections Not supported for OLE DB connections Not supported for OLE DB connections Use SqlSetSessionParameter Not supported for OLE DB connections Not supported for OLE DB connections; use native router connectivity
13-9
Chapter 14
Report Programming
This chapter explains how a SQLWindows application can print and display reports based on report templates created with Report Builder, including: SalReport* functions SAM_Report* messages RPT_* constants
14-1
Chapter 14
Report Programming
Report Builder has two environments: At designtime, you create a report layout. At runtime, a SQLWindows application passes data for the report to Report Builder. The application can print or display the report. An application can also create a report template at runtime.
Designtime
The diagram below shows the designtime and runtime environments of Report Builder: Designtime environment Runtime environment Source data Report Builder SQLWindows application
Report template
Displayed or printed reports As used in this chapter, the term Report Builder means the collection of files that make up the designtime and runtime environments.
Designtime
At designtime, you use Report Builder to define the format of a report. You do not associate a report template with a specific data source. A SQLWindows application that you write (using the functions and messages explained in this chapter) supplies the data. The sections below explain the Report Builder concepts that are relevant for a SQLWindows application. Read Business Reporting for how to create a report template with Report Builder.
Report template
A report template describes the layout and format of a report. The report template shows how the data appears in the parts of a report.
14-3
Chapter 14
Report Programming
Blocks
A report is divided into blocks. A block is a group of related lines on a report. These are the types of blocks: A report header at the beginning (such as the title of a report or summary information). A page header at the top of each page. Detail block which is the body of a report. Header and footer blocks for each break group you define. A break group separates detail blocks into logical groups such as regions or departments. A break group controls when subtotals are printed. A page footer at the bottom of each page. A report footer at the end (such as grand totals).
Input items
A SQLWindows application supplies values for the report fields associated with input items. An application passes a set of values for the input items each time it receives a SAM_ReportFetchNext message. At designtime, you specify input items with the Input menu:
Input variables
Input variables are like input items, but you have more control over when you can set them. These are the types of input variables: String Number Date/Time
Runtime
Object
Runtime
At runtime, Report Builder requests and receives data from a SQLWindows application, formats it, performs calculations, and displays or prints the report. A SQLWindows application communicates with Report Builder by calling SalReport* functions; Report Builder communicates with SQLWindows applications through SAM_Report* messages. The SQLWindows application is called the server because it supplies data; Report Builder is the client because it requests data. At runtime, a SQLWindows application can: Print or display a report using an existing report template Create a new report template Create a new report template based on a table window Print or display a report using table window data
Sections in this chapter show examples for each of these The report template and the SQLWindows application are independent of each other. The SQLWindows application calls a SalReport* function that specifies the name of the report template. Then, Report Builder sends messages to the SQLWindows application to ask for data. The data that the application sends must correspond to the input items defined in the report template.
14-5
Chapter 14
Report Programming
The diagram below shows the basic steps you follow to display or print a report: SQLWindows application SalReportView or SalReportPrint SAM_ReportStart SAM_ReportFetchInit Report Builder
Report template
The steps are explained below: Call SalReportView or SalReportPrint. Process the SAM_ReportStart message by performing initialization needed before sending report data to Report Builder: If the data source is a database, you can call SqlConnect and then call SqlPrepare for a SELECT statement If the data source is a file, you can open the file
Report Builder ignores a value you Return in SAM_ReportStart processing. Process SAM_ReportFetchInit. Report Builder sends SAM_ReportFetchInit when it is ready to format the first page of a report. To process SAM_ReportFetchInit, the application can initialize variables and do whatever is needed to get the start of the report data. For example: For a database, you can call SqlExecute For a file, you can set the file pointer to the start of the file
If you Return FALSE, the report stops. If you do not Return a value, or you do not process the message, the report continues.
SalReportPrint
Process SAM_ReportFetchNext messages. Report Builder sends SAM_ReportFetchNext when it is ready for the next set of data. The application processes SAM_ReportFetchNext by setting variables and objects that the report needs. For example: For a database, you can call SqlFetchNext For a file, you can set the file pointer to the position of the next record
Return TRUE in the SAM_ReportFetchNext processing if the application successfully fetched or read data. When you return TRUE, SQLWindows sends the report data to Report Builder. Return FALSE when the application has sent the last set of data for the report. Process SAM_ReportFinish by performing cleanup operations: For a database, you can call SqlDisconnect For a file, you can close the file
SalReportPrint
Call SalReportPrint to print a report using an existing report template:
Call SalReportPrint( frmServer, strReportTemplate, strVariables, strInputs, nCopies, nOptions, nFirstPage, nLastPage, nError )
The frmServer parameter is the name or handle of a window that processes SAM_Report* messages. This is not the same window that SalReportPrint returns. SalReportPrint is synchronous and does not return until the report has been formatted and sent to Windows or Windows print manager for printing. When printing a report, Report Builder creates a hidden window that it uses to communicate with SQLWindows. For all SAM_Report* messages, the wParam contains the handle of this window. When this function executes, SQLWindows sends the application SAM_Report* messages. The strReportTemplate parameter is the name of the report template created with Report Builder. The strVariables parameter is a list of variables in the application that contain data to use for the report at each SAM_ReportFetchNext.
14-7
Chapter 14
Report Programming
The strInputs parameter is a list of the input items that are defined in the report template. The order of the input items must match the order of the variable names in strVariables. This parameter is optional and is provided so that an application can use: A order different than specified for the input items in the report template Variable names that are different than the input items in the report template
The nCopies parameter is the number of copies of the report to print. You must set nCopies greater than zero. You can set the nOptions parameter to the values in the table below:
Constant RPT_PrintAll (default) RPT_PrintDraft RPT_PrintNoAbort RPT_PrintNoErrors RPT_PrintNoWarn RPT_PrintRange Print all pages of the report Print the report in draft quality (fastest) Do not display the dialog that lets the user cancel the report Suppress error message dialogs during printing Suppress warnings about margin overflow and tiled pages Print a range of pages in the report Description
You can combine RPT_PrintDraft with RPT_PrintRange using the OR (|) operator. If you specify RPT_PrintRange, you specify the page numbers in the range in nFirstPage, and nLastPage. If successful, SalReportPrint returns 0 in nError. If not successful, SalReportPrint returns an RPT_Err* constant in nError. The table on the next page lists the RPT_Err* constants. The value that SalReportPrint returns is reserved for future use and can be ignored.
Error handling
In run mode at designtime, SQLWindows always displays a dialog with an explanation if an error happens:
SalReportPrint
This dialog is useful while you are developing an application. However, for *.EXE applications, SQLWindows only displays an error dialog if you set the nError parameter to one before calling SalReportPrint.
RPT_Err* constants
The SalReport* functions return these RPT_Err* constants:
Constant RPT_ErrBind RPT_ErrCount RPT_ErrFilenameLength RPT_ErrFileOpen RPT_ErrInput RPT_ErrLoadDLL RPT_ErrMaxRpts RPT_ErrPrtOpen RPT_ErrRptOpen RPT_ErrRptWindow RPT_ErrType Description A bind error happened Too many bind/input variables The report file name is too long Cannot open the report template Mismatch between an input variable and a bind variable Cannot load the required DLLs Exceeded the maximum number of reports Cannot open the printer Cannot open the report Cannot open the report window Input variable data type does not match bind variable data type
SalReportDlgOptions
By default, SalReportPrint displays this dialog while printing:
Call SalReportDlgOptions after SalReportPrint, but before printing begins, such as when processing the SAM_ReportFetchInit or SAM_ReportStart message. To get the window handle while processing these messages, use the wParam of the
Developing with SQLWindows
14-9
Chapter 14
Report Programming
SAM_ReportStart or SAM_ReportFetchInit message (you need to convert the wParam to a window handle with SalNumberToWindowHandle). Do not use the hWndReport value that SalReportPrint returns because it may not yet be valid. The strCaption, strLine1, and strLine2 parameters are strings that SQLWindows displays in the dialog. The strDocName parameter is the string that Windows print manager displays.
Example
This example shows a menu item that calls SalReportPrint: Set nOptions to RPT_PrintAll to print all pages in the report. Set nCopies to 1 to print 1 copy of the report. Call SalReportPrint. The SAM_ReportStart processing: Calls SalReportDlgOptions to create a custom dialog that is displayed while printing Connects to a database
The SAM_ReportFetchInit processing calls SqlPrepare and SqlExecute for the SELECT statement. The SAM_ReportFetchNext processing calls SqlFetchNext. After the last row has been fetched, the message processing returns FALSE to tell Report Builder that there is no more data for the report. The SAM_ReportFinish processing disconnects from the database.
Global Declarations ... Constants ... String: RPT_Template = 'salesumm.qrp' String: RPT_Variables = ':strSalesAgent, :dtSaleDate, :strCustFirst, :strCustLast, :nStyleID, :nStylePrice' String: RPT_Inputs = 'SALES_AGENT, SALE_DATE, CUST_FIRST_NAME, CUST_LAST_NAME, STYLE_ID, STYLE_PRICE' String: SQL_Select = 'select sd.sales_agent, sd.sale_date, c.first_name, c.last_name, sd.style_id, s.style_price into :strSalesAgent, :dtSaleDate, :strCustFirst, :strCustLast, :nStyleID, :nStylePrice from sales_data sd, customers c, styles s where sd.customer_id = c.customer_id and sd.style_id = s.style_id order by sales_agent, sale_date' String: strCaption = 'The Haberdashery'
SalReportPrint
String: strLine1 = 'Fine Men\'s Clothing Since 1895' String: strLine2 = 'Sales Summary Report' String: strDocName = 'Sales Summary Report' Variables Window Handle: hWndReport String: strSalesAgent Date/Time: dtSaleDate String: strCustFirst String: strCustLast Number: nStyleID Number: nStylePrice Number: nCopies Number: nOptions Number: nFirstPage Number: nLastPage Number: nError Sql Handle: hSql Number: nFetch ... Form Window: frmMain ... Menu Item: &Print Report ... Menu Actions Set nOptions = RPT_PrintAll Set nCopies = 1 Set nError = 1 Set hWndReport = SalReportPrint( frmMain, RPT_Template, RPT_Variables, RPT_Inputs, nCopies, nOptions, nFirstPage, nLastPage, nError ) ... Message Actions On SAM_ReportStart Call SalReportDlgOptions( SalNumberToWindowHandle( wParam ), strCaption, strLine1, strLine2, strDocName ) Set SqlDatabase = 'SALES' Call SqlConnect( hSql ) On SAM_ReportFetchInit If NOT SqlPrepare( hSql, SQL_Select ) Return FALSE Else If NOT SqlExecute( hSql ) Return FALSE Else
14-11
Chapter 14
Report Programming
Return TRUE On SAM_ReportFetchNext If SqlFetchNext( hSql, nFetch ) If nFetch = FETCH_Ok Return TRUE Else Return FALSE On SAM_ReportFinish Call SqlDisconnect( hSql )
SalReportPrintToFile
Call SalReportPrint to File to write a report to a file in RTF format or ASCII text format:
hWndReport = SalReportPrintToFile ( hWndFrm, strTemplate strDestFile, strVariables,strInputs, nCopies, nOptions, nFirstPage, nLastPage, bFormat, nErr )
The parameters are the same as for SalReportPrint except for strDestFile which is the name of the file and bFormat which you set to TRUE if you want the report file to be saved in RTF (Rich Text Format) or FALSE for an ASCII text file. SalReportPrintToFile returns before printing begins.
SalReportView
Call SalReportView to display a report using an existing report template:
hWndReport = SalReportView( frmServer, frmDisplay, strReportTemplate, strVariables, strInputs, nFlag )
The return value (hWndReport) is the same as for SalReportPrint. Also, the frmServer, strReportTemplate, strVariables, and strInputs parameters are the same as for SalReportPrint. You can let Report Builder display the report in its standard view window or you can supply your own view window: To use the standard view window, pass hWndNULL in the frmDisplay parameter To use your own view window, pass its name or handle in the frmDisplay parameter
The standard view window is almost the same as the Report Builder designtime preview window. The standard form window has menu items and push buttons that 14-12 Developing with SQLWindows
SalReportView
let the user page forward and backward through the report, size the report, and print the report. If you use your own view window, you can supply these same functions by calling SalReportCmd (explained later).
SalReportView returns after report formatting begins. Before you call SalReportView, you can set nFlags to one of the constants below to turn off the printer icon on the default report view tool bar or turn off the tool bar completely: RPT_NoPrint RPT_NoToolbar No print button on the tool bar No tool bar in the preview window
After the functions returns, the nFlags parameter functions the same as the nError parameter for SalReportPrint.
SalReportCmd
If you use your own view window to display a report, you can provide the same functions as the standard report view window's menus and toolbar by calling SalReportCmd:
bOk = SalReportCmd( hWndReport, nCommand )
The hWndReport parameter is the window handle returned by SalReportView. The nCommand parameter is one of the RPT_Cmd* constants in the table below. You can only call SalReportCmd if you supplied your own window handle or name (in the frmDisplay parameter) when you called SalReportView.
14-13
Chapter 14
Report Programming
RPT_Cmd* constants
These are the RPT_Cmd* constants:
Constant RPT_CmdFirstPage RPT_CmdGoToPage RPT_CmdLastPage RPT_CmdNextPage RPT_CmdPrevPage RPT_ CmdPrint RPT_CmdPrinterSetup RPT_CmdSizeActual RPT_CmdSizeFit Description Displays the first page of the report Display a dialog where the user can enter the page number in the report to scroll to Displays the last page of the report Displays the next page of the report Display the previous page of a report Prints the report Displays the Printer Setup dialog so the user can change the print settings Displays the report in its actual size in the report window Displays the report sized to fit in the report window
Example
The constants, variables, and message processing are the same as for the SalReportPrint example and are not repeated here. When the user selects the Display Report menu item: Call SalReportView. The second parameter tells Report Builder the name of a form window defined in the application to use to display the report. The frmView form window that displays the report has top-level menu items that call SalReportCmd.
Form Window: frmMain ... Menu Item: &Display Report ... Menu Actions Set nError = 1 Set hWndReport = SalReportView( frmMain, frmView, RPT_Template, RPT_Variables, RPT_Inputs, nError ) ... Form Window: frmView ... Menu Item: First! ... Menu Actions Call SalReportCmd( hWndReport, RPT_CmdFirstPage )
SalReportReset
Menu Item: Last! ... Menu Actions Call SalReportCmd( Menu Item: Next! ... Menu Actions Call SalReportCmd( Menu Item: Print! ... Menu Actions Call SalReportCmd( Menu Item: Setup! ... Menu Actions Call SalReportCmd( Menu Item: Actual! ... Menu Actions Call SalReportCmd( Menu Item: Fit! ... Menu Actions Call SalReportCmd(
hWndReport, RPT_CmdLastPage )
hWndReport, RPT_CmdNextPage )
hWndReport, RPT_CmdPrint )
hWndReport, RPT_CmdPrinterSetup )
hWndReport, RPT_CmdSizeActual )
hWndReport, RPT_CmdSizeFit )
SalReportReset
SalReportReset clears a report window so you can display or print again with a new set of data:
bOk = SalReportReset( hWndReport )
The hWndReport parameter is the window handle returned by SalReportPrint or SalReportView. SalReportReset causes SAM_ReportFetchInit and SAM_ReportFetchNext messages.
Example
Except as explained below, the constants, variables, and message processing are the same as for the SalReportPrint example. The frmView window has a menu item that lets the user change the current report to a slightly different one: Set the b300 Boolean to TRUE. Call SalReportReset. The SAM_ReportFetchInit processing checks the b300 Boolean. If it is set, the code prepares and executes the SELECT statement. The SELECT stateDeveloping with SQLWindows
14-15
Chapter 14
Report Programming
ment is the same as for the SalReportPrint example except that the WHERE clause restricts the query to rows with a STYLE_PRICE value greater than 300.
Global Declarations ... Constants ... User String: SQL_Select3 = 'select sd.sales_agent, sd.sale_date, c.first_name, c.last_name, sd.style_id, s.style_price into :strSalesAgent, :dtSaleDate, :strCustFirst, :strCustLast, :nStyleID, :nStylePrice from sales_data sd, customers c, styles s where sd.customer_id = c.customer_id and sd.style_id = s.style_id and s.style_price > 300 order by sales_agent, sale_date' ... Variables Boolean: b300 ... Form Window: frmView ... Menu Item: Over &300 ... Menu Actions Set b300 = TRUE If NOT SalReportReset( hWndReport ) Call SalMessageBox( 'Report Error', 'SalReportReset', MB_Ok | MB_IconHand ) Set b300 = FALSE ... Form Window: frmMain ... Message Actions On SAM_ReportFetchInit If b300 If NOT SqlPrepare( hSql, SQL_Select3 ) Return FALSE Else If NOT SqlExecute( hSql ) Return FALSE Else Return TRUE Else ...
SalReportClose
SalReportClose
Use SalReportClose after SalReportPrint or SalReportView returns to end printing before the end of a report. For example, you can call SalReportClose in the actions for a cancel menu pick or a push button. With SalReportView, SalReportClose is the same as the user double-clicking the system menu of the report view window and the application calling SalDestroyWindow.
The strReportTemplate, strVariables, strInputs, and nError parameters are the same as for SalReportPrint and SalReportView. If the bDefault parameter is FALSE, SalReportCreate creates a report template with the input items that you specify in strInputs. You can then open the report template and complete its definition. If bDefault is TRUE, SalReportCreate creates a report template with the input items that you specify in strInputs, fields, and captions for the input items, and page headers and footers. You can then specify this report template in calls to SalReportPrint or SalReportView.
Example
The example below creates a report template named salesum2.qrp. The bDefault parameter is TRUE, so the report template will have the input items specified in RPT_Inputs, fields, captions, page headers, and page footers.
Menu Item: &Create Report Template ... Menu Actions Call SalReportCreate( 'salesum2.qrp', RPT_Variables, RPT_Inputs, TRUE, nError )
Input variables
The earlier examples showed generating reports with input items that the application passes each time it receives SAM_ReportFetchNext. At each SAM_ReportFetchNext, the application passes the same set of input items to Report Builder.
Developing with SQLWindows
14-17
Chapter 14
Report Programming
With input variables, you have additional control over: Data you pass to Report Builder When you pass data to Report Builder Data you can retrieve from a report
You set and get input variables with the SalReportSet*Var and SalReportGet*Var functions:
Function SalReportSetDateTimeVar SalReportSetNumberVar SalReportSetObjectVar SalReportSetStringVar SalReportGetDateTimeVar SalReportGetNumberVar SalReportGetObjectVar SalReportGetStringVar Description Sets a Date/Time input variable Sets a Number input variable Sets an object input variable Sets a String input variable Gets a Date/Time input variable Gets a Number input variable Gets an object input variable Gets a String input variable
You can call SalReportGet*Var and SalReportSet*Var while processing: SAM_ReportStart SAM_ReportFetchInit SAM_ReportFetchNext SAM_ReportNotify
If you process SAM_ReportNotify, you can detect which part of the report Report Builder is processing and set or get input variables as appropriate. For more, read Example on page 14-20.
SAM_ReportNotify
Report Builder sends the SAM_ReportNotify message when it is ready to format a part of a report. When you process SAM_ReportNotify, you can check the lParam to find the part Report Builder is ready to process. The lParam is one of the RPT_* constants in the tables below. Report Builder ignores any value that you return during SAM_ReportNotify processing.
SAM_ReportNotify
RPT_* constants
The RPT_* constants for SAM_ReportNotify are grouped in three categories according to when sent:
Category RPT_Before* RPT_Output* RPT_Done* When Sent Just before a report block is about to be formatted After a report block is formatted, but before it is output After the report block is output
14-19
Chapter 14
Report Programming
Example
This example checks the lParam to find if Report Builder is ready to process the first break header:
On SAM_ReportNotify If lParam = RPT_BeforeBreakHeader1 ! strPic contains an image. Set the report variable ! named PICTURE to the contents of strPic. Call SalReportSetObjectVar( frmMain, 'PICTURE', strPic )
SalReportTableCreate
You can create a report template by calling SalReportTableCreate:
bOk = SalReportTableCreate( strReportTemplate, hWndTable, nError )
The strReportTemplate parameter is the name of the report template. The hWndTable parameter is the handle of the table window. The nError parameter is the same as for the other SalReport* functions.
Here is how SQLWindows creates the report template: The column titles are used for the input item names. SQLWindows translates spaces in column titles to underscores. The page header contains the table window title, the date, and the column titles as background text. However, a report with data from a child table window does not have a title. The detail block contains the table window columns. The page footer contains a page number.
SalReportTablePrint
This function prints a report using table window data:
hWndReport = SalReportTablePrint( hWndTable, strReportTemplate, nParameterArray, nError )
The return value (hWndReport) is the same as for SalReportPrint and SalReportView. The hWndTable parameter is the handle of the table window. The strReportTemplate parameter is the name of the report template. The nParameterArray parameter is a numeric array that contains settings for printing parameters:
Offset 0 1 2 3 Offset constant RPT_PrintParamOptions RPT_PrintParamFirstPage RPT_PrintParamLastPage RPT_PrintParamCopies Description Same as nOptions for SalReportPrint and SalReportPrintToFile First page number to print Last page number to print Number of copies to print
The nError parameter is the same as for the other SalReport* functions.
SalReportTableView
This function displays a report using table window data:
hWndReport = SalReportTableView( hWndTable, hWndDisplay, strReportTemplate, nError )
The return value (hWndReport) is the same as for SalReportPrint and SalReportView.
14-21
Chapter 14
Report Programming
The hWndTable parameter is the handle of the table window. The hWndDisplay parameter is the same as for SalReportView. The strReportTemplate parameter is the name of the report template. The nError parameter is the same as for the other SalReport* functions.
Example
This example shows three menu items that call: SalReportTableCreate SalReportTableView SalReportTablePrint
Global Declarations ... Constants ... User ... String: SQL_Select2 = 'select sd.sales_agent, sd.sale_date, c.first_name, c.last_name, sd.style_id, s.style_price into :tblReport.colSalesPerson, :tblReport.colSalesDate, :tblReport.colFirstName, :tblReport.colLastName, :tblReport.colItem, :tblReport.colPrice from sales_data sd, customers c, styles s where sd.customer_id = c.customer_id and sd.style_id = s.style_id order by sales_agent, sale_date' ... Variables Window Handle: hWndReport Window Handle: hWndTable Number: nError Sql Handle: hSql Number: nFetch Number: nPrintParmArray[4] ... Form Window: frmMain ... Menu Item: &Create ... Menu Actions Set hWndTable = SalCreateWindow( tblReport, frmMain ) If NOT SalTblPopulate( hWndTable, hSql, SQL_Select2, TBL_FillNormal ) Call SalMessageBox( 'Cannot populate table window', 'Table Window Error', MB_Ok )
Else Set nError = 1 Call SalReportTableCreate( 'salesum3.qrp', hWndTable, nError ) Menu Item: &View ... Menu Actions Set hWndTable = SalCreateWindow( tblReport, frmMain ) If NOT SalTblPopulate( hWndTable, hSql, SQL_Select2, TBL_FillNormal ) Call SalMessageBox( 'Cannot populate table window', 'Table Window Error', MB_Ok ) Else Set nError = 1 Set hWndReport = SalReportTableView( hWndTable, hWndNULL, 'salesum3.qrp', nError ) Menu Item: &Print ... Menu Actions Set hWndTable = SalCreateWindow( tblReport, frmMain ) If NOT SalTblPopulate( hWndTable, hSql, SQL_Select2, TBL_FillNormal ) Call SalMessageBox( 'Cannot populate table window', 'Table Window Error', MB_Ok ) Else Set nError = 1 Set nPrintParmArray[RPT_PrintParamCopies] = 1 Set hWndReport = SalReportTablePrint( hWndTable, 'salesum3.qrp', nPrintParmArray, nError ) ... Table Window: tblReport ... Title: Sales Summary ... Contents Column: colSalesPerson ... Title: Sales Person ... Data Type: String ... Column: colSalesDate ... Title: Sales Date ... Data Type: Date/Time ... Column: colFirstName
14-23
Chapter 14
Report Programming
... Title: Cust First Name ... Data Type: String ... Column: colLastName ... Title: Last Name ... Data Type: String ... Column: colItem ... Title: Item ... Data Type: Number ... Column: colPrice ... Title: Price ... Data Type: Number
Chapter 15
Table Windows
This chapter explains table windows including: Types of table windows User interface Simple and advanced programming techniques Table window features Table window messages
15-1
Chapter 15
Table Windows
Table windows have many features that give a developer flexibility in creating powerful applications. A table window is a matrix of rows (records) and one or more columns. The intersection of a row and column is called a cell. A table window represents a relational table well. This makes a table window suited for displaying queries.
Both types of table windows refer to the entire window as a single entity. 15-2 Developing with SQLWindows
Minimizable
15-3
Chapter 15
Table Windows
Property Icon File Location and Size Lines per row Allow row sizing
Description A file that contains an icon used when the table window is minimized. The icon file must be in *.ICO format. Displays a cascading menu with the table window's position (top and left) and size (width and height). By default, the lines per row is one. When you set lines per row to two or more, text wraps in columns where you turn on word wrap. If Yes, users can drag and resize rows at runtime. You can also change this setting dynamically at runtime by calling SalTblDefineRowHeader and specifying TBL_RowHdr_RowsSizable. The background color of the table window. The color of text in the table window. The font of text in the table window. The font size of text in the table window. The font enhancement of text in the table window. If Yes (default), rows in the table window cache are discardable. SQLWindows makes space for new rows by discarding unused rows. If No, SQLWindows does not automatically discard rows and keeps all data in the cache. The number of table window rows that can be stored in the cache. The default is 100 and the maximum is 2,147,423,632 rows. Please see the section Table Window Cache Beginning on page 14-33 for more details. Set this property to Yes if you want this top-level window to allow docked windows.. Default value is No. This property is enabled only if the Allow child docking property is set to Yes. This property controls which directions can a child window dock itself to this top-level window.
Background Color Text Color Font Name Font Size Font Enhancement Discardable
have minimize and maximize push buttons. A child table window is created and destroyed along with its parent.
15-5
Chapter 15
Table Windows
Property Background Color Text Color Font Name Font Size Font Enhancement Discardable
Description The background color of the table window. The color of text in the table window. The font of text in the table window. The font size of text in the table window. The font enhancement of text in the table window. If Yes (default), rows in the table window cache are discardable. SQLWindows makes space for new rows by discarding unused rows. If No, SQLWindows does not automatically discard rows and keeps all data in the cache. The number of table window rows that can be stored in the cache. The default is 100 and the theoretical maximum is 2,147, 423,632 rows. For more information, read Table window cache on page 15-35.
Adding columns
You can add columns like other child objects by: Clicking the column push button in the Controls palette OR Selecting Column in Coding Assistant OR Entering the column definition directly into the outline
After you click the column push button in the Controls toolbar, move the mouse pointer to the left side of the table window until the mouse pointer changes to the one shown on the left. Click to add the first column. To add more columns, more the mouse pointer to the right side of an existing column and click.
15-7
Chapter 15
Table Windows
Column attributes
The table below describes the attributes for a table window column. To display the Attribute Inspector for a column, position the mouse pointer on the column heading and right-click. .
Property Object Name Object Title Visible Description The name you use to refer to the column in statements. The title in the column heading. Create a mnemonic by adding an ampersand (&) before the letter that is the mnemonic. If Yes (default), the column is visible at runtime. If No, the column is not visible at runtime. At runtime, you can change the setting of this property with SalHideWindow and SalShowWindow. Column Width Data Type The width of the column in inches. The default is 1.2 inches. The data type of the column: String Long String Number Date/Time Max Data Length The maximum number of characters that the user can enter in the column. The default is 100. The maximum length of a String or Long String data type is 32 kilobytes. This option is only available if the column is editable. Important: The value that you specify in Max Data Length is the maximum capacity of the object, not the number of bytes that SQLWindows allocates for the objects value. At runtime, SQLWindows allocates the number of bytes in the actual value of the object at any one time. Also, when you set a variable or another object with the value, SQLWindows only copies the number of bytes in the actual value, not the number of bytes in the Max Data Length setting of the source object. Cell Type You can set this item to: Standard Drop Down List Behaves like a combo box when a cell gets the focus. When you set this, you can set properties for the list (read the entry for Drop Down List below). Popup Edit Check Box Behaves like a multiline field when a cell gets the focus. Behaves like a check box when a cell gets the focus. When you set this, you can set properties for the check box (read the entry for Check Box below). At runtime, a user cannot enter characters in this cell type. Default Use to read and write SQL database columns longer than 254 bytes
User interface
Description When you set the Cell Type to Drop Down List, you can set this to: Sorted Vertical Scroll Auto Drop Down Allow Text Editing SalListFiles SalListGetMultiSelect SalListQueryFile SalListQueryMultiCount SalListSetMultiSelect Items in the list are sorted The list has a vertical scroll bar The list drops automatically when a cell gets the focus User can type new text as well as choosing an item from the list
Note: You can call any SalList* function for a column that you set as a drop down list, except for:
Check Box
When you set Cell Type property to Check Box, you can set this to: Checked Value Unchecked Value Ignore Case When the cell contains this value, the check box is checked When the cell contains this value, the check box is not checked The values you specify for checked and unchecked are compared to the cell value without regard for case
Editable
If Yes (default), the user can enter and edit the column text. If No, the user cannot enter or edit text. At runtime, you can change the setting of this property with SalEnableWindow and SalDisableWindow.
Justification for the column. The default is left. The output format of the column. The default is unformatted. For more, read Chapter 11, Formatting and Validating. Input validation criteria for the column. For more, read Chapter 11, Formatting and Validating. The country profile for the column. For more, read Chapter 11, Formatting and Validating. When the lines per row is two or more, you can set this property to Yes so that text in the cell wraps automatically.
User interface
This section explains basic table window functions from the point of view of a user.
15-9
Chapter 15
Table Windows
Note: A user can also move and resize columns using the mouse pointers explained in the section called Moving and Sizing Columns earlier in this chapter.
Row mode
In row mode, you can select one or more entire rows. When a row is selected, it has a dark background, and light characters (sometimes called inverse-video or reversed). When a row is not selected, it has a white or light background and the characters in it are black or dark unless the user has changed the system colors. Selected rows can be non-contiguous.
Cell mode
In cell mode, you can enter or edit data in the cells of a row. For example, the right and left arrow keys move the insertion point between characters.
Insertion point
In cell mode, the row with the focus frame contains the insertion point. The insertion point is a blinking vertical line. When you type, text appears at the insertion point.
User interface
Description If the table is a top-level window, puts the table in cell mode and selects the first editable cell on the focus row. If the table is a child window, moves to the next cell if the table is in cell mode, otherwise moves from object to object on the form window or dialog box. Toggles the selection of the focus row. Moves the focus frame up. Selects the focus row. Moves the focus frame up. Selects or deselects the focus row as the previous focus row. Moves the focus frame up. Table selection is not affected. Moves the focus frame down. Selects the focus row. Moves the focus frame down. Selects or deselects the focus row just as the previous row. Moves the focus frame down. The table window selection is not affected. Scrolls into view the window columns to the right. Scrolls into view the window columns to the left. Displays the previous window of rows. Displays the previous window of rows. The table window selection is not affected. Displays the next window of rows. The first row is selected. Displays the next window of rows. The table window selection is not affected. Displays the rows at the beginning of the table window. Displays the rows at the beginning of the table window. The table window selection is not affected. Displays the rows at the end of the table. Selects the last row in the table window. Displays the rows at the end of the table. The table window selection is not affected. Selects all displayed rows.
Space Bar Up Arrow Shift+Up Arrow Ctrl+Up Arrow Down Arrow Shift+Down Arrow Ctrl+Down Arrow Right Arrow Left Arrow Page Up Ctrl+Page Up Page Down Ctrl+Page Down Home Ctrl+Home End Ctrl+End Shift+PgUp Shift+PgDown
15-11
Chapter 15
Table Windows
Programming techniques
There are two general programming techniques that you can use with table windows: Simple technique Advanced technique
Simple technique
You use this technique when the data for the table window comes from a SQL database.
Advanced technique
You use this technique when the data for the table window comes from a nondatabase source such as an array, a flat file, or variables.
Programming techniques
You can also use the advanced technique when the source of data is a SQL database, although it is easier to use the simple technique. However, the advanced technique is more flexible. For new database applications, you probably want to use the simple technique.
The rest of this section covers how these operations work with the two techniques.
Code examples
Note the following about the code examples in this section: Only code directly related to processing a table window is shown. Unrelated details such as changing the cursor or displaying a confirmation dialog box are not shown. SQL database processing is done in result set mode.
The first parameter is a table window handle. The second parameter is a Sql Handle. The third parameter is a SELECT statement. If the SELECT statement has not been prepared, specify it in this parameter (as done in this example). If a SELECT statement has already been prepared, specify an empty string (''). The fourth parameter specifies the way in which to populate the table. TBL_FillNormal means to populate only the visible portion of the table window. Additional rows are populated as the user scrolls them into view.
15-13
Chapter 15
Table Windows
Deleting a row
In the delete operation described below, the user selects one or more rows in the table window and then chooses the Delete menu item. The steps below are performed in the Menu Actions section. 1. Call SalTblAnyRows to find if any row has the ROW_Selected flag set to TRUE:
Call SalTblAnyRows( tblCompanyInfo, ROW_Selected, 0 )
The second parameter says to find rows that have these flags on (ROW_Selected in this example). The third parameter says to find rows that have these flags off. This is not appropriate in this example, so zero is specified. 2. Call SqlPrepare and specify a DELETE statement:
Call SqlPrepare( hSqlA, 'DELETE FROM COMPANY ' || 'WHERE ID = :tblCompanyInfo.cnID' )
3.
SalTblDeleteSelected finds all rows that have the ROW_Selected flag set to TRUE and deletes the rows from both the table window and the database. The Sql Handle (hSqlA) must be associated with a DELETE statement. You can also use SalTblDoDeletes to delete rows. SalTblDoDeletes is like SalTblDeleteSelected, except that you specify the flags that of the rows to delete (such as ROW_MarkDeleted or ROW_Selected):
Call SalTblDoDeletes( tblCompanyInfo, hSqlA, ROW_Selected )
4.
Inserting rows
There are two parts to inserting rows: The user chooses an Insert menu item that creates a new, empty row in the table window After the user has created and entered data in one or more new rows, the user chooses the Apply Changes menu item to INSERT the new rows into the database
For the first part, the steps below are performed in the Menu Actions section for the Insert menu item. 1. Create a new row in the table window by calling SalTblInsertRow:
Set nIndex = SalTblInsertRow( twCompanyInfo, TBL_MaxRow )
Programming techniques
SalTblInsertRow adds a blank row at the location you specify. In the example above, the second parameter is a flag that says to add the new row at the end of the table window. SalTblInsertRow returns the row number in nIndex, which is used in the next two function calls. 2. Set the focus to the new row and position the text insertion bar to a cell in the row by calling SalTblSetFocusCell:
Call SalTblSetFocusCell( twCompanyInfo, nIndex, csName, 0, -1 )
The second parameter is the row number returned by SalTblInsertRow. The third parameter specifies where to set the column focus in the row. The fourth and fifth parameters select specific characters within the focus cell. This is not needed for this example, so 0, -1 is used for these parameters to select the entire cell. The user can now enter data in the cells of the new table window row. For the second part, the steps which follow are performed in the Menu Actions section of the Apply Changes menu item. They INSERT one or more new rows into the database that the user entered: 1. The user might not have moved the cursor off a newly-inserted row. Call SalTblKillEdit to force the setting of the ROW_Edited flag, the result of which is the validation (checking of the data type) of the value that the user entered:
Call SalTblKillEdit( twCompanyInfo )
2.
Call SalTblAnyRows to find if any row has the ROW_New flag set to TRUE:
If SalTblAnyRows( tblCompanyInfo, ROW_New, 0 )
The second parameter says to find rows that have these flags on (ROW_New in this example). The third parameter says to find rows that have these flags off. This is not appropriate in this example, so zero is specified. ('If' is used instead of 'Call' because 'Call' would ignore the boolean return. The function returns TRUE if any row has ROW_New set to TRUE.)
Call SqlPrepare and specify an INSERT statement: Call SqlPrepare( hSqlA, 'INSERT INTO COMPANY( ID, ..., FAX)' || 'VALUES( :twCompanyInfo.cnID, ' || ... ':twCompanyInfo.csFAX ) ' )
3.
Call SalTblDoInserts:
Call SalTblDoInserts( tblCompanyInfo, hSqlA, FALSE )
SalTblDoInserts finds and INSERTs all rows that have the ROW_New flag set to TRUE. The second parameter is the Sql handle that must be associated with an INSERT statement. The third parameter says not to clear the ROW_New flag of
Developing with SQLWindows
15-15
Chapter 15
Table Windows
each row after inserting it in the database. You do not want to insert part of the rows and then have a rollback happen. If that happened, you lose flags for the partial transaction. It is better to wait until you have successfully inserted all rows are before clearing the ROW_New flag. 4. 5. COMMIT or ROLLBACK the INSERT. Set the table window row number to TBL_MinRow:
Set nRow = TBL_MinRow
6.
Call SalTblFindNextRow to find the next row with the ROW_New flag set to TRUE. The second parameter is the table window row number which indicates where the search is to start (this was set to TBL_MinRow in the previous step). When it finds a row that matches the flag (ROW_New), SalTblFindNextRow returns the row number in this parameter. The third parameter specifies flags for the row. The fourth parameter specifies flags that the row does not have; this is not appropriate for this application, so zero is specified. The loop repeats until there are no more rows with the ROW_New flag set to TRUE. Call SalTblSetRowFlags to clear the ROW_New and ROW_Edited flags for the processed row. The third parameter are the flags to set to FALSE (ROW_New and ROW_Edited ORed together). The fourth parameter specifies the setting for the flags (FALSE means off).
The loop above can be replaced with one call to the new function SalTblSetFlagsAnyRows:
Call SalTblSetFlagsAnyRows( twCompanyInfo, ROW_New | ROW_Edited, FALSE, ROW_New, 0 )
Updating rows
For this application, the user can change values in one or more table window rows. However, the changes are not made in the database until the user selects the Apply Changes menu item. The steps below (in the Menu Actions section for the Apply Changes menu item) UPDATE one or more rows in the database that the user changed.
Programming techniques
1.
The user might not have moved the cursor off an updated row. Call SalTblKillEdit to force the setting of the ROW_Edited flag, the result of which is the validation of the value that the user entered:
Call SalTblKillEdit( twCompanyInfo )
2.
Call SalTblAnyRows to find if any row has the ROW_Edited flag set to TRUE:
If SalTblAnyRows( tblCompanyInfo, ROW_Edited, 0 )
The second parameter says to find rows that have the ROW_Edited flag set to TRUE. The third parameter says to find rows that have these flags off. This is not appropriate in this example, so zero is specified. 3. Call SqlPrepare and specify an UPDATE statement:
Call SqlPrepare( hSqlA, 'UPDATE COMPANY ' || 'SET NAME = :twCompanyInfo.csName, ' || ... 'FAX = :twCompanyInfo.csFAX) ' , || 'WHERE ID = :twCompanyInfo.cnID' )
4.
Call SalTblDoUpdates:
Call SalTblDoUpdates( tblCompanyInfo, hSqlA, FALSE )
SalTblDoUpdates finds all rows with the ROW_Edited flag set to TRUE and UPDATEs them. The second parameter is the Sql Handle that must be associated with an UPDATE statement. The third parameter says not to clear the ROW_Edited flag of each row after it has been updated in the database. 5. 6. COMMIT or ROLLBACK the UPDATE. Set the table window row number to TBL_MinRow:
Set nRow = TBL_MinRow
7.
Set nRow = TBL_MinRow Loop If NOT SalTblFindNextRow( tblCompanyInfo, nRow, ROW_Edited, 0 ) Break Call SalTblSetRowFlags( tblCompanyInfo, nRow, ROW_Edited, FALSE )
Call SalTblFindNextRow to find the next row with the ROW_Edited flag set to TRUE. The second parameter is the table window row number which indicates where the search is to start (this was set to TBL_MinRow in the previous step). When it finds a row that matches the flag, SalTblFindNextRow returns the row number in this parameter. The third parameter specifies flags that the row has. The fourth parameter specifies flags that the row does not have; this is not appropriate for this application, so
Developing with SQLWindows
15-17
Chapter 15
Table Windows
zero is specified. The loop repeats until there are no more rows with the ROW_Edited flag set to TRUE. Call SalTblSetRowFlags to clear the ROW_Edited flag for the processed row. The third parameter is the flag to set to FALSE (ROW_Edited). The fourth parameter specifies the setting for the flag (FALSE means off).
The INTO clause names the table window columns that receive the data. Each column name in the INTO clause is qualified with the table window handle:
:twCompanyInfo.cnID
2.
3.
4.
Programming techniques
If the source of data is not a database, you must determine the row count for the table window. For example, if the data comes from an array, you can use SalQueryArrayBounds to determine the number of elements. 5. Set the table range with SalTblSetRange. The table range is the number of rows in the table window.
Call SalTblSetRange( twCompanyInfo, 0, nRowCount -1 )
The first parameter is a table window handle. The second parameter is the lower bound of the table range and the third parameter is the higher bound of the table range. SalTblSetRange causes SQLWindows to send SAM_FetchRow messages to the table window. 6. Process SAM_FetchRow messages.
Table Window: twCompanyInfo ... Message Actions ... On SAM_FetchRow If Not SqlFetchRow( hSqlA, lParam, nFetchResult ) Return FALSE Else Return TRUE
SQLWindows sends a SAM_FetchRow to a table window when the table window needs the contents of a row that is not already in memory (cache). For example, when the application first displays a table window, SQLWindows sends one SAM_FetchRow message for each row that is visible on screen. As the user scrolls, SQLWindows sends additional SAM_FetchRow messages, one for each row that the user scrolls to. To process a SAM_FetchRow message, get the data from its source and assign values to the table window columns. Return a value to indicate the status of the SAM_FetchRow processing. This application calls SqlFetchRow to retrieve a row of data. The INTO clause in the SELECT statement (from step 1) mapped the database table columns to the table window columns. The second argument to SqlFetchRow is the current row number (context) in the table window. The lParam for a SAM_FetchRow message is the number of the row currently being processed.
15-19
Chapter 15
Table Windows
Deleting a row
In the delete operation described below, the user selects a row in the table window and then chooses the Delete menu item. The steps below are performed in the Menu Actions section. 1. Delete the source data (in an array, variables, or flat file). For a SQL database, call SqlPrepare and specify a DELETE statement:
Call SqlPrepare( hSqlB, 'DELETE FROM COMPANY' || 'WHERE ID = :twCompanyInfo.cnID' )
The column name in the WHERE clause is qualified with the table window handle (:twCompanyInfo.cnID). This tells SQLWindows to use the value for cnID in the row that has the context. You set the context row with SalTblSetContext. After calling SqlPrepare, call SqlExecute for the Sql Handle. 2. Remove the row from the table window with SalTblDeleteRow. If the data comes from a database, the call looks like this:
Call SalTblDeleteRow( twCompanyInfo, SalTblQueryContext( twCompanyInfo ),TBL_Adjust )
The first parameter is the handle of the table window. The second parameter is the row to delete. This example calls SalTblQueryContext to get the row that has the context. The third parameter is a flag that specifies to maintain correspondence between the table window row and the row in the database result set.
Important: SalTblDeleteRow deletes the row from the table window only. You must prepare and execute a DELETE statement to delete the row from the database (read step 1).
If the data does not come from a database, the call looks like this:
Call SalTblDeleteRow( twCompanyInfo, SalTblQueryContext( twCompanyInfo ), TBL_NoAdjust )
If the source of data is not from a database, there is no need to maintain correspondence with a result set, so specify TBL_NoAdjust for the third parameter. 3. For a SQL database, COMMIT or ROLLBACK after deleting the row from the table window.
Programming techniques
Inserting rows
There are two parts to inserting rows: The user chooses an Insert menu item that creates a new, empty row in the table window. After the user has created and entered data in one or more new rows, the user chooses the Apply Changes menu item to INSERT the new rows into the database.
For the first part, the steps below are performed in the Menu Actions section. 1. Create a new row in the table window by calling SalTblInsertRow:
Set nIndex = SalTblInsertRow( twCompanyInfo, TBL_MaxRow )
SalTblInsertRow adds a blank row at the location that you specify. The second parameter is a flag (TBL_MaxRow) that says to add the new row at the end of the table window. The row number (nIndex) that SalTblInsertRow returns is used in the next two function calls. 2. Set the focus to the new row and position the text insertion bar to a cell in the row by calling SalTblSetFocusCell:
Call SalTblSetFocusCell( twCompanyInfo, nIndex, csName, 0, -1 )
The second parameter is the row number returned by SalTblInsertRow. The third parameter specifies where to set the column focus in the row. The fourth and fifth parameters select specific characters within the focus cell. This is not needed for this example, so 0, -1 is used for these parameters (this selects the entire cell). The user can now enter data in the cells of the new table window row. For the second part, the steps below in the Menu Actions section for the Apply Changes menu item INSERT into the database one or more new rows that the user entered: 1. The user might not have moved the cursor off a newly-inserted row. Call SalTblKillEdit to force the setting of the ROW_Edited flag, the result of which is the validation of the value that the user entered:
Call SalTblKillEdit( twCompanyInfo )
15-21
Chapter 15
Table Windows
2.
Call SqlPrepare( hSqlB,'INSERT INTO COMPANY( ID, ..., FAX )' || 'VALUES(:twCompanyInfo.cnID, ' || ... ':twCompanyInfo.csFAX) ' , || 'ADJUSTING C ' )
The column names in the VALUES clause are qualified with the table window handle (:twCompanyInfo.*). This tells SQLWindows to use the value for the columns in the row that has the context. 3. Set the table window row number to TBL_MinRow:
Set nIndex = TBL_MinRow
4.
Call SalTblFindNextRow to find the next row with the ROW_New flag set to TRUE. The second parameter is the table window row number where to start the search (this was set to TBL_MinRow in the previous step). When it finds a row that matches the ROW_New flag, SalTblFindNextRow returns the row number in this parameter. The third parameter specifies flags that the row has. The fourth parameter specifies flags that the row does not have; this is not appropriate for this application, so zero is specified. The loop repeats until there are no more rows with the ROW_New flag set to TRUE. Call SalTblSetContext to set the context on the row. SalTblFindNextRow returns the row number in nIndex that matches the ROW_New flag. Using the data from the table window cells, process the insert in the data source (such as an array, variables, or a flat file). For SQL database, call SqlExecute. Call SalTblSetRowFlags to clear the ROW_New and ROW_Edited flags for the processed rows. The third parameter are the flags to set to FALSE (ROW_New and ROW_Edited ORed together). The fourth parameter specifies the setting for the flags (FALSE means off).
5.
Programming techniques
Updating rows
For this application, the user can change values in one or more table window rows. However, the changes are not made in the data source until the user selects the Apply Changes menu item. The steps below in the Menu Actions section UPDATE one or more rows in the database that the user changed: 1. The user might not have moved the cursor off an updated row. Call SalTblKillEdit to (indirectly) force the validation of the value entered by the user:
Call SalTblKillEdit( twCompanyInfo )
2.
The column names in the SET clause are qualified with the table window handle (:twCompanyInfo.*). This tells SQLWindows to use the value for the columns in the row that has the context. 3. Set the table window row number to TBL_MinRow:
Set nIndex = TBL_MinRow
4.
Loop If SalTblFindNextRow( twCompanyInfo, nIndex, ROW_Edited, 0 ) Call SalTblSetContext( twCompanyInfo, TBL_TempRow ) Call SqlFetchRow( hSqlA, nIndex, nFetchResult ) Call SalTblSetContext( twCompanyInfo, nIndex ) Call SqlExecute( hSqlB ) Call SalTblSetRowFlags( twCompanyInfo, nIndex, ROW_Edited, FALSE ) Else Break
Call SalTblFindNextRow to find the next row with the ROW_Edited flag set to TRUE. The second parameter is the table window row number where to start the search (this was set to TBL_MinRow in the previous step). When it finds a row with the ROW_Edited flag set to TRUE, SalTblFindNextRow returns the row number in this parameter. The third parameter specifies the flag (ROW_Edited) that the row has. The fourth parameter specifies flags that the row does not have; this is not appropriate for this application, so zero is specified. The loop repeats until there are no more rows with the ROW_Edited flag set TRUE.
15-23
Chapter 15
Table Windows
Call SalTblSetContext to set the context to TBL_TempRow. Call SqlFetchRow. SQLWindows fetches the row pointed to by the second parameter from the database. However, instead of fetching the column values into the row indicated by the second parameter, the values are fetched into TBL_TempRow. This step synchronizes the table window row with the corresponding result set row. Call SalTblSetContext to set the context back to the table window row. Using the data from the table window cells, process the update in the data source (such as an array, variables, or a flat file). For a SQL database, call SqlExecute. Call SalTblSetRowFlags to clear the ROW_Edited flag for the processed rows. The third parameter is the flag to set to FALSE (ROW_Edited in this case). The fourth parameter specifies the setting for the flag (FALSE means off).
5.
For a SQL database, COMMIT or ROLLBACK after updating the row in the database.
Context row
The context row is the row whose individual column values are referenced when used as variables. When a user edits a table, the context row is the row being edited. The context row is usually the same as the row that has the focus, but it can be different. Internally, SQLWindows numbers each row beginning from zero. The context row identifies the row number that is addressed when you refer to a table window column. The context row is the row used when you refer to a column name in: SQL statements Function calls Set statements Comparisons
:twCompanyInfo is the table window handle and colName is a column in the table window. A name such as this refers to a cell in the current context row. SQLWindows sets the context row (in lParam) when it sends a SAM_FetchRow message to a table window. Changing the context row does not affect the focus row.
You can set the context row with SalTblSetContext. This function does not fetch a row automatically if it is not already in the table window cache. If the context row is set to a row not already in cache, a blank row appears in the table window. To avoid this, use SalTblFetchRow to set the context. Rows are normally numbered 0 to 2,147,423,631. However, for a split-window (described later in this chapter): Rows in the top-half of the table window are numbered 0 to 2,147,423,631. Rows in the lower-half of the table window are numbered -2,147, 423,630 to -1.
Note: For more information, read Table window cache on page 15-35.
You can populate a table windows in two ways: SalTblPopulate (simple technique), which populates a table window with a result of a database query SalTblSetRange (advanced technique), which populates a table window with data from any source
For the advanced technique, the data for a table window can come from one or more of the following sources: Database tables Flat files Arrays Variables Constants
15-25
Chapter 15
Table Windows
In order, the parameters are: Table window handle. Sql Handle. SELECT statement. If you have already prepared the SELECT statement, specify an empty string (' '). If you have not prepared the SELECT statement, specify it in this parameter. A constant that specifies how to populate the table:
Description Populates the entire table window. Populates only the visible portion of the table window. Additional rows are populated as the user scrolls them into view. Populates the visible portion of the table window and returns control to the application. Additional rows are populated at a rate of 4 per second. Once all rows have been populated, the table window receives a SAM_FetchDone message.
The example below prepares the SQL statement before calling SalTblPopulate:
Table Window: tblExample Message Actions ... On SAM_Create Set strSql = 'select name, trainer, room from guest_roster' || ' into :tblExample.colname, ' || ':tblExample.colTrainer, :tblExample.colRoom' Call SqlPrepare( hSql, strSql ) Pushbutton: pbPopulate ... Message Actions On SAM_Click Call SalTblPopulate( tblExample, hSql, ' ', TBL_FillNormal )
Here are examples of how you can use SalTblPopulate: To fill a table window with the results of a SELECT one time. You provide a SELECT statement and SalTblPopulate compiles, executes, fetches, and fills the table window. If you do not specify an INTO clause, SalTblPopulate creates columns automatically. To fill a table window many times using the same SELECT statement, but with different WHERE criteria. This is useful for a detail table window in a master-detail application or for query-by-example (QBE). You do not supply a SELECT statement for SalTblPopulate, but you do supply a Sql Handle that has a prepared SELECT already (call SqlPrepare or SqlRetrieve first). SalTblPopulate binds (for the new criteria), executes, fetches, and fills the table window. This avoids recompiling the SELECT.
These are the steps that SalTblPopulate follows if you specify a non-null string in the strSelect parameter: SqlPrepare Bind (gets the current values of bind variables) SqlExecute Fills table window (how it does this depends on the constant you specify in the third parameter)
These are the steps that SalTblPopulate follows if you specify a null string in the strSelect parameter: Bind (gets the current values of bind variables) SqlExecute Fills table window
Is it not efficient to call SqlPrepareAndExecute and then call SalTblPopulate with a null strSelect parameter. Instead use SqlPrepare (or SqlRetrieve) because SalTblPopulate performs the bind and execute before fetching. You can find the number of rows that the SELECT returned by calling SqlGetResultSetCount.
15-27
Chapter 15
Table Windows
You can process these messages when using SalTblPopulate: SQLWindows sends SAM_FetchRow is sent to the table window before fetching a row SQLWindows sends the SAM_FetchRowDone message after fetching a row, so you can perform additional processing on the fetched values SQLWindows sends SAM_FetchDone after all rows have been populated by SalTblPopulate with the TBL_FillAllBackground option
In order, the parameters are: Table window handle The lower bound of the table range The higher bound of the table range
To create an empty table window, set the second and third parameters to 0 and -1:
SalTblSetRange( hWndTbl, 0, -1 )
To set a dynamic table range, set the second and third parameters to 0 and TBL_MaxRow:
SalTblSetRange( hWndTbl, 0, TBL_MaxRow )
A dynamic table range has some important features that are discussed in a separate section. When you call SalTblSetRange, SQLWindows sends one SAM_FetchRow message for each visible row in the table window. The application does two things to process SAM_FetchRow messages: Gets the data from the source Assigns the data values to the table window columns
When the user scrolls in a table window and a row needs to be displayed that is not currently in the cache, SQLWindows sends a SAM_FetchRow message to the table window for each row.
SAM_FetchRow message
SQLWindows sends this message to a table window for each row in the table range that needs to be fetched (from the data source) if the row is not already in the cache. SQLWindows sends a SAM_FetchRow to a table window when a row must be copied into the table window cache: When the application first displays a table window, SQLWindows sends a SAM_FetchRow message for each row that is visible on screen As the user scrolls, SQLWindows sends a SAM_FetchRow message for each row
SQLWindows assigns lParam to be the row number for a SAM_FetchRow message. If the source of data is a SQL database, you process a SAM_FetchRow message by calling SqlFetchRow to retrieve the row into the table window based on the row number in lParam. SqlFetchRow returns TRUE or FALSE, and updates a fetch indicator variable that specifies the status of the fetch. SQLWindows stops sending SAM_FetchRow messages when you return FALSE. The fetch indicator variable can be one of these values:
Constant TBL_NoMoreRows TBL_RowDeleted TBL_RowFetched Description Row could not be fetched and there are no more rows Row was not fetched because it has been deleted Row was successfully fetched
For example:
Table Window: twTabWinEmployee ... Message Actions On SAM_FetchRow ! The table window needs a row to be fetched from the ! database If SqlFetchRow( hSql, lParam, nFetch ) If nFetch = FETCH_Delete Return TBL_RowDeleted Else Return TBL_RowFetched Else Return TBL_NoMoreRows
15-29
Chapter 15
Table Windows
If the source of data is not a SQL database, process a SAM_FetchRow message by retrieving the data from its source and assigning it to columns in the current row.
Important: Setting a breakpoint on a statement that executes while processing a SAM_FetchRow message can cause incomplete painting of the table window.
The example above set the table range to the number of elements in the array. This means that SQLWindows sends exactly the number of SAM_FetchRow messages as there are elements in the array. For applications that cannot set the table range to the exact size of the data source, return TBL_NoMoreRows during SAM_FetchRow processing to signal that there is no more data to fetch.
SalTblPopulate
There are two ways to use SalTblPopulate with dynamic table windows: You can call SalTblPopulate for a table window that does not have columns. SQLWindows creates the columns at runtime based on the columns in the query. This feature only works if the table window does not have columns. You can call SalTblPopulate and specify a SELECT statement that does not have an INTO clause. The table window must have the correct number of columns and the data types of the columns must match those in the query. SQLWindows automatically assigns the query columns to the table window columns.
SalTblPopulate destroys automatic columns before populating a table window. This means that SalTblPopulate can populate a table window with different queries which were not assigned columns at designtime.
SalTblCreateColumn
This function creates a table window column automatically at runtime:
bColID = SalTblCreateColumn( hWndTbl, nColumnPos, nDispWidth, nMaxChars, strTitle )
The columns that this function creates are not available at designtime.
15-31
Chapter 15
Table Windows
Note: SQLWindows assumes that the data type of a column you create with SalTblCreateColumn is String.
If you set Discardable attribute to Yes, SQLWindows discards rows when you call SalTblCreateColumn. If you set Discardable to No, SQLWindows expands rows when you call SalTblCreateColumn.
SalTblDestroyColumns
This function destroys columns that SalTblCreateColumn or SalTblPopulate created:
SalTblDestroyColumns( hWndTbl )
This function only destroys automatic columns created by SalTblCreateColumn. This function returns FALSE if the table window does not contain automatic columns.
The first column of tblMain The third column of tbl1, a child table of frm1
Messages
SQLWindows sends SAM_Validate to a table window itself when the user edits an automatic column created by SalTblPopulate. This is needed because automatic table columns do not exist in the outline. You can use hWndItem to get the handle of the automatic column. SQLWindows sends SAM_FetchRowDone to a table window when one row has been populated. The lParam for this message is the row number that was populated. SQLWindows ignores any value you return when you process this message.
The nFlagsOn and nFlagsOff parameters are row flags that specify rows to include in the sum (such as all modified rows). This function computes the average value of a table window column:
Table range
The nFlagsOn and nFlagsOff parameters are row flags that specify rows to include in the average (such as all modified rows). This function sorts a table window:
bRet = SalTblSortRows( hWndTbl, nColumnID, nOrder )
The nColumnID parameter identifies the sort key column. The sort key column cannot be an automatic column. The nOrder parameter specifies the direction of the sort: TBL_SortIncreasing (default) or TBL_SortDecreasing.
Note: The table window cache must not be discardable and the setting of maximum rows in memory must be large enough to hold the rows that you are sorting. For more information, read Table window cache on page 15-35.
Table range
The table range defines the number of rows in the table window. A table window can have a static range or a dynamic range.
With a static table range, SQLWindows knows the row number when the user moves the slider box to the bottom of the vertical scroll bar.
15-33
Chapter 15
Table Windows
Make the table range dynamic by calling SalTblSetRange and specifying TBL_MaxRow for the third parameter:
SalTblSetRange ( hWndTbl, 0, TBL_MaxRow ) ... On SAM_FetchRow If DoFetch( hWndTbl ) Return TBL_RowFetched Else Return TBL_NoMoreRows
The actual number of rows in the table window is determined when TBL_NoMoreRows is returned to the application. With a dynamic table range, SQLWindows does not know the row number when the user moves the slider box to the bottom of the vertical scroll bar. As a result, when the user attempts to move the slider to the bottom, SQLWindows sends a SAM_CountRows message to the table window. You can use a dynamic table range for a split table window where the user displays existing rows in the top half of the table window and inserts new rows in the lower half of the table window. Scroll bar operation is not as smooth as it is with a static scroll range.
SAM_CountRows message
SQLWindows sends this message to a table window when both of the following are true: The table window has a dynamic scroll range The user moves the scroll box to the bottom of the vertical scroll bar
Process a SAM_CountRows message by returning the number of rows in the table. For example: Count the number of rows in a result set (SqlGetResultSetCount) Count the number of records in a flat file Determine the number of elements in an array
The application is not required to process this message. If the application does not process this message, SQLWindows sends SAM_FetchRow messages until the application returns TBL_NoMoreRows. However, the application performs better if it processes SAM_CountRows. SAM_CountRows does not use lParam. The example below calls SalTblSetRange and specifies TBL_MaxRow in the third parameter (dynamic table range). When the user moves the slider box to the bottom 15-34 Developing with SQLWindows
of the vertical scroll bar, SQLWindows sends a SAM_CountRows message to the table window. The application calls SqlGetResultSetCount and returns the number of rows.
Table Window: tblEmployee ... Message Actions On SAM_Create Call SqlPrepare( hSqlPrimary, strSqlTableWindow ) Call SqlExecute( hSqlPrimary ) Call SalTblReset( hWndForm ) Call SalTblSetRange( hWndForm, 0, TBL_MaxRow ) On SAM_CountRows ! Count the number of rows in the result set. Call SqlGetResultSetCount( hSqlPrimary, nRowCount ) Return nRowCount
Although the theoretical maximum capacity of a table window is 2,147,423,632 rows, the limiting factors are: The size for the cache you set for the Max Rows in Memory item in the Attribute Inspector. The number that you specify is the maximum number of rows that can be in the cache at any one time. The default value is 100 rows. System memory. The amount of memory required to store one row.
15-35
Chapter 15
Table Windows
The cache and other limiting factors determine how many rows can be in a table window at any one time. However, if the table window cache is discardable, the table window can theoretically address 2,147,423,632 rows in the top half and 2,147,423,632 rows in the bottom half. Rows are normally numbered 0 to 2,147,423,631. However, for a split-window (described later in this chapter): Rows in the top-half of the table window are numbered 0 to 2,147,423,631. Rows in the lower-half of the table window are numbered -2,147,423,630 to -1.
An exception to these rules is made for a dynamic table range. SalTblSetContext, SalTblFindNextRow, SalTblFindPrevRow, and SalTblSetRowFlags cause SQLWindows to send a SAM_FetchRow message if the row has not already been fetched.
SalTblReset sets cache to zero rows which results in all rows being discarded. If you try to fetch a row already in the cache, but the user has changed the row without applying an UPDATE, SQLWindows sends SAM_CacheFull if: The Discardable item is set to yes
SAM_CacheFull message
SQLWindows sends this message to a table window when a row is to be fetched, but the table window cache is full and SQLWindows cannot discard any rows. SQLWindows sends a SAM_CacheFull message to the table window when scrolling if: The Maximum Rows in Memory value has been reached. The Discardable item is set to No.
The minimum value for rows in memory is 78, regardless of the maximum number of rows in the memory item setting. The theoretical maximum value for rows in memory is 2,147,423,632. However, see the Table Window Cache section on page 14-33 for more details. The lParam for SAM_CacheFull is the row number the table window tried to fetch.
15-37
Chapter 15
Table Windows
Constant TBL_Flag_ShowVScroll
Default FALSE
Description Displays the vertical scroll bar all the time. Otherwise, it is only displayed when there are more rows than displayed in the table window. When TRUE, SQLWindows displays a wait cursor while responding to a user action that scrolls the table window (such as when the user presses the PgUp, PgDn, Home, or End key, or when the user clicks the vertical scroll bar). Functions such as SalTblScroll do not display a wait cursor automatically. You must call SalWaitCursor before and after calling Sal* functions.
TBL_Flag_ShowWaitCursor
TRUE
When TRUE, users can only select one row at a time in the table window. Users can drag-size columns at runtime. When TRUE, SQLWindows does not display the last vertical column separation line. When TRUE, SQLWindows does not display the dotted lines between rows.
Row flags
Each row has flags that define the properties of the row. The ROW_* constants represent row flags:
Constant ROW_Edited ROW_Hidden ROW_HideMarks ROW_MarkDeleted ROW_New ROW_Selected ROW_UnusedFlag1 ROW_UnusedFlag2 Row has been edited. Row is hidden. Do not use the symbols in the default row header. For more information, read Row header on page 15-47. Row is marked for deletion. Row is newly-inserted. Row is selected. Application defined. Application defined. Description
Column flags
Row flags are not stored with data in the table window cache, so even if a row is swapped out, row flags are lost. A row can have more than one flag set to TRUE. For example, after the user edits a newly-inserted row, it has both the ROW_New and the ROW_Edited flags set to TRUE. The loop in the example below uses SalTblFindNextRow to search for rows with the ROW_New flag set to TRUE. Once SQLWindows finds a row with ROW_New set to TRUE, SalTblSetRowFlags clears (sets to FALSE) the ROW_New and the ROW_Edited flags:
Loop Set nRow = TBL_MinRow If NOT SalTblFindNextRow( tblCompanyInfo, nRow, ROW_New, 0 ) Break Call SalTblSetRowFlags( tblCompanyInfo, nRow, ROW_New | ROW_Edited, FALSE )
The code in the loop above can be done in one call to SalTblSetFlagsAnyRows:
Call SalTblSetFlagsAnyRows(tblCompanyInfo, ROW_New | ROW_Edited, FALSE, ROW_New, 0 )
This example determines if there are any rows that the user has inserted or changed:
If SalTblAnyRows( tblCompanyInfo, ROW_New | ROW_Edited, 0 ) ! Do something
You can define your own use for the flags ROW_UnusedFlag1 and ROW_UnusedFlag2. To assign a meaningful name to these flags, define a constant as follows:
Constants User Number: ROW_MyFlag = ROW_UnusedFlag1
Column flags
Use these constants to specify column properties for SalTblSetColumnFlags and SalTblQueryColumnFlags:
Constant COL_Editable COL_RightJustify COL_CenterJustify Users can edit text. Right-justify or center text. Only set one of these flags to TRUE at the same time. If neither flag is set to TRUE, the column if left-justified. Description
15-39
Chapter 15
Table Windows
Description
Fill the column cell with '#' when the text does not fit (except when the cell has the focus).
TBL_Error constant
SQLWindows returns TBL_Error when a table window function is unsuccessful.
TBL_* constants
These constants are the starting and ending row numbers in a table window:
Constant TBL_MaxRow TBL_MinRow TBL_MinSplitRow Highest row number Lowest row number Low row number in bottom half of a split table window Description
Use TBL_MinRow and TBL_MaxRow with SalTblFindNextRow and SalTblFindPrevRow to search for rows from the beginning or end of the table window respectively. You can use TBL_MinRow to append a row to the bottom half of a split window:
Set nIndex = SalTblInsertRow( tblCompanyInfo, TBL_MinRow )
and use TBL_MaxRow to append a row to the top half of a split table window:
Set nIndex = SalTblInsertRow( tblCompanyInfo, TBL_MaxRow )
You can also use TBL_MinRow with SalTblSetFocusRow to set the focus to the first row in the split window, and use TBL_MaxRow with SalTblSetRange. For more information, read Split windows on page 15-49.
SAM_CaptionDoubleClick
SQLWindows sends this message to a table window and a table column when the user double-clicks a column title. For this message, wParam is the column window handle. You can use SalNumberToWindowHandle to get the window handle from wParam.
SAM_ColumnSelectClick
SQLWindows sends this message to a table window and column window when the user selects or deselects a column by clicking the column title. TBL_Flag_Selectable must be TRUE (default). For this message, wParam is the column window handle.
SAM_EndCellTab
SQLWindows sends this message to a table window when the user tries to tab past the last editable cell in the table window. The application must return TRUE if it processes this message. This example shows how to use SAM_EndCellTab to insert a row when the user tabs past the last row in the table.
Table Window: tbl1 ... Message Actions On SAM_EndCellTab Call SalTblInsertRow( hWndForm, TBL_MaxRow ) Return TRUE
The user must be positioned in the last editable cell of the last row.
Developing with SQLWindows
15-41
Chapter 15
Table Windows
SAM_RowValidate
SQLWindows sends this message when the user tries to move the focus off a row:
Table Window: tbl1 ... Message Actions On SAM_RowValidate If SalIsNull( col1 ) Call SalMessageBox( 'You must enter a value', 'Validation Error', MB_Ok ) Return VALIDATE_Cancel Else Return VALIDATE_Ok
SAM_AnyEdit
SQLWindows sends this message to a table window and column when the user edits a cell.
SAM_Click
SQLWindows sends this message to the table window and the non-editable column when the user clicks in a non-editable column.
SAM_DoubleClick
SQLWindows sends this message to a table window and the non-editable column when the user double-clicks a non-editable column. If the user double-clicks a non-editable column, SQLWindows sends the table window and the non-editable column: SAM_Click SAM_DoubleClick
When the focus changes, SQLWindows sends SAM_KillFocus to the column losing the focus and SAM_SetFocus to the column getting the focus.
SAM_FieldEdit
SQLWindows sends this message to a table window and column when the user edits a column and moves the focus away from the cell.
SAM_Validate
SQLWindows sends this message to a table window column when the user changes the value of the item and then moves the focus away from that item, or when the user changes the value of the item and then calls SalSendValidateMsg or SalTblKillEdit.
SAM_Close
SQLWindows sends a top-level table window this message when the user chooses the Close Menu item from the system menu of the table window. SQLWindows does not send a SAM_Close message to a child table window since a child table window does not have a system menu and cannot be closed.
Call SalTblKillFocus to turn off the focus frame. Changing the focus row also changes the context row (the context follows the focus).
15-43
Chapter 15
Table Windows
Focus cell
Use SalTblKillEdit to end editing and force SQLWindows to validate (check the data against the column data type). After calling SalTblKillEdit, the table window is in row mode. You can also call SalSendValidateMsg to force SQLWindows to validate the data. After calling SalSendValidateMsg, the table window is in cell mode.
Scroll position
The scroll position is the top-most visible row in the table window. To find the current scroll position, call SalTblQueryScroll. You can change the scroll position by calling SalTblScroll. These constants specify table scrolling for SalTblScroll:
Constant TBL_AutoScroll TBL_ScrollBottom TBL_ScrollTop Description Scroll as needed so that the row is visible Scroll the row to the bottom of the table window Scroll the row to the top of the table window
The font you set with the Attribute Inspector or with SalFontSet applies to the entire table window. You cannot set the font for an individual column. Call SalFontGet to find the current font of the table window.
Column title
To find the current column title, call SalTblGetColumnTitle. To set a new column title, call SalTblSetColumnTitle.
Column width
Call SalTblQueryColumnWidth to get the current column width. Set a new column width by calling SalTblSetColumnWidth.
15-45
Chapter 15
Table Windows
position two, and so on. If you or a user changes the order of the columns, their positions change to reflect the visual order. Column identifier. A column identifier is the position of a column in the outline or its order of creation. A column identifier is a permanent, non-changing number associated with a column. The first column created is column one, the next column two, and so on. A column identifier does not change if you or a user changes the order of the columns. You pass a column position to these functions: SalTblCreateColumn SalTblGetColumnWindow
You pass a column identifier to these functions: SalTblColumnAverage SalTblColumnSum SalTblGetColumnText SalTblGetColumnWindow SalTblSetColumnPos SalTblSetColumnText SalTblSortRows
You can also use column identifiers in references (see below). To get the window handle of a column, call SalTblGetColumnWindow and specify either the column identifier or the column position.
Locking columns
Use the # character as a separator between the table window name and the column number. For example:
tblMain#1 frm1.tbl1#3
The first column of tblMain The third column of tbl1, a child table of frm1
Locking columns
You can lock columns on the left-side of a table window. Locked columns do not scroll horizontally. Columns to the right of locked columns appear to scroll under the locked columns. You lock columns with SalTblSetLockedColumns:
Call SalTblSetLockedColumns( hWndTbl, 2 )
The example above locks the left-most two columns in the table window. Before calling SalTblSetLockedColumns, you can call SalTblSetColumnPos to move columns to the left side of the table window. Call SalTblQueryLockedColumns to find out how many columns are locked. The user can edit the data in the cells of an editable locked column. The user cannot: Move a locked column Move an unlocked column on top of a locked column
Row header
The row header is a non-editable column fixed on the left side of the table window. A row header can display a row number or other value (key) that identifies the data in the row. You can set row header properties with SalTblDefineRowHeader:
Call SalTblDefineRowHeader(hWndTbl, strTitle, nWidth, TBL_RowHdr_Visible | TBL_RowHdr_ShareColor, colRowHeader )
15-47
Chapter 15
Table Windows
In order, the parameters are: Table window handle Title of the row header Width of the row header Properties for the row header (TBL_RowHdr_*) Window handle of a table window column that is mirrored in the row header
SAM_RowHeaderClick
SQLWindows sends this message to a table window when the user clicks a row header. For this message, lParam is the context row.
SAM_RowHeaderDoubleClick
SQLWindows sends this message to a table window when the user double-clicks a row header. For this message, lParam is the context row.
SAM_CornerClick
SQLWindows sends this message to a table window when the user clicks the title of a row header. The row header title is in the upper-left hand corner of the table window.
SAM_CornerDoubleClick
SQLWindows sends this message to a table window when the user double-clicks the title of a row header. The row header title is in the upper-left hand corner of the table window.
Split windows
Constant TBL_RowHdr_ShareColor
Description Sets the row header color to the text color of the cells. If TBL_RowHdr_ShareColor is FALSE, the row header uses the table window's default text color. Displays a graphic depending on the setting of the row flags: 4 7 Row is modified (ROW_Edited). Row is marked for deletion (ROW_MarkDeleted). Row is new (ROW_New). This is the default row header.
TBL_RowHdr_MarkEdits
Split windows
A table window can be split horizontally. The lower-half of a split table window can be used to insert new rows or to display dynamic summary data. You split a table window horizontally using SalTblDefineSplitWindow:
Call SalTblDefineSplitWindow( hWndTbl, 3, TBL_Split_Adjustable )
In order, the parameters are: Table window handle. Number of rows in the lower-half of the table window. The TBL_Split_Adjustable constant is the row header flag passed as the last parameter of SalTblDefineSplitWindow. If set to TRUE, this enables the user to drag-adjust the number of visible rows in the upper and lower halves of the split window.
If you specify TBL_Split_Adjustable, when the user moves the mouse pointer to the black bar (splitter bar) between the upper and lower part of the table window, the mouse pointer changes to the splitter on the left. A user can drag up or down to change the size of a split window. Call SalTblQuerySplitWindow to determine the number of rows in the lower-half of a split table window.
15-49
Chapter 15
Table Windows
SalEditCopy
Function SalTblCopyRows
Description Copies one or more selected table window rows to the clipboard. Tabs are placed between columns and an end-of-line character is placed at the end of each row.
Use TBL_Adjust when you delete data from both the result set and the table window:
Call SalTblDeleteRow( hWndForm, nRow, TBL_Adjust )
TBL_TempRow constant
You can fetch a row from the database into TBL_TempRow without overwriting values in the actual table window row. Fetching a database row usually places the values in the corresponding table window row. However, when you update, avoid overwriting edited values. TBL_TempRow lets you fetch the database row into a special table window row, establish the current SQL cursor position and enable the update to take place. For more information, read Updating rows on page 15-23.
The specific cell that SQLWindows checks or set is at the intersection of the context row and the column you specify.
15-51
You can process these messages in the message actions of a table window column. For example, to let a user scroll through a list of values for a cell by pressing the Up and Down arrow keys, process WM_KEYDOWN and check the wParam for the virtual key codes VK_UP and VK_DOWN.
Chapter 16
Pictures
This chapter shows how to create and use picture objects in SQLWindows applications. This chapter explains: Picture properties Messages and functions you can use with pictures
16-1
Chapter 16
Pictures
About pictures
A picture displays a graphic image. A picture is a child of a form window or dialog box. A picture object can contain: Graphic images DOS files
Examples of pictures are: An organization's logo Graphics that indicate instructions Images that give an application visual appeal, such as an image that fills the background of a form Images that a user can cut, copy, and paste Images retrieved from a database or a file
Picture attributes
The table below describes the attributes for a picture.
Property Object Name Visible Description The name you use to refer to the picture window in statements. If Yes (default), the picture is visible at runtime. If No, the picture is not visible at runtime. At runtime, you can change the setting of this property with SalHideWindow and SalShowWindow. Location and Size Editable Displays a cascading menu with the form window's position (top and left) and size (width and height). If No (default), a user cannot edit the object. You can still change the contents of the picture within the application (such as with a Set statement). If Yes: A user can cut, copy, and paste the picture. A user can shift the input focus to the picture. The focus is indicated by the focus frame. At runtime, you can change the setting of this property with SalEnableWindow and SalDisableWindow. File name Displays a dialog where you select a file that contains an image to display in the picture. If you set the File Storage item to Internal, SQLWindows copies the image file into the application. If you set the File Storage item to External, SQLWindows finds and displays the image file at runtime and designtime.
External. SQLWindows reads the image from a disk file at both runtime and designtime.
You must distribute the external file with production versions of an application.
Size for Best Fit Sizes the image to fit either the width or height of the picture At runtime, call SalPicSetFit to set the picture fit. Scale Width Scale Height Tile to Parent Corners Border Style Border Thickness Background Color Border Color The scaling percentage. The default is 100. The scaling percentage. The default is 100. If Yes, the picture fills the background of the parent object. The corner shape (square or round) for the picture. The default is square. The border style for the picture (no border, solid, drop-shadow, raised-shadow, or etched). The default is solid. The border thickness. The default is 1. Displays a palette where you can set the color of the background (the area of the picture not covered by an image). Displays a palette where you can set the color of the picture border.
16-3
Chapter 16
Pictures
Picture messages
A picture receives these messages: SAM_Click SAM_Create SAM_Destroy SAM_DoubleClick SAM_KillFocus (only editable pictures receive this message) SAM_SetFocus (only editable pictures receive this message) SAM_Timer
Most of these messages work the same as they do for other application objects. Some special features of the SAM_Click and SAM_DoubleClick messages are explained next.
Picture functions
Picture functions
The SAL functions for pictures are grouped into these categories: Cutting, copying, pasting, and clearing Storing and retrieving images Other functions
SalEditCopyTo
This function displays a dialog so a user can copy the image with the focus to a file:
16-5
Chapter 16
Pictures
bOk = SalEditCopyTo( )
SalEditPasteFrom
This function displays a dialog so a user can select a file to paste into the picture with the focus:
bOk = SalEditPasteFrom( )
A user can retrieve the image file types listed in the table for SalEditCopyTo above. SQLWindows converts the image from one of these formats to display a bitmap. A user can select any type of file. If the file type a user selects is not in the table above, SQLWindows pastes it in the picture using the generic document icon shown on the left. The contents of the file are available to SQLWindows through the SalPicGetString function. For example, you can use SalEditPasteFrom to copy a file into a picture and then use SalPicGetString to copy the file to a string. Then, you can write to a database or file. 16-6 Developing with SQLWindows
SalPicSetFile
This function sets the contents of a picture from a file without user interaction:
bOk = SalPicSetFile( hWndPict, strFileName )
SalPicGetString
This function copies the contents of a specified picture to a string:
nLength = SalPicGetString( hWndPict, nFormat, strDest )
For an example, read Storing pictures in a database on page 16-9. You use a constant in the second parameter to specify the format:
Constant PIC_FormatBitmap PIC_FormatIcon PIC_FormatObject Description The contents of the picture is a bitmap The contents of the picture is an icon The contents of the picture is a graphic image
SalPicSetString
The function copies a string to the picture you specify:
bOk = SalPicSetString( hWndPict, nFormat, strSource )
You use the same constants as for SalPicGetString in the second parameter to specify the format. For an example, read Storing pictures in a database on page 16-9.
Clipboard
File or database
16-7
Chapter 16
Pictures
At runtime, the source of a picture can be: An image that was stored in the application at designtime. The Clipboard using SalEditPaste. A file using SalEditPasteFrom or SalPicSetFile. You can also read a file and use SalPicSetString to move the file's contents to a picture. A LONG VARCHAR column in a database using SalPicSetString to move the column's contents to a picture.
At runtime, you can write the contents of a picture to: The Clipboard using SalEditCopy A file using SalPicGetString to move the contents of a picture to a file A LONG VARCHAR column in a database using SalPicGetString to move the contents of a picture to the column
Inserting pictures
To insert an picture in a database: Call SalPicGetString to move the object from the picture to the bind variable in the INSERT's VALUES clause. In this example, the object in the picture named picObject is moved to the :lsImage bind variable. Prepare, execute, and commit the INSERT command.
Retrieving pictures
To retrieve a picture from a database: Prepare and execute the SELECT command. Call SalPicSetString to move the object from the INTO clause's variable to a picture. In this example, the object in the :lsImage INTO variable is moved to the picture named picObject.
Call SqlPrepare( hSql,'select fit, descr, image, numkey into :cbFit :mlDescr, :lsImage, dfKey from SWOBJECT where ROWID = :strRowIDs[nCurrentRow]') Call SqlExecute(hSql) If SqlFetchNext( hSql, nFetch ) Call SalPicSetString( picObject, PIC_FormatObject, lsImage )
16-9
Chapter 16
Pictures
Updating pictures
To update a picture in a database: Call SalPicGetString to move the object from the picture to the bind variable in the UPDATE's SET clause. In this example, the object in the picture named picObject is moved to the :lsImage bind variable. Prepare, execute, and commit the UPDATE command.
For a graphic image, SalPicGetDescription returns the strings in the table below:
Image type Tag Image File Format Paintbrush Graphics Interchange Format Device-Independent Bitmap Icon file String returned by SalPicGetDescription
SalPicSet
This function inserts a resource (bitmap or icon file that you specified in the Resources section of the outline) into a picture:
bOk = SalPicSet ( hWndPic, tResource, nFormat )
SalPicSetFit
This function sets the fit for a picture:
bOk = SalPicSetFit( hWndPict, nFit, nScaleWidth, nScaleHeight )
SalQueryFieldEdit
This function returns the setting of the field edit flag for a picture:
bSet = SalQueryFieldEdit( hWndPict )
SalSetFieldEdit
This function sets or clears the field edit flag for a picture:
bOk = SalSetFieldEdit( hWndPict, bSet )
SalPicClear
This function clears the contents of a picture:
bOk = SalPicClear( hWndPict )
16-11
Chapter 16
Pictures
16-13
Chapter 17
Drag-and-Drop
This chapter explains the functions and messages that you use to write a drag-anddrop interface in a SQLWindows application.
17-1
Chapter 17
Drag-and-Drop
About drag-and-drop
You can write applications where the user can use the mouse to drag from one window and drop into another. For example, you can add drag-and-drop features to applications so that the user can: Fill a data field by dragging a list box entry to a data field Select a picture by dragging from one picture object to another
You can specify the mouse cursors that a window displays while the user drags. You cannot use drag-and-drop to drag a file from a Explorer window to an application window.
Terms
Drag mode. While in drag mode, SQLWindows suspends the mouse's normal operation until the user releases the mouse button. Also, SQLWindows reports the window where the mouse is positioned to the application while in drag mode. Drag. Moving the mouse while in drag mode. Drop. Releasing the mouse button in a valid window while in drag mode. Source window. The window from which a user drags. Target window. The window where the mouse is while in drag mode. Auto dragging. The default mouse action that starts drag mode.
Any SQLWindows object can be a target window. However, target windows that do not have actions (such as Frames) do not receive SAM_Drag* messages.
Drag-mode events
Drag-mode events
SQLWindows informs an application about drag mode events by sending messages to both the source and target windows.
Auto dragging
SQLWindows starts drag mode automatically when the application returns TRUE from the SAM_DragCanAutoStart message. This is the minimum that the application does to let a user drag from a window. However, you must write additional code to do something when the user drops in a window. Auto dragging begins when the user holds down the left mouse button over a window and does not move the mouse for a short period of time. When this happens, SQLWindows changes the cursor to indicate drag mode. This user interface for auto dragging does not interfere with other mouse operations for the window. For example, the user can still edit Data Fields and can still select from List Boxes as long as the user moves the mouse or releases the mouse button before SQLWindows starts drag mode.
Application-initiated dragging
You can start drag mode at other mouse-down events using the SalDragDropStart function. For example, you can start drag mode on a SAM_Click message for a picture window. This way the user does not have to hold the mouse down for some interval-drag mode starts immediately when the user presses the left button. You can call SalDragDropStart to start drag mode at any time a mouse button (right, middle, or left) is down.
17-3
Chapter 17
Drag-and-Drop
Application-defined cursors
SQLWindows displays default cursors to indicate drag mode to the user. When drag mode starts, SQLWindows displays a special cursor to indicate this to the user. When drop is disabled, SQLWindows displays a different cursor. You can override the default cursors that SQLWindows provides. You can associate up to three types of application-defined cursors with a window. Window Cursor. SQLWindows displays this cursor when a window is not in drag mode. Drag Cursor. SQLWindows displays this cursor when a window is in drag mode and dropping is enabled. Disabled Drop Cursor. SQLWindows displays this cursor when a window is in drag mode and dropping is disabled.
Functions
SalDragDropDisableDrop
This function disables dropping while in drag mode:
bOk = SalDragDropDisableDrop( )
SalDragDropEnableDrop
This function enables dropping while in drag mode:
bOk = SalDragDropEnableDrop( )
SalDragDropGetSource
This function returns the handle of the source window and the location of the mouse in the source window when drag mode started:
bOk = SalDragDropGetSource( hWndSource, nX, nY )
SalDragDropGetTarget
This function returns the handle of the target window and the location of the mouse in the target window:
bOk = SalDragDropGetTarget( hWndTarget, nX, nY )
SalDragDropStart
This function starts drag mode:
SalDragDropStop
This function ends drag mode:
bOk = SalDragDropStop( )
SalCursorSetFile
This function sets a cursor for the window:
bOk = SalCursorSetFile( hWnd, strFile, nType )
The strFile parameter is the name of a cursor or icon file specified in the Resources section of the outline. The nType parameter is one of these constants: CURSOR_Window. Displayed when not in drag mode when the mouse is over the window. CURSOR_DisableDrop. Displayed in drag mode when drop is disabled. CURSOR_DragDrop. Displayed in drag mode when drop is enabled.
SAM_DragStart
SQLWindows sends this message when drag mode starts.
wParam lParam X coordinate in the window Y coordinate in the window
17-5
Chapter 17
Drag-and-Drop
SAM_DragEnd
SQLWindows sends this message when drag mode ends.
wParam lParam Not used Not used
SAM_DragNotify
SQLWindows sends this message when a mouse action happens in drag mode.
wParam lParam Handle of a target window One of these values: SAM_DragEnter SAM_DragDrop SAM_DragExit SAM_DragMove The user moved the mouse into a target window The user dropped the mouse in a target window The user moved the mouse out of a target window The user moved the mouse within a target window
SAM_DragDrop
SQLWindows sends this message when the user drops the mouse on this target window.
wParam lParam Handle of a source window Not used
SAM_DragExit
SQLWindows sends this message when the user moves the mouse out of this target window while in drag mode.
wParam lParam Handle of a source window Not used
Auto-dragging example
SAM_DragMove
SQLWindows sends this message when the user moves the mouse within this target window while in drag mode.
wParam lParam Handle of a source window Not used
Auto-dragging example
This example uses auto-dragging to show how to drag a selection in a list box to a data field: The lb1 list box is the source window. When the user holds down the mouse button for an interval, SQLWindows sends the list box the SAM_DragCanAutoStart message. The message actions for the list box process SAM_DragCanAutoStart by returning TRUE if the user has selected an entry. SQLWindows sends the list box the SAM_DragStart message when drag mode starts. The SAM_DragStart message actions get the list box selection and store it as the list box's window text. The df1 data field is the target window. SQLWindows sends the data field the SAM_DragDrop message when the user drops on the data field. The SAM_DragDrop message actions for the data field: Get the handle of the source window from the wParam Make sure the source window is not the data field itself and the parent of the source window is the same as the parent of the data field Get the window text of the source window and use it to set the data field window text
List Box: lb1 ... List Initialization Text: Value 1 ... Message Actions On SAM_DragCanAutoStart If SalListQuerySelection( hWndItem ) != LB_Err Return TRUE Else Return FALSE On SAM_DragStart
17-7
Chapter 17
Drag-and-Drop
! Store the current selection as window text so we can use it on the drop Call SalListQueryText( hWndItem, SalListQuerySelection( hWndItem ), sList ) Call SalSetWindowText( hWndItem, sList ) Data Field: df1 ... Data ... Data Type: String Editable? Yes ... Message Actions On SAM_DragDrop Set hWndSrc = SalNumberToWindowHandle( wParam ) If hWndSrc != hWndItem AND SalParentWindow( hWndSrc ) = hWndForm Call SalGetWindowText( hWndSrc, sSource, 1000 ) Call SalSetWindowText( hWndItem, sSource )
Global Declarations ... Constants System Number: WM_LBUTTONDOWN = 0x201 ... Picture: pic1 ... Message Actions On WM_LBUTTONDOWN Call SalDragDropStart( hWndItem ) Picture: pic2 ... Message Actions On SAM_DragDrop Set hWndSrc = SalNumberToWindowHandle( wParam ) If hWndSrc != hWndItem AND SalGetType( hWndSrc ) = TYPE_Picture Set nLength = SalPicGetString( hWndSrc, PIC_FormatBitmap, strPic ) If nLength > 0 If NOT SalPicSetString( hWndItem, PIC_FormatBitmap, strPic ) Call SalMessageBox('Could not drag picture.', 'Drag-and-Drop Error', MB_Ok | MB_IconStop )
17-9
Chapter 17
Drag-and-Drop
when a user drops on a picture, call SalDropFilesQueryFiles or SalDropFilesQueryPoint in the SAM_DropFiles message processing and decide whether to process what the user is dropping or to ignore it by executing a Return statement with no other processing. To completely disable file dropping for an editable picture, call SalDropFilesAcceptFiles.
The default for editable picture objects is TRUE. The default for all other window types is FALSE. When an object receives a SAM_DropFiles message, call this function to find the location of the mouse where the user dropped the file or files:
bOk = SalDropFilesQueryPoint( hWnd, nX, nY )
When an object receives the SAM_DropFiles message, call this function to get the names of the files that the user dropped:
bFiles = SalDropFilesQueryFiles( hWndSource, sFileArray[*] )
This function returns the number of files that the user dropped. This function returns zero if it fails. This function fails unless you call it in SAM_DropFiles message processing.
SAM_DropFiles message
SQLWindows sends this message to a window when the user drops a file or files from Explorer on the window. SQLWindows only sends this message to windows that have enabled file dropping. Call SalDropFilesQueryFiles to get the names of the files dropped on the object. Call SalDropFilesQueryPoint to get the location of the mouse in the window where the user dropped the file or files. This message does not use wParam or lParam.
Chapter 18
Libraries
This chapter shows how to write and use: Include libraries Dynalibs
18-1
Chapter 18
Libraries
Include libraries
Include libraries let you: Share application components in more than one application Share application components with other developers
An include library is a collection of SQLWindows objects such as form windows, dialog boxes, or class definitions that are shared by more than one application. You edit libraries in the same way as an application. You maintain components for an include library in a single source file. This means that you only need to change one source file to change a component used in many applications. Include library (*.APL) Application 1 (*.APP)
Application 2 (*.APP)
An include library only contains components that you use in other applications. An include library contains a set of related outline items. An item is anything that you can copy to the Clipboard.
Include libraries
These are examples of what an include library can contain: Top-level windows (form windows, table windows, and dialog boxes) MDI windows Internal functions External function definitions Class definitions A group of global variables and constants
Nested includes
You can nest included items. An include library can contain items from other libraries.
When you use an item from an include library in an application, SQLWindows incorporates the item in the appropriate part of the application's outline. In an application, you can include items from any number of libraries. SQLWindows displays included items in the color that you specify in Tools, Preferences. On monochrome computers, SQLWindows displays included items in italics.
18-3
Chapter 18
Libraries
Important: When you use an include library in an application, statements in the application actions section of the library are not included. If you need application actions in a library (such as for SAM_SqlError processing), put the code in an internal function and call the function in the application actions.
You can also change an include library by opening it with another instance of SQLWindows, editing it, and then saving it.
Component menu
The sections below explain the menu items in the Component menu.
Include libraries
Go To Item (F5)
Starts a new instance of SQLWindows and opens the include library that contains the selected included item. You can then edit the included item. When you save and close this instance of SQLWindows, the first instance of SQLWindows resumes. Unless you uncheck Refresh When Changed in Tools, Preferences (page 4-32), SQLWindows detects that one of the included items has changed and automatically re-includes the changed include library. When you edit an included item in an include library, the target item is selected in the include library.
Refresh
Re-includes all libraries. Choose Refresh to include a recently-changed include library without closing the current application (such as when another person changes an include library on a file server).
Merge
Permanently merges all libraries with the open application. Once merged, the items are a fixed part of the application. Merging removes the information that relates the included items to their original libraries. SQLWindows displays a warning dialog before completing the merge.
Tools, Preferences
General tab: Refresh When Changed.
By default, SQLWindows automatically detects changes in libraries and re-includes them if they have changed. Turn off this feature by unchecking the check box. This is useful when libraries are in a remote location or when the re-include is time-consuming.
18-5
Chapter 18
Libraries
C
A dynalib is different from an include library: With an include library, you share source code at designtime. All items in the include library are available in the including application. With an dynalib, you share compiled code at runtime. Only the interface to objects and functions are available to an application that uses a dynalib.
A dynalib shares its objects and functions with other applications. This is called exporting. Other applications use the items. This is called importing. The diagram shows an overview of the process of creating and using dynalibs:
Create a dynalib source file (*.APL) with the items you want to export
Compile the dynalib *.APL source file to create the *.APD runtime library
18-7
Chapter 18
Libraries
Faster Compiles. You do not need to compile dynalibs every time you compile the application. Unlike an include library, the code in a dynalib is not recompiled when you compile the application. This means that using dynalibs can reduce the time required to compile an application.
The items above are not visible to an importing application. However, there are design techniques you can use to share these items in dynalibs. For more, read How to use non-exportable items in dynalibs on page 18-10.
How to export
For each item you want to export, you must explicitly mark it with an __exported pragma in a trailing comment in the item's declaration. Put two underscores at the
start of the pragma. In this example, the declarations mean the dynalib exports numGInLib1 and strGInLib1:
Number: numGInLib1 !__Exported String: strGInLib1 ! Pragmas such as "__exported" are insensitive to case, position, and quoting
For multiline items, put the pragma as a comment on the first line (usually the line where you name the item):
Form Window: frmExporter !__exported Dialog Box: dlgExporter !__exported
System variables
System variables like hWndForm are available to the dynalib and are shared by all dynalibs and an application.
Nesting dynalibs
A dynalib can use objects or call functions in another dynalib. This feature makes it possible for an application to indirectly use the same dynalib more than once. If this happens, SQLWindows loads only one instance of the dynalib and its global variables. For example, an application uses dynalib1 and dynalib2. Dynalib2 also uses dynalib1. The first time the application or dynalib2 refers to dynalib1, SQLWindows loads one instance of it.
Semi-qualified references
You cannot make semi-qualified references to variables (such as hWnd.var) in dynalibs. This type of late-bound reference requires var to be a consistently defined data type and object type throughout the application and all its dynalibs. The compiler cannot enforce this consistency in any other way except to reject the reference because the compiler does not have global knowledge of the application and its dynalibs.
Recompiling dynalibs
You can replace existing dynalibs with newly-compiled ones without recompiling the importing applications if the dynalib's interface does not change. Examples of changes to the interface are: Changing the name of an exported item Changing the return data type of a dynalib's functions Changing the names or data types of a function's parameters
Developing with SQLWindows
18-9
Chapter 18
Libraries
Changing the names or data types of a window's parameters Adding or changing the instance variables of a UDV that is passed as a parameter
However, you can change the behavior of an existing function or add new items.
Version compatibility
When a new version of Gupta is announced as binary incompatible with previous versions in the release notes, this means that dynalibs and importing applications must be recompiled to use the new runtime environment.
UDVs. You can pass UDVs (user-defined variables) between dynalibs or between an application and a dynalib. Place class declarations in an include file that is included by both the dynalib and the application. Inherited Functions. Only window functions explicitly defined by a window are exported from a dynalib. Inherited window functions are not automatically exported. To make an inherited function available to clients of the dynalib, define a window function that does nothing but call the inherited function. This is what the function declaration looks like in the *.APL source file:
CEmpFormClass: LibForm ... Functions Function: GetEmployeeData Description: A call to an inherited function. Returns Boolean Parameters Number: numEmployeeID Actions Return CEmpFormClass.GetEmployeeData( numEmployeeID )
If you do not give a target file name, SQLWindows uses the base name of the source file and an *.APD extension.
18-11
Chapter 18
Libraries
Imported items are displayed in the same color as include library items. Only the interfaces to imported items are displayed in the application, not the entire item with all its child items. For example, SAL code is not displayed. Examples of imported items in an application are shown in later section of this chapter. You refer to imported items the same way as other items. For example, you can call SalCreateWindow in the application to create an instance of a form window defined by a dynalib and pass parameters to the window the same as if you had defined the form window in the application:
Set hWnd = SalCreateWindow( FormEmployee, hWndNULL, numEmployee )
You can then send messages to the form window or call its window functions:
Call FormEmployee.GetEmployeeData( numEmp )
Use function calls instead of messages because message numbers are hard to coordinate across multiple dynalibs and because functions can take as many parameters as you need instead of only wParam and lParam. If you create more than one instance of the form window, you need to use a windowhandle qualified call as you normally do:
Call hWnd.FormEmployee.GetEmployeeData( numEmp )
18-13
Chapter 18
Libraries
Chapter 19
19-1
Chapter 19
COM concepts
Component software
The basis of object-oriented analysis and design is breaking down a project into its logical components. This is also the basis for component software, which is software composed of building blocks. A component is a reusable, self-contained piece of software in binary form that is independent of any application. A component can be plugged into any application with relatively little effort. Components provide a standard model for packaging services and exposing them to consumers. Components are black boxestheir data and implementation details are hidden. A component is not a complete application. A component performs a limited set of tasks within an application domain. A component can be fine grained (for example, a window that only displays JPEG images), medium grained (such as a tabbed dialog control), or coarse grained (such as a multi-dimensional database analysis application). Components can be used in unpredictable combinations and in ways not anticipated by the original developer.
COM
Microsofts COM (Component Object Model) provides a standard way for components to interoperate. Components interoperate using client-server interaction models. COM defines a standardized means for creating components and for controlling the communication between these components and their clients. Unlike traditional objects, components can interoperate across tools and networks. Standardizing the communication means that an application can look for a COM object at runtime, discover its interface, and know how to interact with it.
Interfaces
A COM component exposes one or more interfaces. In its simplest definition, an interface is the way in which an object exposes its functionality to the outside world. An interface is strongly typed contract between a software component and a client that provides a relatively small but useful set of semantically related operations. Each interface provides a set of functions or events through which a client accesses the component: Incoming interfaces are collections of functions which a client can call to request that the component perform an action. Outgoing, or source, interfaces are collections of event definitions. They describe calls which the component can make and which are implemented in
COM concepts
the client, if the client chooses to respond to the event. In COM terminology, components fire events, and clients handle them. The way that an objects methods, events, and properties are related is called the object model. Learning a components object model is essential to using it successfully. COM specifies the binary layout of incoming interfaces as a table of function pointers, based on the C++ vtable structure. For certain components, this means they can be called directly through this table, called a custom interface, from development tools which support the binary level calling style, while others support a more generic, 4GL-style of access, called OLE automation, or automation access, through the IDispatch interface. Automation access is the only access supported by SQLWindows. A server is a COM component which provides an interface (or interfaces) and a client is an application which uses an interface by calling one or more of its functions.
GUIDs
Each COM component is identified by a globally unique identifier (GUID). COM servers use these types of identifiers: Each COM class is uniquely identified by a class ID (CLSID) Each interface is uniquely identified by an interface ID (IID) Each method is identified by a dispatch ID (dispID) Each event is identified by a dispatch ID
Through the use of GUIDs, each object is referenced at runtime by COM. The association between the GUID information and the host server is stored in the registry. Every server that hosts COM objects must be registered in order for those objects to be available to client components.
Type information
Type information is standard descriptions of properties, methods, and events that an object supports as well as return types, parameter names, and parameter types. Type information is stored in a type library. Clients read a type library to get information about server objects properties and methods.
19-3
Chapter 19
message and calls the method on the server-side object. This technique of packing and unpacking function call parameters is called marshalling. Client COM libs Proxy Microsoft RPC Distributed COM (DCOM) extends COM across machine boundaries, providing remote invocation of COM component in a location-transparent manner. Location transparency enables a client application to function consistently, regardless of whether the components it uses are located on the client machine or on a separate machine. Whether the client and server are on the same computer or on different computer, the communications between the two takes place through RPC (Remote Procedure Call). Lower-level protocols ride underneath RPC. RPC masks the differences between heterogeneous computers. Server Stub COM libs
Microsoft provides many different server types within its software offerings, and within Microsoft Office all three types are available, as well as both visual and nonvisual components. The Microsoft Calendar Control is an example of an ActiveX
COM concepts
Control which supports events and automation access, and Microsoft Word provides examples of both visual and non-visual components: the Microsoft Word application component is a non-visual component and supports both automation access (through functions and events), and the Document component can be incorporated into a SQLWindows application as an insertable object, complete with type information, or hosted within the container control. When acting as a COM component client, SQLWindows applications must access components through auto-generated SAL classes called proxy classes, which can be functional classes for access to COM interfaces, COM Proxy Classes for COM CoClasses, and ActiveX classes which extend their COM Proxy CoClasses as child window types. All automation access is made through the functional class which acts as a proxy to the COM interface. For more, read COM client class outline structure on page 19-17. SQLWindows clients fully support ActiveX semantics such as automation (page 19-30), events (page 19-33), embedding (page 19-28), menu merging (page 19-36), and toolbar negotiation (page 19-36).
19-5
Chapter 19
The table below maps the COM entities to the outline types:
COM entity CoClass Interface Event interface COM server outline type CoClass class Interface class COM server Events section COM client outline type COM Proxy class or ActiveX class (if visual) Functional class, derived from Object class Message Actions child items in COM Proxy or ActiveX classes, or ActiveX class child windows
4.
5.
The Controls palette is the most convenient way. Using it, you have direct access to the ActiveX objects installed on your computer. With ActiveX Explorer, you must know the name of the type library that contains the object you want. A type library can contain many objects, so you may have to hunt for the object once the type library is open. The Controls Palette only contains visible objects. For non-visible objects, you must use ActiveX Explorer.
Both the Controls palette and ActiveX Explorer generate an include file with a class hierarchy for the object. In turn, this include file includes automation.apl which defines the standard classes Object, Variant, SafeArray, and OleErrorInfo. The file "OLE automation.apl" may also be included. It is an auto-generated file and its contents depend on what is installed on your computer.
Note: The Controls palette always generates the include file with the Generate Full option. For more, read SAL code generation options on page 19-13.
ActiveX button
19-7
Chapter 19
When you click the right mouse button while over a list of ActiveX components in the Controls palette, you can: Add a button for the selected component to the Controls palette Choose to display only controls or insertable objects
To create an ActiveX component at designtime using a button on the Controls palette: 1. 2. Click the ActiveX button in the Controls palette. Select an ActiveX component in the list and drag it just to the right of the ActiveX button OR Select an ActiveX component in the list, click the right mouse button and select Add to Palette. 3. When you want to create the object, click its button and then draw it on the toplevel window as you would any other object.
To create an ActiveX insertable object at designtime using the Insert Object dialog: 1. 2. 3. Click the ActiveX button in the Controls palette. Draw the object on the top-level window as you would any other object. The Insert Object dialog appears. Select an insertable object in the dialog and click OK.
To create an ActiveX insertable object at designtime using the Paste Special dialog: 1. Click the ActiveX button in the Controls palette.
2. 3. 4. 5.
Draw the component on the top-level window as you would any other object. The Insert Object dialog appears. Click Cancel. Later, select the insertable object and right click the mouse and select Paste Special. The Paste Special dialog appears. In the Paste Special dialog, set the options and click OK.
To create an ActiveX insertable object at runtime (an empty ActiveX container) using the SAL ActiveX API: 1. 2. 3. 4. Click the ActiveX button in the Controls palette, but do not choose any specific control from the dropdown list. Draw the component on the top-level window as you would any other object. The Insert Object dialog appears. Click Cancel. In your application logic, call a SAL ActiveX API function to create the object.
After viewing a type library, you can use ActiveX Explorer to generate SAL code for interfaces that you select. ActiveX Explorer creates an APL with a class hierarchy that invokes the methods of the server. ActiveX Explorer includes this APL in the current application. ActiveX Explorer can also check an AXLibs *.APL and open its corresponding type library.
19-9
Chapter 19
ActiveX Explorer can also open context-sensitive help for a type library if help for the type library exists.
Toolbar
From left to right, this is the function of each of the buttons: Displays ActiveX Explorer open type library dialog Displays the help file for the open type library Generates an *.APL for the open type library Sets the options for generating an *.APL Regenerates the *.APL for the open type library Includes the *.APL for the open type library in the outline Shows or hides CoClasses in the open type library Shows or hides interfaces in the open type library Shows or hides events in the open type library Shows or hides enums in the open type library Shows or hides functions in the open type library Shows or hides get properties in the open type library Shows or hides set properties in the open type library Displays data types as SAL data types or as automation data types
There is also an ActiveX Explorer menu to the right of the Tools menu when you display ActiveX Explorer. The items in this menu correspond to the toolbar buttons.
By default, when you select Gupta APLs, ActiveX Explorer displays the names of APLs in the AXLibs directory, but you can click the Browse button to navigate to a different directory. The *.APL must have been generated by ActiveX Explorer (SQLWindows 3.0).
19-11
Chapter 19
When you select an *.APL and click OK, ActiveX Explorer checks the APL to find the name of the type library, and then opens and reads that type library. After ActiveX Explorer opens a type library, it displays a dialog with three sections: ClassView, a list in the upper left-hand part MembersView, a list in the upper right hand part InfoView in the bottom part
Each of these sections has its own context menu. You can resize the ClassView, MembersView, and InfoView sections using the splitter cursor.
ClassView
The ClassView shows CoClasses, interfaces, event sets, and enumerations in the type library.
ClassView
By default, the ClassView section lists its items alphabetically, but you can check Group Members in the context menu to sort the list by type. You can also view only certain types by checking items in the context menu. When you select Generate, SQLWindows creates an AXLibs *.APL and includes it in the current application. What SQLWindows puts in the *.APL depends on the options you set in Generate Options and on the items you check in the ClassView. You can 19-12 Developing with SQLWindows
individually check certain items in the ClassView or select Check All Shown in the context menu to check all items. These are examples of the icons in the ClassView: Library CoClass Interface Event Enumeration
Stub. Generates the selected classes without any functions. Use this option when you need some classes to appear in the outline which, although your code does not use them directly, are referred to in the Functions of the classes which you do use. Stub generation of a CoClass will cause stub generation of its interfaces, even if they are not selected in the list. Full. Generates the selected classes with implementations for all of the classes' functions. In addition, this option generates stub classes for any classes which are directly referred to by the ones which are being completely generated, so that the APL code can compile.
19-13
Chapter 19
Deep. Generates the selected classes with implementations for all of the classes' functions. In addition, this option generates all classes which are directly or indirectly referred to with implementations for all of their functions. The option selected here is the default Generate option in ClassView context menu, The ActiveX Explorer toolbar, and the ActiveX Explorer menu.
Invoke Options
Invoke by Function Name. Invoking by function name is particularly desirable for generating client code for development of custom COM servers and ActiveX objects. The dispatch IDs for these objects may change during development. They can also change from version to version. An incorrect dispatch ID can result in a wide range of problems, from runtime errors to undefined program behavior. The worst case would be the intended method having the same parameter list as the actual called method, but different functionality. Invoking by name avoids such problems, although it is slower. Invoke by Dispatch ID. Invoking a COM object by using its dispatch ID is signficantly faster than using a function name. This is especially true when invoking the object a large number of times, as in filling a spreadsheet from a database.
Note: You can generate an interface from the ClassView list by selecting it for generation, or by selecting a CoClass which implements that interface.
If you generate enumerations, SQLWindows adds each member as a constant in the outline.
MembersView
The MembersView displays the items in a CoClass, interface, event set, or enumeration.
MembersView
When a CoClass is selected in ClassView, the MembersView displays interfaces for that CoClass When an interface is selected in ClassView, the MembersView displays methods in that interface When an enumeration is selected in ClassView, the MembersView displays its enumerations When an event set is selected in ClassView, the MembersView displays its events
As with the ClassView, you can list the item alphabetically (default) or by type and you can choose to show only certain types of items.
19-15
Chapter 19
These are examples of the icons used in the MembersView: Method Get Prop Set Prop Event Enumeration
InfoView
The InfoView section displays details about the selected item in the ClassView or MembersView.
InfoView
Using the context menu, you can: Switch between displaying a function or event in its SAL form, using SAL data types, or in its COM form, using automation data types. Open the help file for the type library. If the InfoView is displaying information for an item, ActiveX Explorer sets the help display to that topic when possible.
To learn more about these classes read Object class on page 19-40 and COM Proxy Class on page 19-41. When SQLWindows generates a COM Proxy class, it also generates a functional class for each interface that the CoClass implements. The classes are added to the base classes of the COM Proxy class. These functional classes provide the means to access the functionality provided by the COM component.
19-17
Chapter 19
If the class is visual, SQLWindows generates a further class: Nonvisual CoClass Object Visual CoClass Object
At runtime, a nonvisual COM object does not exist until you call its Create method:
Call MyCOMProxy.Create
19-19
Chapter 19
top. Each object represents an element of an application, such as a cell in a worksheet or a word in a document. To effectively use an Office application through SQLWindows and ActiveX, you must learn the applications object hierarchy. VBA has two types of documentation: MSDN and online help.
MSDN documentation
If you have MSDN (Microsoft Developer Network), you can find the Visual Basic Programmers Guide and Visual Basic Language Reference for Office 97 VBA in: Office Developer Documentation/Office 97 Documentation
You can find the Developer Object Model Guide, Visual Basic Programmers Guide and Visual Basic Language Reference for Office 2000 VBA in:
Office 97
To install the help for Office 97 VBA: 1. Start the install program. For a new installation, complete each dialog until you get to the one where it asks you the type of installation you want. Select Custom.
19-21
Chapter 19
If you already have Office 97 installed, then select Add/Remove at this dialog:
2.
Select the application (such as Excel) for which you want to install VBA help. Click Change Option.
3.
Select the help component. The wording varies depending on the application as shown in the table below.
Wording
19-23
Chapter 19
4.
Select Change Option. As with the previous dialog, the wording varies depending on the application, but you want to check Help for Visual Basic, Online Help for Visual Basic, or Programming Help.
5.
Important: You must repeat the steps above for each application for which you want to install VBA help.
Installing Outlook 97 VBA help. The Office 97 installation program cannot install the VBA help for Outlook. You must manually copy the files. The VBA help file for Outlook is in the ValuPack directory on the Office 97 CD. To install this help file: 1. 2. 3. 4. 5. 6. 7. 8. Quit Help. Insert the Office CD. In the ValuPack directory, double-click the MoreHelp subdirectory. Select the vbaoutl.hlp and vbaoutl.cnt files. Copy these two files to your Office 97 installation directory (usually C:\Program Files\Microsoft Office\Office). If asked whether you want to replace the existing versions of these files, click Yes. To update the table of contents and the index so that they include the topics in the files you just copied, select Start, Find and then click Files or Folders. In the Named field, type *.gid.
9.
In the Look in field, type C:\Program Files\Microsoft Office\Office (or your installation directory) and then click Find Now.
10. When the file names appear at the bottom of the dialog box, select all of them and select File, Delete.
Office 2000
1. 2. 3. Start the install program and proceed to the Selecting Features step. Expand the Office Tools branch. Select Visual Basic Help and click.
4.
Warning: Selecting Run from My Computer does not install the files.
5.
19-25
Chapter 19
For Word 2000, this topic is displayed automatically when you open vbawrd9.chm.
Controls
To get an overview of the class hierarchy for Excel 97, open vbaxl8.hlp, double-click Getting Started with Visual Basic, and then double-click Microsoft Excel Objects.
For Excel 2000, this topic is displayed automatically when you open vbaxl9.chm.
Controls
A control is a lightweight, in-process object. A control typically implements IDispatch (automation) and type information, and can have events. A control has an *.OCX extension.
19-27
Chapter 19
The main advantage to using the ActiveX container control to embed automation objects is that users can insert any one of a variety of object types into an application at runtime and subsequently manipulate the object programmatically via the SalActiveX* API. To create an ActiveX container control, follow these steps: 1. 2. 3. Click the ActiveX button on the Controls palette. Draw the control on a form or dialog. Click Cancel, since you do not wish to do any further development to the control at design time.
Embedded objects
Data associated with an embedded object is contained in an ActiveX container control and can be saved with your application.
Note: To place an object in an ActiveX container control, the object must be in your system registry. When you install an application that supplies the objects you want to use in your application, that application should register its object library on your system so that application's objects appear in the Insert Object dialog and in the Controls palette.
When you use an ActiveX container control to create an embedded object, all the data associated with the object is copied to and contained in the ActiveX container control. When you save the contents of the control to a file, the file contains the name of the application that produced the object, the object's data, and a metafile image of the object. For this reason, embedded objects can greatly increase the size of an application.
than an application that displays the same data using a linked object because the application with the embedded object actually contains the source file's data. To create an embedded object, follow these steps: 1. 2. 3. 4. 5. 6. 7. Click the ActiveX button on the Controls palette. Draw the control on a form or dialog. Click Create from File. Click Browse. SQLWindows displays the Browse dialog. Navigate to the file you want to embed and select it. Click Open. You return to the Insert Object dialog. In the Insert Object dialog, click OK to create the embedded object.
SalActiveX functions
For details about these functions, read the online help. These functions provide support for all ActiveX objects.
Name SalActiveXAutoErrorMode Description Turn off automatic error handling (on by default) by calling this function and specifying FALSE. Later, you can turn automatic error handling on by calling this function and specifying TRUE. Gets an instance of an ActiveX object when the server application is already up and running.
SalActiveXGetActiveObject
You can programmatically manipulate a container control and its contents at runtime using these functions.
Name SalActiveXClose SalActiveXCreate SalActiveXCreateFromData SalActiveXCreateFromFile SalActiveXDelete Description Closes an object and ends the connection to the application that provided the object. Creates an object given its class descriptor (progID). Recreates an object from binary storage data, in the form of a string. Creates an instance of an ActiveX object. Deletes an instance of an ActiveX object.
19-29
Chapter 19
Description Opens an object for an operation such as editing. Each object can support its own set of verbs. Gets the storage (state and data) associated with the object as a raw blob of bytes. This provides an alternate runtime persistence mechanism for embedded objects. Gets the file name of an ActiveX object that was inserted into a window using the SalActiveXInsertObjectDialog function and the Create from File option. Gives access to the automation dispatch interface of the object in the specified container. Gets the ProgID of an ActiveX object that was inserted into a window using the SalActiveXInsertObjectDialog function and the Create from File option. Displays the standard Insert Object dialog. Returns the status of the object in an ActiveX container control.
SalActiveXGetFileName
SalActiveXGetObject SalActiveXGetProgID
SalActiveXInsertObjectDlg SalActiveXOLEType
Automation
Automation is an industry standard used by applications to provide objects in a consistent way to other applications, development tools, and macro languages. To use automation, the object must support the IDispatch interface. There are two type of automation: static and dynamic.
Static automation
With static automation, type information is available at compile time (early bound) and all calls are type checked for validity. With static automation, you use ActiveX Explorer or the Controls palette to generate a functional class derived from the Object class. This derived class contains a function for each of the object's methods. Each function pushes any parameters onto the stack, invokes the method, and pops a return. For example, ActiveX Explorer generated this code to invoke a tree control's GetNode method:
Function: GetNodes Description: Returns
Automation
Boolean: Parameters ComctlLib_INodes: returnValue Static Variables Local variables Boolean: tmpret Actions Set tmpret = Invoke("Nodes", INVOKE_GET) Call PopObject(-1, returnValue) Call FlushArgs() Return tmpret
Dynamic automation
With dynamic automation, you use the methods of the Object class directly to make calls to the server. You do not use ActiveX Explorer to generate method invocations. No type information is used and invalid invocations can cause runtime errors. Push any parameters onto the stack and then invoke the method:
xlapp.PushStringByRef( "hello" ) xlapp.Invoke( "SetActiveCell", INVOKE_FUNCTION )
To invoke a method, you must: 1. 2. 3. 4. Push parameters onto the stack, either by value or by reference Execute the method by calling Invoke or InvokeID Pop the parameters off the stack Flush the parameters from the stack by calling FlushArgs
19-31
Chapter 19
The easiest way to write this code is to let ActiveX Explorer generate it automatically and then use that as a starting point. The examples below show the code that is generated by ActiveX Explorer.
Handling events
Boolean: Parameters Variant: Item Variant: Key Variant: Before Variant: After Static Variables Local variables Boolean: tmpret Actions Call PushVariantByRef(Item) Call PushVariantByRef(Key) Call PushVariantByRef(Before) Call PushVariantByRef(After) Set tmpret = Invoke("Add", INVOKE_FUNCTION) Call PopVariant(0, Item) Call PopVariant(1, Key) Call PopVariant(2, Before) Call PopVariant(3, After) Call FlushArgs() Return tmpret
At runtime, you call the Objects CreateObject method to create a specific object.
xlapp.CreateObject( Excel.Sheet.8 )
Handling events
An event interface is part of a CoClass signature. A COM server interface fires events. A SQLWindows client application can process events from both visual and non-visual servers. An event belongs to CoClass, not to a window, and there is no correspondence between events and Windows messages. If an ActiveX control has defined events, SQLWindows represents the event in the Message Actions section of the outline. Event handlers have a fixed signature (as
19-33
Chapter 19
defined by the control), but you define the implementation in the Message Actions block.
Functional Class COM Proxy Class ActiveX Class Process events in a visual ActiveX object in the Message Actions of a derived class or in an instance Visual instances Your COM Proxy Class Non-visual instances
Process events in the Message Actions of a COM Proxy Class that you derive from the generated COM Proxy Class
To process events with non-visual servers, you derive a new COM Proxy Class from the generated COM Proxy Class. The events for the COM Proxy Class appear in Coding Assistant and in the context menu when you are positioned in the Message Actions in derived classes. 19-34 Developing with SQLWindows
Handling events
COM Proxy Class: WordApp Description: Derived From: Class: Word_Application ... Message Actions On DocumentChange Parameters Actions ... On Quit Parameters Actions ...
To process events with visual servers, add code in the message actions of instances of the ActiveX Class. The events for the ActiveX Class appear in Coding Assistant and in the context menu when you are positioned in the Message Actions of an instance of an ActiveX class.
If an event has parameters, SQLWindows adds definitions of them to the Parameters section. This example shows an instance of a visual ActiveX object:
AX_MSACAL_Calendar: CalendarCtrl Message Actions On KeyDown Parameters Receive Number: KeyCode Number: Shift Actions ...
SQLWindows assumes that any numeric event parameter is the same subtype as defined by the server. You may also add subtypes to the definition of numeric event parameters, which may change the numeric value that the server passed. For example, if the server defines an event parameter as subtype VT_R8 and passes the value 3902.58, your client application will receive that value. But if you manually add a subtype of VT_I4 to the parameter definition in your client application, it will then receive a value of 3903. Gupta recommends that you explicitly add the appropriate subtype to each numeric event parameter defined by your client application.
19-35
Chapter 19
Properties
When an ActiveX object is selected, the Attribute Inspector displays the properties of the control and you can edit them.
Ambient properties
ActiveX objects usually ask their container for the current values of certain stock entities such as font and background color. This provides a consistent look-and-feel coordination between controls in a window.
In-place activation
When an ActiveX object supports in-place activation, a user can double-click the object to interact with the application supplying the object without switching to a different application or window. The menus and toolbars of the server application merge with those of the application that contains the object. By convention, only embedded objects support in-place activation.
Collections
SQLWindows follows similar rules for menu merging: At designtime, SQLWindows merges the object server's menus with the menu in with the main SQLWindows window At runtime, SQLWindows merges the object server's menus with the menu in the parent window of the container control
Menu groups
In ActiveX, menus in clients and servers are assigned to menu groups. ActiveX clients have these three groups: File Container Window
The actual menus that go into each group depend on the nature of the application. However, when an ActiveX client merges its menus with a server's, it follows this strict order: File group (client) Edit group (server) Container group (client) Object group (server) Windows group (client) Help group (server)
You identify which menus belong to the client's File, Container, and Window groups in the menu editor (select Component, Menu Editor). In the Menu Editor, there is an ActiveX Menu Group combo box where you associate a menu with one of the client groups. For more, read Menu Editor on page 6-10.
Collections
A collection is a group of related objects that can be indexed numerically like an array. A collection lets you work with a set of similar things as a single group instead of as independent entities. SQLWindows supports ActiveX collections with these methods in the Object class: IsCollection Next Reset
Developing with SQLWindows
19-37
Chapter 19
Skip
The Object class methods let you manipulate a collection in a type-independent manner. A collection is a dispatch interface that has a property name "_NewEnum" or "NewEnum". The DISPID of this property is always DISPID_NEWENUM. The IsCollection method in the Object class looks for this property to determine if the object is a collection. The Next, Reset, and Skip methods are implemented through a COM interface named IEnumVARIANT. The methods implemented in a collections actual interface let you manipulate a collection in a type-dependent manner. A collections interface must implement these methods: Count Item
Handling exceptions
SQLWindows has two types of ActiveX error handling: Default error handling where SQLWindows detects ActiveX error and displays a standard error dialog Custom error handling where you detect and handle errors
Gets a detail about an error when an Invoke fails. The textual description of the error is obtained from the description field of OleErrorInfo structure. Source of the error is obtained from the source field. The helpFile field contains the fully qualified drive, path, and file name of a Help file with more information about the error. The Help context ID of the topic within the Help file can be obtained from the helpContext. The scode field will contain a value describing the error. Either this field or wcode (but not both) will be filled in. 19-38 Developing with SQLWindows
Handling exceptions
If you turn off automatic error handling, you may need to include extra logic in your application to properly decode some errors. For example, if you are using the Microsoft Rich Text control, and your application supplies an invalid file name as a property to that control, the error returned in the scode field is 2146828213. In Visual Basic, the same error would return 75. To get the 75 value in SAL, convert the large negative value to hexadecimal, then extract the rightmost four hex digits (004B), then convert that value to decimal (75). Parameters olexExceptionOleErrorInfo. An instance of the ActiveX exception class. Return value bOK is TRUE if the function succeeds and FALSE if it fails.
You can then check the instance variables or use them in a custom error dialog. Heres an example:
ActiveX ax1 OleErrorInfo oError If ax1.GetLastError( oError ) Set mlDesc= oError.description || oError.source Set dfScode= oError.scode Set dfWcode=oError.wcode Set dfHelpContext = oError.helpContext Set dfHelpFile = oError.helpFile
The table below describes the variables in OleErrorInfo: Variable name scode wcode source description helpFile helpContext Return value Error code Version-independent progID Explanation of error Fully qualified help file path and file name Help context ID of relevant help topic Description
19-39
Chapter 19
Include libraries
When you add an ActiveX component to an application, SQLWindows generates wrapper classes in an include library that is included by your application. Gupta creates one include library per type library and as you add components to your applications, Gupta adds to the include library. SQLWindows uses the root name of the type library and adds an *.APL extension. SQLWindows uses this mechanism so that it does not have to regenerate the wrapper classes each time you re-use a component. You can set the directory where SQLWindows stores the ActiveX include libraries, by selecting Tools, Preferences, clicking the Directories tab, and specifying a directory in the ActiveX Libraries field. For more, read Preferences on page 4-32.
Licensing
Some controls ship with a license file that limits the controls use to where they are installed. When you add such a control to an application, SQLWindows stores the license in the outline. When SQLWindows creates the control for deployment, it uses the license to validate creation of the control.
Object class
The Object class represents an ActiveX dispatch interface. The Object class contains methods to manage automation. You use it to call functions and get and set properties on an ActiveX object:
Name Attach Count CreateObject Description Attaches this Object to the dispatch of another Object Counts the number of items in a collection. Creates an automation object locally.
Name CreateObjectEx Detach FlushArgs GetLastError Invoke InvokeID IsCollection IsDispatchVaild Next Pop* Push* Push*ByRef
Description Creates an automation object on a remote server. Disassociates an object from its server to force release early. This frees resources when an application no longer needs an object. Call this function after popping parameters off the stack to reset the stack Gets details about an error when an Invoke fails Invokes a method by name. Invokes a method by its dispatch ID. Determines whether an ActiveX object is a collection. Determines whether an ActiveX object has a been attached as an automation object. Gets the next item in an ActiveX collection. Pops a parameter value off the stack after invoking a method. Pushes a parameter value onto the stack before invoking a method. Pushes a parameter value by reference onto the stack before invoking a method. Use this function when the function you are invoking can change the value you are passing. Resets the ActiveX collection back to the first item. Moves the internal pointer in an ActiveX collection forward by a number of elements.
Reset Skip
19-41
Chapter 19
Function Release
Description Releases the association between the COM class variable and the SQLWindows data structures.
Variant class
The Variant class represents the ActiveX VARIANT runtime data type. A Variant can contain any kind of data. You can use the Variant class in place of any data type (including built-in data types and the Object data type) to work with data in a more flexible way. SQLWindows uses the Variant type to pass parameters for dispatch interfaces (IDispatch) used in automation.
Warning: The Variant class is intended only for supporting interfaces to ActiveX and is not recommended as a general purpose class for SAL programming. This class is not appropriate for most general purpose SAL programming. Instead use the native SAL types for non-ActiveX programming.
Warning: When storing data in a Variant object, the data is copied. This includes storing Strings and SafeArrays. This is necessary for transporting data to and from ActiveX components, but causes significant performance problems if used for general purpose SAL programming. Instead, you should use SQLWindows's native arrays and Strings as much as possible and only convert to a SafeArray when required for ActiveX.
Methods
This class has the methods in the table below. For details about these methods, read the online help.
Name ActiveXType AsActiveX Get* MakeOptional SalType Set* Description Returns the type of value stored in the Variant. Changes the Variant to the VT_* type you specify. Gets a value stored in the Variant. Call this when using a Variant as an optional parameter. Returns the SAL data type. Assigns the specified value to the Variant.
Variant class
Description Not applicable TRUE=-1, FALSE=0 OLE automation string currency date IDispatch SCODE Variant created, but not assigned a value 1-byte signed int 2-byte signed int 4-byte signed int 4-byte real 8-byte real 1-byte unsigned int 2-byte unsigned int 4-byte unsigned int IUnknown interface VARIANT C-style void Not applicable
SAL type constants SAL_ARRAY SAL_BOOLEAN SAL_STRING SAL_NUMBER SAL_DATE SAL_OBJECT SAL_NUMBER Not applicable SAL_NUMBER SAL_NUMBER SAL_NUMBER SAL_NUMBER SAL_NUMBER SAL_NUMBER SAL_NUMBER SAL_NUMBER Not applicable SAL_VARIANT SAL_NUMBER SAL_NOTYPE
SAL data type SafeArray Boolean String Number Date/Time Object Number Not applicable Number Number Number Number Number Number Number Number Not applicable Variant Number Unknown; possibly corrupt
19-43
SafeArray class
You use SafeArrays to pass arrays along with information about the array's dimensions and bounds. The reason they are safe is because the array itself is a data structure that contains boundary information as well as actual reference to the data.
Warning: When storing data in a Variant object, the data is copied. This includes storing Strings and SafeArrays. This is necessary for transporting data to and from ActiveX components (marshalling), but causes significant performance problems if used for general purpose SAL programming. Instead, you should use SQLWindows's native arrays and Strings as much as possible and only convert to a SafeArray when required for ActiveX.
You can create three types of SafeArrays: One dimensional Two dimensional Multi-dimensional
There is a separate type for two dimensional arrays because they are common. The multi-dimensional array is generic. This class has the methods in the table below. For details about these methods, read the online help.
Name Create Create2D CreateMD GetLowerBound GetLowerBound2D GetLowerBoundMD Get* Get*2D Get*MD GetUpperBound Description Creates a single-dimensional SafeArray. Creates a two-dimensional SafeArray. Creates a multi-dimensional SafeArray. Returns the lower bound in a single-dimensional SafeArray. Returns the lower bound in a two-dimensional SafeArray. Returns the lower bound in a multi-dimensional SafeArray. Gets a Date, Number, Object String, or Variant from an array element in a single-dimensional SafeArray. Gets a Date, Number, Object String, or Variant from an array element in a two-dimensional SafeArray. Gets a Date, Number, Object String, or Variant from an array element in a multi-dimensional SafeArray. Returns the upper bound in a single-dimensional SafeArray.
Description Returns the upper bound in a two-dimensional SafeArray. Returns the upper bound in a multi-dimensional SafeArray. Puts a Date, Number, Object String, or Variant into an array element in a single-dimensional SafeArray. Puts a Date, Number, Object String, or Variant into an array element in a two-dimensional SafeArray. Puts a Date, Number, Object String, or Variant into an array element in a multi-dimensional SafeArray.
These classes contain methods that get and set properties. For details about parameter and return types, start ActiveX Explorer, and select Standard OLE Types.
19-45
Chapter 19
Chapter 20
Important: Before reading this chapter, read COM concepts on page 19-2.
20-1
Chapter 20
Overview
You can write COM automation servers with SQLWindows and create non-visual business objects. You use the Interface and the CoClass outline types to write COM servers. Through COM automation, clients can call methods that you write in the Interface. You can also define events in the CoClass and fire them in the Interface code. Clients can process these events. SQLWindows generates GUID identifiers automatically for a server class and its interfaces, methods, and events. SQLWindows automatically generates type library information about the server. You can install automation servers that you write with SQLWindows as MTS packages. For more, read MTS (Microsoft Transaction Server) support on page 2034. SQLWindowss COM server support is intended for non-visual automation servers, not visual editing servers. To write COM automation servers, you use these two types of classes: Interfaces and CoClasses. You derive a CoClass from one or more Interfaces. Interface Interface implementation
CoClass
You can derive an Interface from a functional class, or from another Interface. You can derive the CoClass from multiple Interfaces where each Interface represents a different model of programmatic access.
Note: Like a CoClass, an interface may use multiple inheritance. However, an Interface may only inherit from a maximum of one other Interface; in that situation, any additional parent classes must be functional classes.
You can derive a server from existing interfaces or from new interfaces. For MTS servers, you can request the that the server support IObjectControl.
Important: You cannot use the wizard to edit existing CoClasses or interface classes. You can only edit the elements of a new (just being created) entity. For example, if you derive a new CoClass from an existing Interface, you cannot edit the Interface although the wizard will display the methods and properties of the Interface.
20-3
Chapter 20
You create servers and interfaces with the COM Class Wizard by specifying information in a series dialogs as shown in the diagram below. Select what to generate
CoClass
MTS CoClass
Interface
Same as for COM server on the left, with additional settings for MTS
Choose collection element type Add argument Add function Add property Add argument Add event Set attributes Summary Specify/view functions, properties, and events
Optional step
To start the COM Class Wizard, select Components, Wizards or press Ctrl+W. Then in the Wizards dialog, start the COM Class Wizard by double-clicking its icon or by selecting its icon and clicking Start.
In the first dialog you specify what you want to create (CoClass, MTS CoClass, or Interface).
20-5
Chapter 20
If you select COM server in the first dialog, SQLWindows displays this dialog where you name the server, set its attributes, and name or select the interfaces.
Important: You cannot derive from more than one new interface; you can derive from multiple existing interfaces.
Click Top level object to make this creatable by clients outside the server. Click the Attributes button to set the description, helpstring, and help context number for the server.
To derive the server from a new interface, click New Interface. In a later dialog you specify the functions and properties of the interface.
To make a new interface a collection, click Collection. When you click Next, SQLWindows displays a dialog where you specify whether this is a collection of an existing class or a collection of an intrinsic data type. To derive the server from an existing interface, click Existing Interface and then click Pick Interface. SQLWindows displays a dialog where you can select existing interfaces.
In this dialog you select one or more existing interface classes from which you want the server class to derive. Use the arrow buttons to move class names from the lefthand list to the right-hand list. Use the Up and Down buttons to change the order of the derived from list. If you specify that a server is a collection, SQLWindows displays this dialog where you specify whether the server is a collection of an existing class or a collection of an intrinsic data type (but only those compatible with the standard automation data
20-7
Chapter 20
types). When you click Next, SQLWindows automatically generates Item, Add, and Remove functions, and a Count property for the collection.
For collections of Number data types, you select the corresponding automation type from the list. For more, read Setting the automation type for Numbers on page 20-17.
After you specify the information about the interfaces, SQLWindows displays the dialog below.
In this dialog you define or view the functions and properties of each interface. You can also define the servers events in this dialog.
Note: If the selected interface already exists, you can only view the functions, properties, and events.
To set the description, help string, and help context number for a new interface, click the Attributes button next to the interface name.
20-9
Chapter 20
For functions and properties, begin by selecting an interface name in the drop-down list at the top. If this is a new interface, click Add to add a new function or property. If this is an existing interface, the functions are listed but you cannot edit them.
Note: SQLWindows only generates function stubs for functions and properties. Later you must add code using the outline editor.
In the Add Function dialog you specify the name of a function, its parameters, and its return type. For returns that are Number data types, you select the corresponding automation type from the list. For more, read Setting the automation type for Numbers on page 20-17.
To add a parameter click the plus button to display the Add Argument dialog. Use the arrow buttons to change the order of the parameters.
In the Add Argument dialog, you specify the parameter name, its data type, whether it is an array, and whether it is passed by value or passed by reference (receive parameter). For Number parameters, you select a corresponding automation type that same way you do for returns. If you click the Properties tab, you can add accessor functions that read and write named attributes.
Enter the name of the property and select its data type. For Number data types, you select a corresponding automation type that same way you do for returns and parameters. Also select whether this is a Set or Get property only or both a Set and Get property (the default is Set only). SQLWindows generates functions with names with this format: PropGetname PropSetname
20-11
Chapter 20
To set the description, help string, and help context number of a function or property, select the function or property and click the Attributes button below the list.
Warning: After you generate a COM server, you can edit the outline and assign unique help strings and help contexts to the PropGetname and PropSetname functions of a given property. However, when you compile and SQLWindows generates the type information, the PropGetname help string and context is assigned to the PropSetname function as well. This is not a defect in SQLWindows, but is a COM feature: a property only has one help string and context even if it has both a get and set function.
To add or view events, click the Events radio button at the top of the dialog.
To set the description, help string, and help context number of the events, click the Attributes next to the Events radio button.
If this is a new server class, click Add to add a new event. If this is an existing class, the events are listed but you cannot edit them.
In this dialog you specify the name of an event and its arguments. Click the plus button to add a new argument (this displays the same dialog as for the Add Function dialog). For events that are Number data types, you select a corresponding automation type in the Add Argument dialog in the same way that you do for returns, parameters, and properties. Use the arrow buttons to change the order of the arguments. SQLWindows adds the event you define to the Events section of the CoClass. If you select MTS CoClass in the first COM Class Wizard dialog, the second dialog has additional items for MTS.
If you check Support IObjectControl, SQLWindows generates an IObjectControl class (with the name specified in the field on the right) with these functions: Activate,
20-13
Chapter 20
CanBePooled, and Deactivate. If you check Can be pooled, SQLWindows generates a Return TRUE statement in the CanBePooled function.
If you select interface in the first COM Class Wizard dialog, this dialog appears.
In this dialog you specify the name of the interface and whether it is a COM collection. You may also designate an existing interface, from which the new interface inherits, by choosing an existing interface name in the Derives From combo box.
Outline
At the end of the process, SQLWindows displays this page which summarizes what you generated.
Outline
This is the generated outline structure for a COM server:
Interface: ILineItem Description: Attributes GUID: {90B8E4A0-0010-11D4-BF61-005004707BD0} Help String: Help Context: 0 Derived From ... Class Variables Instance Variables Functions Function: Show Description: Attributes Dispatch Number: 0 Help String: Help Context: 0 ... ... CoClass: LineItem Description: Attributes
20-15
Chapter 20
GUID: {46C6976-6572-0013-0007-1900000000064} Help String: Help Context: 0 Creatable: Yes Derived From Class: ILineItem Events Attributes GUID: {90B8E4A2-0010-11D4-BF61-005004707BD0} Help String: Help Context: 0 Event: ItemEvent Attributes Dispatch Number: 0 Help String: Help Context: 0 Parameters Receive Number: nItemID Use: VT_I4
Note that there is no procedural code in the server class; that is in the interface classes. Creatable means that the object is not creatable by the client, but can be passed to the client as a return value or through a parameter. Some objects cannot reasonably live outside an owning object. The Microsoft Word Document CoClass is an example: it cannot be created from outside, but can be created by adding one to the Documents object and retrieved from the Documents object (which itself cannot be created from outside, but must be retrieved from the application). For more, read Passing objects outside the server on page 20-17.
Automation types
SQLWindows exposes all SAL data types as standard automation types:
SAL data type String Number VT_BSTR VT_I2, VT_I4, VT_UI1, VT_R4, VT_R8, VT_CY For more, read Setting the automation type for Numbers on page 20-17. Boolean Date/Time Object SafeArray VT_BOOL VT_DATE VT_DISPATCH VT_ARRAY Automation type
20-17
Chapter 20
Automation type VT_I4 VT_UI1 VT_R4 VT_R8 VT_CY long byte float double No C equivalent
C type
The SAL Number data type has greater precision than any of the automation types. In most cases you can use VT_R4 or VT_R8 to pass non-integer values.
Note: You can also set the automation type to the name of an Enum. For more, read Setting the automation type to an Enum name on page 20-22.
You can also select the automation type after generating the class. Items with a Number data type have a Use child item that specifies the corresponding automation type.
You can set the type in these ways: By typing it directly By cycling through the types with the arrow keys on the numeric keypad By selecting it in Coding Assistant
An event can have parameters. You can pass objects as event parameters. For more, read Passing objects outside the server on page 20-17 . An event can have Receive parameters. Events are synchronous; when a server fires an event, control does not return to it until the client has completed processing the event. If a client changes the value of a Receive parameter, that value is visible to the server when control returns to it. 20-18 Developing with SQLWindows
Collections
An Interface of a CoClass fires an event. Clients of the CoClass receive and can process events. An Interface fires an event with:
Call serverCoClassname.eventName([parameters])
where eventName is declared as an event of serverCoClassname. The parameters must match the type of the declaration of eventName.
Collections
A collection is a group of related objects that can be indexed numerically like an array. A collection lets you work with a set of similar things as a single group instead of as independent entities. If your server holds a number of items of the same type, you should implement a collection to enable clients to work with them in a consistent way. To create a collection, define an Interface class with two required methods: Count and Item.
Syntax nCount = Count() oDisp = Item( nItem ) or oDisp = Item( vItem ) Description Returns the number of items in the collection. Returns the item identified by the parameter. You must provide at least an implementation that uses a numeric parameter. Use a Variant parameter for iteration schemes not based on integers.
When SQLWindows finds an interface class with methods with these names and signatures, it knows it is a collection class. Optionally, you can implement Add and Remove methods if they are relevant for the collection. You can automatically generate collection interfaces using the COM Class Wizard (page 20-2).
Example
This is what a collection looks like in the outline:
Interface Class: INumberCollection Description: Attributes GUID: {2B7FFF84-42C5-11D3-9FEB-00104B260106} Help String:
Developing with SQLWindows
20-19
Chapter 20
Help Context: 0 ... Functions Function: Item Description: Attributes Dispatch Number: 0 Help String: Help Context: 0 Returns Number: Parameters Number: nIndex ... Actions ... Function: Count Description: Attributes Dispatch Number: 1 Help String: Help Context: 0 Returns Number: ... Actions ...
Enumerations
An enumeration is a named collection of numeric constants. You use enumerations with COM servers. You code enumerations in the Enumerations section under Constants:
Constants ... Enumerations Enum: EnumName Attributes GUID: {0F2907E0-39FE-11D3-BF61-005004707BD0} Help String: String Help Context: 0001 Item: Itemname_n [=integer_value_n] ...
Enumerations
By default, the first enumerator has a value of 0, and each successive enumerator is one larger than the value of the previous one, unless you explicitly specify a value for a specific enumerator. An Enum can contain duplicate constant values. To refer to an enumerator, specify the Enum name and item name together separated by a period: enumname.name_n
The example above returns the constant value associate with the nth item in the list. You refer to an Enum wherever you can refer to a Number.
Note: You cannot use an Enum name as a data type name.
Example
In this example, the values start at 1 and increment by 1 with Saturday being 7. If no value had been supplied for Sunday, it would have defaulted to 0.
Enum: Day Attributes GUID: {731C2721-49A6-11D3-BF61-005004707BD0} Help String: Day of the week Help Context: 0 Item: Sunday = 1 Item: Monday Item: Tuesday Item: Wednesday Item: Thursday Item: Friday Item: Saturday
In this example, the values of Diamonds, Hearts, Clubs, and Spades are 5, 6, 4, and 5 respectively. No value was specified for Hearts and Spades, so they were assigned default values (incrementing the previous value by 1). Note that 5 is used more than once.
Enum: Suits Attributes GUID: {5741C9AA-49D4-11D3-BF61-005004707BD0} Help String: Suits in a deck of cards Help Context: 0 Item: Diamonds = 5 Item: Hearts Item: Clubs = 4 Item: Spades
20-21
Chapter 20
Dynamic instantiation
When you declare a CoClass variable, SQLWindows creates it at runtime and you can refer to it. However, you can re-initialize it at any time using the new keyword:
Set serverCoClassVar = new serverCoClassName
The new keyword takes as an argument the type of object being created and returns a reference to an object of that type. serverCoClassVar must be a variable of type serverCoClassName.
CoClassVar2 and CoClassVar1 must be the same type, or CoClassVar2 is of a type from which the type of CoClassVar1 derives.
Important: CoClass variables are references, not actual values. After you perform an assignment, both variables refer to the same object and changes made through one variable changes the object itself and that change is visible in any other variable that refers to that object.
Reference counting
If you want to force release of an object safely, assign OBJ_Null to an object variable. This causes the same sequence as going out of scope and causes the referenced object to be freed if there are no other references to it in your application (or from outside, in the case of COM server objects). For more, read Reference counting on page 20-23.
Reference counting
SQLWindows manages object lifetimes through reference counts. When an object variable goes out of scope, the runtime drops the reference count of the referenced object, and if the object is no longer referenced, it is released.
Warning: You can create islands in memory where a set of objects that refer to each other are lost, with no application object referring to any one of them, but each with a non-zero reference count. This storage is not released because SQLWindows does not perform garbage collection.
If you want to force release of an object safely, assign OBJ_Null to an object variable. This causes the same sequence as going out of scope and causes the referenced object to be freed if there are no other references to it in your application (or from outside, in the case of COM server objects). For more, read Setting CoClass variables to null on page 20-22.
SQLWindows takes the information you supply in this function, fills in a COM EXCEPINFO structure, and passes a pointer to it to the client after the Invoke. An EXCEPINFO structure describes an exception that the server raised.
20-23
Chapter 20
SalSetErrorInfo does not halt processing. It should be the last statement that the COM interface function executes.
Parameter nCode Description A number identifying the error. This number should be less than -1000 and negative; if this number is zero or positive, SQLWindows converts the value to E_FAIL, the generic error code. The actual error code returned from the Invoke call is DISP_E_EXCEPTION, meaning that the server raised an exception. sDesc sHelpfileName nHelpContext A textual, human-readable description of the error intended for the end user. The fully qualified drive, path, and file name of a help file with more information about the error. The help context identifier of a topic in the help file. This field is ignored when sHelpfileName is empty.
The COM EXCEPINFO structure has more than these four fields; SQLWindows fills in the remaining fields.
Interface inheritance
Many widely available COM servers use interface inheritance. For example, the Microsoft XML parser, MSXML, has a large number of interfaces that inherit from the IXMLDOMNode interface. To get the most effective use out of COM servers like these, the SQLWindows ActiveX Explorer must create APL files with class hierarchies that reflect the inheritance hierarchy of the server. In Team Developer 3.0, ActiveX Explorer has been enhanced to recognize and preserve interface inheritance in COM servers. For this reason, as well as others, Gupta recommends that you regenerate any existing ActiveX APLs using version 3.0. You can create similar inheritance relationships in the COM servers that you write in SQLWindows 3.0. The COM Class Wizard prompts you for an inherited interface name in the Derived From dropdown whenever you define a new interface. You can also access the Derived From property from the Coding Asssitant, or from the rightclick context menu for interfaces in the outline. With interface inheritance, you have access to any of the methods of any of the parent interfaces. As an example, if you are working with an instance of the MSXML interface IXMLDOMElement, you can also call any of the IXMLDOMNode methods from that instance, since IXMLDOMELement inherits from IXMLDOMNode.
To debug a COM server: 1. 2. 3. Open the server application. Select Project, Build Settings. Check Enable Playback and click OK. If you enable playback mode, you can change Statement Cache Size in the Build Settings to control how often SQLWindows writes statements to disk during recording. A low value may significantly affect performance because of the disk access overhead. If the server exits unexpectedly, any statements in the cache not yet written to disk will not appear in the playback. For this reason, use a low cache
20-25
Chapter 20
size (usually 1) if you need to record the final statement executed before an unexpected exit. 4. 5. Select Debug, Go. Connect to the server from a client application and test. While you test, SQLWindows writes to a log file named with the root name of the application and a *.rec extension. 6. When you exit debug mode the Playback menu item is enabled on the Debug menu. Select it to play back the application. You are prompted for the name of the *.rec file to open. To start the playback, select Debug, Go. During playback you can use animation, breakpoints, step over, step into, and the call stack window.
7.
Note: You cannot use the Variables, Expressions, or Messages windows in playback mode.
8.
To rewind the playback to the beginning of execution, select Debug, Playback Rewind.
You can manually rename a *.rec file. This lets you store different versions of *.rec files.
Warning: Playback files are stamped with an identifying GUID so that they can be correlated with the application file that generated the EXE or DLL. This GUID is regenerated each time you build the COM server, even if the outline has not changed. For this reason, SQLWindows warns you when you open a playback file from an earlier build. If the outline has not actually changed, you can ignore this warning. However, if the outline has changed, you proceed at your own riskexecuting a playback file against an outline which does not match can cause unexpected behavior, including crashing SQLWindows.
Warning: When running a server in debug mode, SQLWindows registers itself as the server instead of the application. When you exit debug mode, SQLWindows re-registers the application as the server. If you exit the application abnormally, SQLWindows cannot reregister the application and you must do so manually by selecting Project, Register Server.
Type information
SQLWindows automatically generates type information for COM servers. For both local servers and in-process servers, SQLWindows embeds the type information in the *.EXE or *.DLL. As well, SQLWindows also generates an external *.TLB file.
Registering servers
You specify the GUID of the type library in the Build Settings. For more, read COM Server Tab and Thread dialog on page 4-18.
Registering servers
Registering a COM server places information about the server in the system registry. Once the server has been registered, applications and development environments can search the registry to determine the servers that are installed. When you build a server *.EXE, SQLWindows adds code internally that interprets standard command-line registration flags: RegServer UnRegServer Embedding The server does whatever COM registration is necessary and exits. The server removes registry information and exits. COM launches servers with this argument. If the server starts and this flag is not present, it means that an end user has run the *.EXE as a standalone application. If the server is not intended to run as a standalone application and this flag is not present, display an error dialog and then terminate the *.EXE. When you build a server *.DLL, SQLWindows makes it self-registering and implements COM registration entry points (DllRegisterServer and DllUnregisterServer) that regsvr32.exe calls.
You can use these menu items so that you do not have to open a DOS prompt during development.
20-27
Chapter 20
Regenerating GUIDs
Select Project, Regenerate GUIDs to generate new GUID values for the COM server.
You want to regenerate GUIDs when: You are starting a new server, but are using existing code You have completed development and you want to assign a fresh set of GUIDs
Internal implementation
SQLWindowss automation incoming interfaces (methods) and outgoing interfaces (events) are dispatch interfaces (dispinterfaces) and are implementations of IDispatch. These interfaces use standard automation types (VT_*) for parameters and returns used with IDispatch::Invoke. SQLWindows automation servers do not support dual interfaces. The SQLWindows runtime environment implements a generic class factory for object instantiation. CoCreateInstance looks for a class factory that knows how to take a progID/GUID, create an instance, and return an IUnknown. At runtime, events are implemented as COM connection points. COM server collections are implemented with IEnumVARIANT.
Threading support
SQLWindows COM servers (both DLLs and EXEs) can use one of two threading models: None, which is a single apartment with a single thread STA (single-threaded apartment) which is multiple single-threaded apartments
Threading support
Introduction to threads
A thread is a path of execution through a section of code in a program and is the smallest unit of execution that Win32 schedules. Threads subdivide the tasks running within a program. A thread consists of a stack, the state of the CPU registers, and an entry in the execution list of the system scheduler. A program executes when the system scheduler gives one of its threads execution control. The scheduler determines which threads should run and when they should run. On a single processor computer, the scheduler can alternate execution among several threads, giving the appearance of concurrent execution. On a multiprocessor computer, the scheduler can move individual threads to different processors to balance the CPU load, executing the threads in parallel. If one thread must wait for an input/output operation to complete, the system gives processor time to another thread. The threads of a process share the virtual address space, global variables, and operating system resources of the process. Each thread in a process operates independently. Threads execute individually and are unaware of the other threads in a process. Thread local storage (TLS) is a Win32 mechanism that allows multiple threads of a process to store data that is unique for each thread. For example, a database server can create a new instance of the same thread each time a user connects. Two instances of the same class created on different threads cannot access each others data. Writing code that can be safely used by multiple threads has become critical because thread overhead is lower than process overhead. Also, threading has only relatively recently become available in Windows for developers to take advantage of to build more efficient applications.
20-29
Chapter 20
Multiple STA
In this model, a process can have multiple apartments, each with its own thread. Process STA STA STA Legend Thread Apartment Object SAL does not support marshalling between threads within an application. SQLWindows does not support MTA (multi-threaded apartment).
Threading support
20-31
Chapter 20
COM server, COM instantiates the object directly in the apartment of the client which provides the most efficient access. Multiple STA client application STA STA
Legend Thread Apartment Object Using multiple STAs has these advantages: Multi-threaded clients are not blocked by serialization You can ensure that different objects run on different threads (thread affinity) Clients have direct references to objects in DLLs MTS is most efficient with the STA model
Build Settings
You control threading through the Build Settings where you can select the threading model (None or Single Threaded Apartment). In the Build Settings, you can also
Threading support
associate a CoClasses to a specific thread. For more, read COM Server Tab and Thread dialog on page 4-18.
20-33
Chapter 20
apartment for it. Each apartment has its own thread-specific and apartment-specific data. The apartments share the runtime environment and the outline. None client CoClass COM marshalling STA client STA 1 CoClass STA 2 CoClass Shared CTD runtime SAL COM EXE STA n
Shared outline
What is MTS?
MTS is a distributed runtime environment for COM objects that provides an infrastructure for running objects across a network. MTS is a combined object request broker (ORB), resource manager, and transaction monitor. MTS provides automatic transaction management, database connection pooling, process isolation, automatic thread-pooling, automatic object instance management, resource sharing, role-based security, transaction monitoring within distributed applications, and more. These services are necessary for scaling server-side components and supporting a substantial number of concurrent client requests. MTS performs all of these services automatically, and without the need for application developers to write special code. A developer can therefore develop server-side components that behave as if only a single client is connected at a time.
MTS architecture
MTS is a DLL surrogate process. DLL server components are loaded into the MTS surrogate (mtx.exe) process along with the MTS Executive (mtxex.dll) as shown below. mtx.exe DLL MTS object DLL MTS object Client Proxy DLL MTS object MTS Executive (mtxex.dll)
You can use SQLWindows to build an MTS object as a DLL. MTS creates proxies for the client. To manage every single instance of a component installed under its control, MTS creates a sibling object called a context object whose interface is exposed by IObjectContext. You use IObjectContext to commit or abort a components transaction, to enable or disable transactions, and to check the security of a components caller. This context contains information about the object's execution environment, such as the identity of the object's creator and, optionally, the transaction encompassing the work of the object. IObjectContext IOrder Transaction ID Object-Creator ID
An MTS object and its associated context object have corresponding lifetimes. MTS creates the context before it creates the MTS object. MTS destroys the context after it destroys the MTS object. MTS coordinates the communication between components and databases over a set of pre-established connections (connection pooling).
20-35
Chapter 20
MTS clients use COM to create MTS components and MTS manages execution of the components. Clients can receive MTS events and get complete/rollback status. An activity is a collection of MTS objects that has a single distributed thread of logical execution. Each MTS object belongs to a single activity. COM+ (the combination of COM with a new version of MTS in Windows 2000) will support these features: Deferred activation, where MTS defers physically creating an object until the client actually calls one of its methods. Early deactivation, where MTS deactivates an object (after a period of inactivity) even while the client still holds a reference to the object. Later, when the client calls a method, MTS creates the object again.
Important: Microsoft refers to deferred activation and early activation collectively as just-intime activation.
IObjectContext
The primary interface that MTS provides for components is the object context via IObjectContext. The object context is implicit and only one is in scope at a time. SQLWindows exposes the IObjectContext through SalMTS* functions.
Function SalMTSSetComplete Description Indicates that the object has successfully completed its work for the transaction. The object is deactivated upon return from the method that first entered the context (stateless object). Indicates that the objects work can never be committed. The object is deactivated upon return from the method that first entered the context (stateless object). Indicates that the objects work is not necessarily done, but that its transactional updates can be committed in their current form (stateful object). Indicates that the objects transactional updates cannot be committed in their current form (stateful object). Creates a new component as part of the current transaction or in a new, independent transaction. Returns TRUE if the component is in a transaction; returns FALSE otherwise. Returns TRUE if declarative security is enabled for the component; returns FALSE otherwise. Returns TRUE if the components caller is a member of the specified role. A role is a symbolic name that defines a class of users for a set of components. Gets the explicit object context (IUnknown).
SalMTSSetAbort
SalMTSEnableCommit
SalMTSGetObjectContext
IObjectControl
You implement the IObjectControl interface when you want to define context-specific initialization and cleanup procedures for your COM objects and specify whether the objects can be recycled. Implementing the IObjectControl interface is optional. You can implement IObjectControl in two ways: Use the COM Class Wizard to automatically generate the class with empty methods to which you add code. Hand code an Interface with this GUID: {51372aec-cae7-11cf-be8100aa00a2fa25}. You can give it any name.
Developing with SQLWindows
20-37
Chapter 20
If you implement the IObjectControl interface in your component, the COM run-time environment automatically calls the IObjectControl methods on your objects at the appropriate times. Only the COM run-time environment can invoke the IObjectControl methods and they are not accessible to an object's clients or to the object itself. When an object supports the IObjectControl interface, COM calls its Activate method once for each time the object is activated. The Activate method is called before any of the object's other methods are called. You can use this method to perform any context-specific initialization an object may require. COM calls the object's Deactivate method each time the object is deactivated. This can be the result of the object returning from a method in which it calls SetComplete or SetAbort, or due to the root of the object's transaction, causing the transaction to complete. You call the Deactivate method to clean up state that you initialized in the Activate method. By implementing the Activate and Deactivate methods, you can create stateless applications. After calling the Deactivate method, the COM run-time environment calls the CanBePooled method to determine whether the deactivated object is placed in an object pool for reuse or if the object is released in the usual way.
Note: While COM currently calls this method, COM does not currently support object pooling. This forward-compatibility encourages developers to use CanBePooled in their applications now in order to benefit from a future release without having to modify their applications later.
Important: If you plan on taking advantage of object pooling when it is available, you must write stateless code and not rely on volatile state because the same object may be used by a different client later.
Methods
Method Activate Description Allows an object to perform context-specific initialization whenever it's activated. This method is called by COM before any other methods are called on the object. Allows an object to notify COM of whether it can be pooled for reuse. Return TRUE if you want the object to be pooled for re-use or FALSE if not. Allows an object to perform whatever cleanup is necessary before it's recycled or destroyed. This method is called by COM whenever an object is deactivated.
CanBePooled
Deactivate
To generate the shared property classes, open Shared Property Manager Type Library in ActiveX Explorer and generate the APL as you would for any ActiveX server. The class names have an MTxSpm prefix. You can then use the APL as a reference for the functions, parameters, and returns.
Sample applications
SQLWindows comes with a sample MTS client application and two MTS server applications. The diagram below shows the multi-tiered architecture of these applications. MTSOledbClient.exe MTSOledbServerClient.dll MTSOledbServer.dll
MTSOledbClient.exe creates an instance of MTSOledbServerClient.dll which creates an instance of MTSOledbServer.dll. The two DLLs are MTS servers. 20-39
Chapter 20
Next, set up MTSOledbServerClient.dll. If you have not used ActiveX Explorer before, please read Using ActiveX Explorer on page 19-9. 1. Open MTSOledbServerClient.apt. You get a message saying that SQLWindows cannot open MTSOledbServer 1.0 Type Library.apl because the COM server does not has a type library APL yet. Click OK. 2. 3. 4. Select Tools, ActiveX Explorer. Select the type library MTSOledbServer 1.0 Type Library and click OK. In the ClassView area of ActiveX Explorer, right click and select Check All Shown, then right click again and select Generate Full. SQLWindows creates an APL and includes it in the application. Close ActiveX Explorer. Select File, Save. Select Project, Build . Select Project, Register Server.
5. 6. 7.
Finally, set up MTSOledbClient.exe 1. Open MTSOledbClient.apt. You get a message saying that SQLWindows cannot open MTSOledbServerClient 1.0 Type Library.apl because the COM server does not has a type library APL yet. Click OK. 2. 3. 4. Select Tools, ActiveX Explorer. Select the type library "MTSOledbServerClient 1.0 Type Library and click OK. In the ClassView area of ActiveX Explorer, right click and select Check All Shown, then right click again and select Generate Full. SQLWindows creates an APL and includes it in the application. Close ActiveX Explorer. Select File, Save.
5.
6.
Setting up MTS
You need to register the two server components with MTS.
Note: Each time you change an MTS-enabled COM server, delete the old MTS package and then reinstall the revised COM server in a new MTS package.
For Windows NT 4.0: 1. 2. 3. 4. 5. 6. 7. 8. Select Start, Programs, Windows NT 4.0 Option Pack, Microsoft Transaction Server, Transaction Server Explorer. Expand the Microsoft Transaction Server tree. Expand the Computers tree and expand your computers tree. Select Packages Installed, right click and select New, Package. In the dialog, click Create an empty package, then give the package a name. Click Next. In the Set Package Identity dialog, select Interactive user - the current logged on user. Click Finish. Expand the Packages Installed tree and expand the tree of the package you just created. Select Components.
20-41
Chapter 20
9.
Right click and select New, Component. In the dialog, click Import component(s) that are already registered.
10. Select these components: MTSOledbServer.CFuncionario and MTSOledbServerClient.CONegCFuncionario. Click Finish. 11. Expand the Components tree. 12. Right click MTSOledbServer.CFuncionario and select Properties.
13. Click the Transaction tab and select Supports transactions. Click OK.
14. Right click MTSOledbServerClient.CONegCFuncionario and select Properties. 15. Click the Transaction tab and select Requires a new transaction. Click OK.
20-43
Chapter 20
To set up MTS on Windows 2000: 1. 2. 3. 4. In the Start menu, choose Settings, Control Panel, Administrative Tools, Component Services. Expand the Component Services tree. Expand the Computers tree and expand your computers tree. Expand COM+ Applications.
5. 6. 7. 8. 9.
Right click COM+ Applications and select New, Application. In the first wizard dialog click Next. Click Create an empty application. Enter the name of the application, select Server Application , and click Next. Select Interactive User, click Next , and then click Finish.
10. Expand the tree of the newly created application. 11. Select Components. 12. Right click and select New, Component. 13. Click Next.
15. Select these two components: MTSOledbServer.CFuncionario and MTSOledbServerClient.CONegCFuncionario. Click Next and then click Finish. 16. Expand the Components tree. 17. Right click MTSOledbServer.CFuncionario and select Properties. 18. Click the Transactions tab and select Supported. Click OK.
20-45
Chapter 20
19. Right click MTSOledbServerClient.CONegCFuncionario and select Properties. 20. Click the Transactions tab and click Requires New . Click OK.
In AddFunction, MTSOledbServerClient.dll calls SalMTSIsInTransaction and displays a dialog letting you know whether it is in a transaction or not. Since you specified that MTSOledbServerClient.dll requires a new transaction in MTS, it is always in a transaction.
Set bTransac = FALSE Set bComplete = SalMTSIsInTransaction(bTransac) If (bComplete AND bTransac) Call SalMessageBox('in transaction -',
Then, MTSOledbServerClient.dll calls SalMTSCreateInstance to create an instance of MTSOledbServer_cFuncionario and calls SalMTSEnableCommit to tell MTS that the objects work is not necessarily finished, but that its transaction updates are consistent and could be committed in their present form. The object maintains its state across calls from the client until it calls SalMTSSetComplete, SalMTSSetAbort, or the transaction ends.
MTSOledbServer_cFuncionario: oFunction ... If SalMTSCreateInstance( oFunction ) Call SalMTSEnableCommit( )
Next, MTSOledbServerClient.dll calls the servers Insert function. If the call succeeds, MTSOledbServerClient.dll calls SalMTSSetComplete. Otherwise, it calls SalMTSSetAbort. Before and after calling SalMTSSetComplete or SalMTSSetAbort, MTSOledbServerClient.dll displays dialogs so that you can follow the progress.
Call oFunction.Insert(pFirstName, pLastName, pMiddleName, pTelephone, pEMail, bReturn) If bReturn Call SalMessageBox( "SetComplete().", "COM Error", MB_Ok ) Set bComplete = SalMTSSetComplete( ) If bComplete Call SalMessageBox("SetComplete().Passed", "COM Error", MB_Ok ) Else Call SalMessageBox("SetComplete().Failed" "COM Error", MB_Ok ) Return 1 Else Call SalMessageBox("SetAbort().", "COM Error", MB_Ok ) Call SalMTSSetAbort( ) Return 0 Else Call SalMessageBox("SalMTSCreateInstance has failed.", "COM Error" , MB_Ok ) Return -1 Return -2
In its Insert function, MTSOledbServer.dll starts by calling SalMTSIsInTransaction and displaying a dialog indicating whether it is in a transaction. Since you set up MTSOledbServer.dll to support transactions in MTS, it runs in a transaction if its creator is running in one; otherwise it does not run in a transaction. In this case, its 20-47
MTSOledbServer.dll creates an OLE DB session and statement and then calls SalMTSDisableCommit. By calling SalMTSDisableCommit, MTSOledbServer.dll tells MTS that the objects work is not finished, and that its transaction updates are inconsistent and cannot be committed in their present form. the object maintains its internal state across calls from the client until it calls SalMTSSetComplete, SalMTSSetAbort, or until the transaction ends.
If SqlCreateSession( hSession , sSession ) Call SalMessageBox('created session - in server comp', 'MTSOledbServer', MB_Ok) If SqlCreateStatement( hSession , hSQL ) Call SalMessageBox(' created stmt - in server comp', 'MTSOledbServer', MB_Ok) Call SalMTSDisableCommit( )
If NOT SqlPrepareAndExecute ( hSQL, " CREATE table myfunction ( first_name char (50) , last_name (50) , midlle_name char (50) , telephone char (50), e_mail char (50)" ) Return FALSE
MTSOledbServer.dll prepares and executes an INSERT statement which uses the function parameters passed to it as values for the new row.
If NOT SqlPrepareAndExecute ( hSQL , " INSERT INTO myfunction ( first_name , last_name , middle_name , telephone , e_mail VALUES ( '" || Robert || "' , '" || John || "' , '" || Jr || "' , '" || Phone_number || "' , '" || EMAIL || "' ) " ) Return FALSE
20-49
Chapter 20
Chapter 21
21-1
Chapter 21
Dynamic linking
DLLs are similar to C libraries. The main difference is that DLLs are linked with the application at runtime, not when you create the application: Linking a library with an application at runtime is called dynamic linking; the library is called a dynamic library Linking a library with an application using a linker is called static linking; the library is called a static library
With static libraries, you combine the code for called functions with the application code when you create the application, but with a DLL you do not combine the code.
21-3
Chapter 21
The table below lists the files for DEMODLLA.APP. The examples in this chapter come from these files.
File name DEMODLLA.APP DEMODLL.C DEMODLL.DEF DEMODLL.DLL DEMODLL.MAK Description SQLWindows application that calls functions in DEMODLL.DLL C source Module definition file Compiled and linked DLL; linked with CDLL.LIB (import library for CDLLI*.DLL) Make file
Notation convention
This chapter uses an asterisk (*) in the name of CDLLI*.DLL. The asterisk represents the first two digits of the version of the software that you are using.
Global Declarations External Functions ... Library name: DEMODLL.DLL ThreadSafe: Yes ... Function: ReturnLPFLOAT Description: Export Ordinal: 27 Returns Boolean: BOOL Parameters Receive Number: LPFLOAT Number: FLOAT Number: FLOAT
For the Library Name, specify the name of the DLL. Set ThreadSafe to Yes if the runtime environment can make calls to the DLL from multiple threads. Set ThreadSafe to No if the runtime environment must pause until the current thread completes. For each function in the DLL that the application calls, specify these items: The name of the function. For more, read Identifying a function on page 21-5 . A description of what the function does (optional). The export ordinal which is a number that identifies a function. For more, read Identifying a function on page 21-5 . The internal data type and the external data type of the return value. Sections later in this chapter explain external data types. If the function does not return anything, you can leave this item blank. The SQLWindows internal data type and the external data type of each parameter that the SQLWindows application passes to the function or that the function returns to the application. Sections later in this chapter explain external data types.
Identifying a function
You have a choice of how you identify the function in the DLL that you want to call. By function name. You spell the function name in the outline exactly as it is declared in the DLL and you specify 0 (the default value) for the export ordinal. By export ordinal. You specify the ordinal number (read Export ordinals on page 21-6) for the function and give the function any name that you want.
21-5
Chapter 21
Export ordinals
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.
The internal data type is a standard SQLWindows data type. Each internal data type corresponds to one or more external data types. The external data type tells SQLWindows the format to use when passing data to the external function and the format to expect when receiving data from the function. The external data types are: Standard C and Windows scalar data types such as LONG, INT, DWORD, and HWND External SAL data types such as HSTRING and HARRAY Structures with one or more of the above data types such as NUMBER and DATETIME
21-7
Chapter 21
Warning: The WINDOWS.H typedefs shown in the table above are for the current version of Windows. The actual underlying definition can be different depending on the version of Windows and the platform. Do not write code that depends on the underlying definitions of these typedefs.
21-9
Chapter 21
SWinCvtNumberToInt( LPNUMBER, LPINT ) SWinCvtNumberToLong( LPNUMBER, LPLONG ) SWinCvtNumberToULong( LPNUMBER, LPULONG ) SWinCvtNumberToWord( LPNUMBER, LPWORD )
Warning: The WINDOWS.H and CBTYPE.H typedefs shown in the table above are for the current version of Windows. The actual underlying definition can be different depending on the version of Windows and the platform. Do not write code that depends on the underlying definitions of these typedefs.
Example
In the example below, the SQLWindows application declares an external function called ReturnDWORD with a Number parameter that has a DWORD external data type. The external function returns the parameter to the SQLWindows application as a DWORD. After calling the external function, the SQLWindows application compares the returned value to the original value to find if it is the same.
External Functions Library name: DEMODLL.DLL Function: ReturnDWORD ... Returns Number: DWORD Parameters Number: DWORD ...
Set dfNum1 = 4123456789 Set dfNum3 = ReturnDWORD( dfNum1 ) If dfNum1 != dfNum3 Call SalMessageBox( 'dfNum1 != dfNum3', 'FAIL', MB_Ok ) Else Set dfStr2 = 'test ReturnDWORD( ) - OK'
The most important thing about the String data type is that you must be aware of its length.
21-11
Chapter 21
Memory management
Strings are fully dynamic and no memory management is required by a SQLWindows developer. Internally, SQLWindows uses buffers in a proprietary format to store and manage String values. The details of these buffers are not important to a SQLWindows developer, but you need to be aware of these things when you call external functions that manipulate Strings: SQLWindows does not keep multiple copies of the same String value in memory. Instead, SQLWindows stores one copy and keeps a reference count for the value (read Reference count example on page 21-12). SQLWindows creates a buffer for a String value the first time that you refer to it, not when the application starts. For more, read Common problem on page 21-14. SQLWindows frees the memory for a String buffer when its reference count drops to zero. The buffer for a String value always has a length, either zero or its length after its last assignment. The length of a buffer for a String value is determined by its most recent assignment. The length of a buffer grows or shrinks as needed. Strings can be any length up to the actual memory available. Depending on the size of a String value's buffer, SQLWindows manages it in a heap through subsegment allocation (read Subsegment allocation on page 21-13) or in the global heap.
SQLWindows does not allocate memory for a String's value until you actually refer to it:
Set str1 = 'select * from' || strTable
After the statement above executes, the reference count for the String value
'select * from' || strTable
is one. If you then assign str1's value to another variable, SQLWindows increments the reference count for the String value to two:
Set str2 = str1
SQLWindows decrements the reference count for the original String value (now only referred to by Str2) and creates a new String value (referred to by str1) and sets its reference count to one.
Subsegment allocation
The current version of Windows has a system-wide limit of 8,192 selectors. Windows uses a selector to refer indirectly to a memory segment. Each call to GlobalAlloc (a Microsoft Windows function that allocates memory from the global heap) uses one selector, which makes GlobalAlloc inappropriate for allocating many small blocks of memory. In fact, the number of available selectors is less than 8,192 because all Windows applications and libraries share the same pool of selectors. Instead of allocating a new segment with GlobalAlloc for each memory request, SQLWindows tries to satisfy as many requests as possible using a single segment. SQLWindows tries to be more efficient than GlobalAlloc by allocating memory in chunks, filling several memory requests using only one selector. SQLWindows expands the segment as needed and returns pointers to areas of memory within the segment. This process of managing memory within a segment is called subsegment allocation.
LPSTR
You use an LPSTR for a null-terminated string.
follow these steps: 1. In the SQLWindows application, set the length of the string's buffer before calling the external function:
Developing with SQLWindows
21-13
Chapter 21
2. 3. 4.
Call the external function in the DLL. The external function writes a 5-byte value to the string. When the function returns, SQLWindows looks for the null terminator to find the end of the value and resets the length of the buffer to five bytes. Five bytes is the length of the buffer the next time you call the external function, unless you explicitly reset the length with SalStrSetBufferLength or assign a new value to the String.
Example
In the example below, the SQLWindows application declares an external function called ShowString with a String parameter that has an LPSTR external data type. The external function displays the String in a message box.
External Functions Library name: DEMODLL.DLL Function: ShowString ... Parameters String: LPSTR ... Call ShowString( 'String in DEMODLLA.APP' )
Common problem
SQLWindows creates a String the first time that you refer to it, not when the application starts. For example, if a SQLWindows application contains this code:
External Functions Library name: TEST.DLL Function: getname ... Parameters Receive String: LPSTR ... Internal Functions Function: MyGetName
then the call to getname in the DLL causes a runtime error because it writes to an invalid buffer (str1 has not been referenced). The solution is to first set str1 to a given length in the SQLWindows application, either by assigning it a value or by calling SalStrSetBufferLength.
LPVOID
An LPVOID data type is like an LPSTR, but SQLWindows ignores null terminators in the value. You use LPVOID for binary data with embedded nulls. For Receive Strings, SQLWindows does not reset the length of an LPVOID when the function returns and does not reclaim unused space.
For example, if you are writing a DLL that needs to make the size of buffer larger than what the application passes to it, you need to use an HSTRING. The HSTRING and LPHSTRING data types are totally implemented in SQLWindows and do not rely on features of Windows or C. SQLWindows ignores null characters in HSTRINGs and LPHSTRINGs. HSTRING means Handle to a String. A handle is a number that indirectly refers to a string. String handles are like file handles or window handles. The actual value of the handle is not important to an application, but SQLWindows knows how to use it to refer to the string. HSTRINGs let you set the length of the buffer, but you must follow a specific protocol in the DLL to use them because SQLWindows dynamically manages them for you. This is why you can only use HSTRING and LPHSTRING with DLLs that you write. In the steps in the protocol, you must call these functions in CDLLI*.DLL:
LPSTR SWinHStringLock( HSTRING, LPLONG ) BOOL SWinInitLPHSTRINGParam( LPHSTRING, LONG ) VOID SWinHStringUnlock( HSTRING )
The next sections explain how you use these functions. Also, read Using CDLLI*.DLL on page 21-31.
21-15
Chapter 21
Reading an HSTRING
A buffer that SQLWindows allocates for a String value does not stay fixed at a specific memory location. The system can move it to make more contiguous memory available. An HSTRING is a handle, not a pointer. The handle is an indirect reference to the String's buffer. To access an HSTRING, you lock its handle. This temporarily fixes the buffer for the String's value and returns a pointer to it (this is called dereferencing). While locked, the system cannot move the buffer. You unlock the memory handle after you finish using the buffer. In the DLL, declare a variable that holds the handle:
HSTRING hString;
Writing an LPHSTRING
To change a String that a SQLWindows application passes to a function in a DLL, you must allocate a new HSTRING. In the SQLWindows application, you must declare the parameter as:
Receive String: LPHSTRING
Returning an HSTRING
In the SQLWindows application, you must declare the return as:
Returns String: HSTRING
The steps you follow in the DLL are almost the same as for writing to a LPHSTRING, with one important addition. In the DLL, declare a variable that holds the handle:
HSTRING hString; Important: Before calling SWinInitLPHSTRINGParam, you must set the HSTRING variable to zero: hString = 0;
21-17
Chapter 21
return hString;
Example
In the example below, the SQLWindows application declares an external function called CombineStrings with two String parameters that have HSTRING external data types and a Receive String parameter that has an LPHSTRING external data type. The external function concatenates the two Strings and returns the combined String.
External Functions Library name: DEMODLL.DLL Function: CombineStrings ... Returns Boolean: BOOL Parameters String: HSTRING String: HSTRING Receive String: LPHSTRING ... Call CombineStrings( 'Hello, ', 'There!', dfStr1 )
lLength
This is what the code does: Finds the length of the two HSTRINGs that the SQLWindows application passed by calling SalStrGetBufferLength in CDLLI*.DLL. This is an example of calling a Sal* function in a DLL. Calls SWinInitLPHSTRINGParam to allocate a new HSTRING that is long enough to hold both of the passed HSTRINGs. Locks the new HSTRING. Locks the first HSTRING that the application passed and copies it to the new HSTRING. Unlocks the first HSTRING that the application passed. Backs up the pointer to the new HSTRING so that the next byte is written at the position of null terminator. Locks the second HSTRING that the application passed and appends it to the new HSTRING. Unlocks the second HSTRING that the application passed. Unlocks the new HSTRING.
21-19
Chapter 21
Call SWinMDArrayDataType to find the data type of the elements in an array. SWinMDArrayDataType returns a pointer to one of these constants: DT_Boolean DT_DateTime DT_Number DT_String DT_LongString
From left to right, these are the arguments for the SWinMDArray* functions: The array handle The value to get or put An index into the array (repeated as many times as necessary for a multidimensional array)
To convert between standard C data types and SQLWindows Number data types in an array, call the SWinCvt* functions in CDLLI*.DLL. For a list of the SWinCvt* functions, read the NUMBER external data type on page 21-9. You can also call SalArray* functions in CDLLI*.DLL (such as SalArrayGetLowerBound ) to manipulate HARRAYs in a DLL that you write. For more, read Using CDLLI*.DLL on page 21-31. Since an HARRAY does not contain actual array values, you cannot use a debugger to examine the values. In the DLL, you can write debugging code that calls SWinArrayGet* functions to retrieve the values.
Example
In the example below, the SQLWindows application declares an external function called ShowArray with a String parameter that has an HARRAY external data type. The SQLWindows application fills an array with values and then calls the ShowArray external function. After calling the external function, the application displays the first element in the array.
External Functions Library name: DEMODLL.DLL Function: ShowArray ... Parameters String: HARRAY ... Set strGlobalStrArray[0] = 'This is the first string'
Set strGlobalStrArray[1] = 'This is the second string' Set strGlobalStrArray[2] = 'This is the third string' Set strGlobalStrArray[3] = 'This is the fourth string' Set strGlobalStrArray[4] = 'This is the fifth string' Call ShowArray( strGlobalStrArray ) Call SalMessageBox( 'strGlobalStrArray[0]: ' || strGlobalStrArray[0], 'ShowArray', MB_Ok )
21-21
Chapter 21
SWinArrayGetHString( hArray, lCurrent, &hString );// Note 3 /* Now that we have the hString, we need to get a pointer to it. */
wsprintf( cBuff, "String Array element %ld: %.50s\n\rContinue?", lCurrent, lpStrItem ); nRet = MessageBox( NULL, cBuff, "ShowArray", MB_YESNO | MB_ICONQUESTION ); if ( nRet == IDNO ) bStopped = TRUE; /* Now unlock the string pointer */
SWinHStringUnlock( hString ); hString = 0; SWinInitLPHSTRINGParam( &hString, 128L ); /* Now hString contains a new string that I can write into. */
lpStrItem = SWinHStringLock( hString, &lLength ); lstrcpy( lpStrItem, "String replaced in ShowArray" ); SWinHStringUnlock( hString ); /* Now we need to put this hString into the array. */ SWinArrayPutHString( hArray, lCurrent, hString ); /* Look at the next element */ lCurrent++; }
This is what the code does: Finds the starting bound and ending bound of the array by calling SalQueryArrayBounds in CDLLI*.DLL. This is an example of calling a Sal* function in a DLL. Displays the bounds of the array by calling SalMessageBox. This is another example of calling a Sal* function in a DLL. Gets an array element into an HSTRING. Locks the HSTRING.
Displays the current value of the array element. Unlocks the HSTRING. Allocates a new HSTRING. Locks the new HSTRING Copies a value to the new HSTRING. Unlocks the new HSTRING with SWinHStringUnlock and copies it into an array element with SWinArrayPutHString.
When you declare an external function parameter with the structPointer data type, SQLWindows bundles the items under it in a C struct and passes a pointer to it to the external function. For example, the Windows function GetClientRect takes two parameters: HWND Window handle
Developing with SQLWindows
21-23
Chapter 21
LPRECT
The four Receive Number data types under structPointer correspond to the four elements of the RECT structure. You can declare the items under a structPointer as receive or non-receive. The code below calls GetClientRect:
Form Window: frmMain ! ! The 4 data fields are defined as Number data types. ! Data Field: dfTop ... Data Field: dfLeft ... Data Field: dfRight ... Data Field: dfBottom ... Pushbutton: pb1 Message Actions On SAM_Click
! ! GetClientRect returns zero in the left and top parameters ! and the width and height of the window in the right and ! bottom parameters. ! Call GetClientRect(frmMain, dfLeft, dfTop, dfRight, dfBottom )
When you use byte, SQLWindows does not null-terminate the value passed to the external function. For example, this code passes "1234ABCD" to the external function:
Set s1 = "ABCD"
21-25
Chapter 21
SQLWindows truncates a value if it is longer than the length you declare for the structPointer element in the SQLWindows application. This code also passes 1234ABCD:
Set s1 = "ABCDxxxxx" Call test( "1234xxxxx", s1 )
When you use byte, SQLWindows does not add a null terminator to the byte array. For example, if the external function changes ABCD to WXYZ, s1 contains WXYZ. Internally, the null terminator follows the Z, but the SQLWindows application does not see it. The byte external data type is like the char external data type, but it handles null terminators differently. Use char to pass a fixed-length string in a structure to an external function. This example passes two 4-byte strings in a structure to an external function:
External Functions Library Name: x.dll Function: test ... Parameters structPointer String: char[4] Receive String: char[4]
When you use char, SQLWindows null terminates the value passed to the external function. For example, this code passes 123-ABC- to the external function (represents a null terminator):
Set s1 = "ABCD" Call test( "1234", s1 )
SQLWindows truncates a value if it is longer than the length you declare for the structPointer element in the SQLWindows application. This code also passes 123ABC-:
Set s1 = "ABCDxxxxx" Call test( "1234xxxxx", s1 )
When you use char, SQLWindows null terminates the string. For example, if the external function changes ABCD to WXYZ, s1 contains WXY-.
Nested structs
You can nest structs. The example below contains 2 rectangles:
structPointer struct
Writing a DLL
This section uses DEMODLL.DLL to show the basics of writing a DLL. You can use the files for DEMODLL.DLL as templates for DLLs that you write.
This section discusses these topics and shows examples, but does not try to teach you how to write a DLL. Use the documentation that comes with your development software or third-party books.
Software tools
To write a DLL, you need the following or its equivalent: Microsoft Visual C++.
21-27
Chapter 21
Files
To create a DLL with functions that you can call from a SQLWindows application, you need these files: A C source file (DEMODLL.C) A module definition file (DEMODLL.DEF) A make file (DEMODLL.MAK)
Writing a DLL
This is what the code does: The EXPORTAPI macro says to define the function as FAR PASCAL, to export the function so that other applications can call it, and to load the data segment when the function is called. Functions in a DLL that other applications call must use the FAR PASCAL calling convention: Use FAR because the functions are called from a different code segment PASCAL creates slightly smaller and faster code
The system calls LIBENTRY at startup to initialize the DLL. In turn, LIBENTRY calls the C function LibMain in your DLL when the DLL is loaded. The LibMain function can perform additional initialization for the DLL. LibMain returns 1 if the initialization is successful.
DESCRIPTION 'Test DLL library' STUB CODE DATA HEAPSIZE 'WINSTUB.EXE' MOVEABLE DISCARDABLE SINGLE MOVEABLE PRELOAD 1024
Here is what the statements do: The LIBRARY keyword says that this is a DLL. The EXPORTS keyword defines the functions called by applications or other DLLs. Give each function in the DLL a unique ordinal entry value (the number after the @ symbol).
21-29
Chapter 21
In the CL command: The c in -Gy2csD tells the compiler to use the PASCAL calling sequence for functions. The w in -Asnw tells the compiler that the stack is not part of the DLLs data segment (SS != DS). The compiler produces an error message when it detects the DLL is trying to pass a stack variable to a function that expects a near pointer. In other words, the w causes a warning message when the DLL tries to create a near pointer to an automatic variable (an automatic variable is one allocated in the stack when the function is called).
The LINK command has five arguments that are separated by commas: The names of the object file to link: DEMODLL.OBJ The name of the final DLL: DEMODLL.DLL The name of the MAP file: DEMODLL.MAP The names of the import libraries and static libraries which for this example are: CBDLL.LIB. Import library for CDLLI*.DLL (this is an example of how you link a DLL to CDLLI*.DLL) SDLLCEW.LIB. C runtime static library for Windows DLLs LIBW.LIB. Import library for Windows functions in KNRL32.DLL, USER32.DLL, GDI32.DLL, and other Windows libraries The name of the module definition file
Writing a DLL
Using CDLLI*.DLL
CDLLI*.DLL comes with SQLWindows and has two types of functions: DLL helper functions Sal* functions
These DLL helper functions are explained in other places in this chapter: SWinCvt* functions for NUMBER data types SWinHStringLock, SWinHStringUnlock, and SWinInitLPHSTRINGParam for HSTRINGs and LPHSTRINGs SWinArray* functions for HARRAY data types
You can call any Sal* function that you can call in a SQLWindows application, such as: SalNumber* functions for NUMBER data types SalDate* functions for DATETIME data types Sal* array functions for HARRAY data types Other Sal* functions as appropriate
To call functions in CDLLI*.DLL: Include CENTURA.H and CBTYPE.H Link CBDLL.LIB (import library for CDLLI*.DLL) with your DLL (read Creating an import library on page 21-31)
21-31
Chapter 21
If you write a DLL that calls function in another DLL, you need to create an import library for the called DLL. You then link your DLL with the import library of the called DLL. At runtime, the system uses the information in an import library to resolve references to external functions. The Microsoft C command IMPLIB creates an import library. For example, the command below creates an import library called IMPORT.LIB for IMPORT.DLL:
IMPLIB IMPORT.DLL
You then link IMPORT.LIB to other *.OBJ files, C libraries, and Windows libraries:
LINK TEST.OBJ + <other *.OBJs and *.LIBs>, TEST.EXE,, IMPORT.LIB, DYNAMIC.DEF
DS and SS are names of registers: The DS (Data Segment) register points to a segment that contains static data. The SS (Stack Segment) register points to the stack. A stack is an area of memory reserved for storing temporary data.
When you use a near pointer in a C program, the pointer can refer to a variable either in static memory or on the stack. The compiler has no way to know whether the near pointer is an offset to DS or SS. This is why C programs normally use the same segment for data and the stack. In other words, DS == SS. However, in a DLL the data segment is the library's own, but the stack segment is the stack of the caller. That is, DS != SS. 21-32 Developing with SQLWindows
Writing a DLL
This function gets the handle of the currently executing object that called the external function in the DLL. If the currently executing object is not a UDV, this function causes a runtime abort. You then pass the handle returned by SalUdvGetCurrentHandle to SWinUdvLock:
LPSTR SWinUdvLock( HUDV );
SWinUdvLock returns the address of the first instance variable defined or inherited by the UDV class. Define a C struct whose first element is a HANDLE and the remainder of which corresponds to the instance variable mapping in the UDV. The pointer returned by SwinUdvLock refers the original SQLWindows data, not to a copy. Changing the data through this pointer changes the data as seen by the SQLWindows application.
21-33
Chapter 21
For example:
typedef struct { HANDLE foohandle; HSTRING strFoo; NUMBER numFoo; } UDVFOO, FAR * LPUDVFOO;
Writing a DLL
Data types
Use these data types for instance variables of a UDV:
SQLWindows Data Type Boolean Date/Time File Handle Long String Number String Sql Handle Window Handle Arrays Examples: Number: numArray[10] Employee: staff[*] UDVs Example: Employee: Manager C struct NUMBER DATETIME HFILE or HANDLE HSTRING NUMBER STRING SQLHANDLE or HANDLE HWND or HANDLE HARRAY C Data Type
Use the HANDLE data type for arrays of file handles, Sql Handles, or window handles. Access elements of an array of handles with these functions:
BOOL SwinArrayGetHandle( HARRAY, LONG, LPHANDLE ); BOOL SwinArrayPutHandle( HARRAY, LONG, HANDLE );
Nested UDVs
When you have a UDV that contains another UDV as a member, the pointer returned by SWinUdvLock can only point to the nested UDVs handle, and not to its instance variables. In this case, you must dereference the handle by calling SalGetUDVData. For example, assume you have a UDV that corresponds to this struct:
typedef struct { HANDLE derivehandle; HSTRING strBase;
21-35
Chapter 21
NUMBER numBase; HANDLE MyFoo; HARRAY haFoo; NUMBER numProduct; } UDVDERIVED, FAR * LPUDVDERIVED;
In the example above (from demodll.c), MyFoo is a nested UDV. To deference MyFoo, define a struct that corresponds to its instance variables:
typedef struct { HANDLE foohandle; HSTRING strFoo; NUMBER numFoo; } UDVFOO, FAR * LPUDVFOO;
Create the new struct and then fill it by calling SalGetUDVData. You can then refer to instance variables in the UDV:
UDVFOO *newudvfoo; newudvfoo = (UDVFOO*)SalGetUDVData((HANDLE)(lpUdvDerived->MyFoo)); SWinCvtNumberToDouble(&newudvfoo->numFoo,&dCurValue);
UDV Arrays
For an array of UDVs, this function returns a reference to a UDV handle:
BOOL FAR CDECL SWinMDArrayGetUdv( HARRAY, LPHUDV, LONG, ... );
The first argument is a handle to the array, the second is the returned reference to the UDV handle, and the third and subsequent parameters are index values for each dimension of the array. After calling this function, pass the handle to SwinUdvLock to get the address of the UDV's instance variables and then directly access them in the DLL.
Using strci*.dll
SQLWindows applications can pass data to and receive data from DLL functions that use C structures by calling functions in strci*.dll. You use strci*.dll when you need more flexibility to manipulate structures than the structPointer external data type provides. For more, read Using C structures (structPointer external data type) on page 21-23. The functions that use C structures are grouped into these categories: Get functions that extract elements from a SQLWindows string buffer
Using strci*.dll
Put functions that insert elements into a SQLWindows string buffer Memory functions that allocate, free, and access global memory
These functions use a string buffer to provide access to C structures. The string buffer is accessed directly by these functions and cannot be used as a normal string within SQLWindows.
Warning: To ensure that the SQLWindows string is large enough to hold the entire structure, call SalStrSetBufferLength to initialize the length of the string. The CStructPut* functions do not detect attempts to write beyond the length of the destination string. Writing beyond the length of the string can cause unpredictable results.
Example Files
These are the example files for strci*.dll:
Name Description
cstructl.apl cstruct.app
Include library that declares external functions in strci*.dll. Sample application that uses strci*.dll.
The first parameter is the SQLWindows buffer for a C structure. The second parameter is the offset, in bytes, of the value to extract. The extracted value is returned. The example below gets a WORD that begins at the eighth byte:
nResult = CStructGetWord( strBuffer, 7 )
The first and second parameters are as described above. The third and fourth parameters contain the number of bytes to extract and the string where the value is
21-37
Chapter 21
stored. The length of the string that has been extracted is returned, including the null terminator. The example below extracts a string that begins at the eighth byte into a string that can hold up to 20 bytes:
nLength = CStructGetString( strBuffer, 7, 20, strExtract ) Important: To extract int data types, call CStructGetWord.
Get Functions
Syntax Description Parameters nResult = CStructGetByte( strBuffer, nOffset ) Extracts a byte from a buffer String: LPVOID Number: LONG Returns Syntax Description Parameters Number: BYTE C structure buffer offset in bytes to extract extracted value
nResult = CStructGetWord( strBuffer, nOffset ) Extracts an unsigned integer from a buffer String: LPVOID Number: LONG C structure buffer offset in bytes to extract extracted value
Number: WORD
nResult = CStructGetLong( strBuffer, nOffset ) Extracts a long from a buffer String: LPVOID Number: LONG C structure buffer offset in bytes to extract extracted value
Number: LONG
nResult = CStructGetFloat( strBuffer, nOffset ) Extracts a float from a buffer String: LPVOID Number: LONG C structure buffer offset in bytes to extract
Using strci*.dll
Number: FLOAT
extracted value
nResult = CStructGetDouble( strBuffer, nOffset Extracts a double from a buffer String: LPVOID Number: LONG C structure buffer offset in bytes to extract extracted value
Number: DOUBLE
nLength = CStructGetString( strBuffer, nOffset, nMaxWidth, strExtract ) Extracts a string from a buffer String: LPVOID Number: LONG Number: LONG Receive String: LPSTR C structure buffer offset in bytes to extract number of bytes to extract where to put extracted string length extracted (including null)
Number: LONG
nFarPointer = CStructGetFarPointer( strBuffer, nOffset ) Extracts a far pointer from a buffer String: LPVOID Number: LONG C structure buffer offset in bytes to extract extracted value
Returns
Number: LONG
The first parameter is a buffer for a C structure. The second parameter is the offset in bytes that indicates where to insert the value. The third parameter is the value to insert. This external data type depends on the function. The example below inserts a WORD beginning at the eighth byte:
CStructPutWord( strBuffer, 7, nValue )
Developing with SQLWindows
21-39
Chapter 21
The first and second parameters are as described above. The third parameter is the maximum number of bytes to insert. The fourth parameter is the null-terminated string to insert. If the maximum number of bytes is less than the length of the string to insert, then the inserted string does not include a null terminator. The example below inserts a string starting at the eighth byte, where up to 20 bytes are allowed:
CStructPutString( strBuffer, 7, 20, strInsert ) Important: To insert int data types, call CStructPutWord.
Put Functions
Syntax Description Parameters bOk = CStructPutByte( strBuffer, nOffset, nInsert ) Inserts a byte into a buffer Receive String: LPVOID Number: LONG Number: BYTE Returns Syntax Description Parameters Boolean: BOOL bOk = CStructPutWord( strBuffer, nOffset, nInsert ) Inserts a word into a buffer Receive String: LPVOID Number: LONG Number: WORD Returns Syntax Description Boolean: BOOL bOk = CStructPutLong( strBuffer, nOffset, nInsert ) Inserts a long into a buffer C structure buffer where to insert (offset in bytes) value to insert C structure buffer where to insert (offset in bytes) value to insert
Using strci*.dll
Parameters
Boolean: BOOL bOk = CStructPutFloat( strBuffer, nOffset, nInsert ) Inserts a float into a buffer Receive String: LPVOID Number: LONG Number: FLOAT C structure buffer where to insert (offset in bytes) value to insert
Boolean: BOOL bOk = CStructPutDouble( strBuffer, nOffset, nInsert ) Inserts a double into a buffer Receive String: LPVOID Number: LONG Number: DOUBLE C structure buffer where to insert (offset in bytes) value to insert
Boolean: BOOL bOk = CStructPutString( strBuffer, nOffset, nMaxWidth, strInsert ) Inserts a string into a buffer Receive String: LPVOID Number: LONG Number: LONG String: LPSTR C structure buffer where to insert (offset in bytes) null-terminated string to insert maximum number of bytes to insert
Boolean: BOOL bOk = CStructPutFarPointer( strBuffer, nOffset, nFarPointer ) Inserts a far pointer into a buffer Receive String: LPVOID Number: LONG Number: LONG C structure buffer where to insert (offset in bytes) value to insert
21-41
Chapter 21
Returns
Boolean: BOOL
2.
3.
Store the pointer to the string in a structure starting at the tenth byte:
Call CStructPutFarPointer( strBuffer, 10, nPointer )
... do something with allocated memory 4. When done using the allocated memory, free it:
Call CStructFreeFarMem( nPointer )
bOk = CStructFreeFarMem ( nFarPointer ) Frees memory allocated by CStructAllocFarMem Number: LONG Boolean: BOOL bOk = CStructCopyToFarMem( nFarPointer, strData, nDataLen ) Copies a string to far memory address of the global memory to free
Using strci*.dll
Parameters
Boolean: BOOL bOk = CStructCopyFromFarMem ( nFarPointer, strData, nDataLen ) Copies data from far memory to a string Number: LONG Receive String: LPVOID Number: LONG address of global memory string to copy number of bytes to copy
Returns
Boolean: BOOL
Copying Buffers
Use the CStructCopyBuffer function to copy data from one buffer to another. The data in the buffers can contain null characters.
Syntax Description Parameters bOk = CStructCopyBuffer(strDest, nDestOffset, strSrc, nSrcOffset, nCopyLen ) Copies data from far memory to a string String: LPVOID Number: LONG String: LPVOID Number: LONG Number: LONG Returns Boolean: BOOL copy to this string (destination) where to copy to in destination string copy from this string (source) where to copy from in source string number of bytes to copy
21-43
Chapter 22
Custom Controls
This chapter shows how to use Microsoft Windows custom controls in SQLWindows applications.
22-1
Chapter 22
Custom Controls
Message actions
1.
Use Coding Assistant or the Controls palette to place a custom control on a parent window and display the Open Control Library dialog. In the lower left of the dialog, make a selection in List Files of Type.
Note: All custom control files are DLLs, but they do not have to have a *.DLL extension.
2. 3. 4.
Select the directory where the custom control is stored in the right list. Select a DLL in the left list. Specify the class name. The author of the custom control supplies the window class name. If you buy a custom control, the documentation tells you the class name.
Important: Some DLLs register window classes for their own use. Be sure to select the class name in the list that you want.
5.
Message actions
SQLWindows sends these messages to a custom control: SAM_Create SAM_CustControlCmd SAM_Destroy SAM_Timer
22-3
Chapter 22
Custom Controls
SAM_CustControlCmd
Custom controls send a WM_COMMAND message to the parent window to tell it that an event happened. For example, when a user clicks a standard push button, BN_CLICK is the notification sent to the parent window. To encapsulate message handling within custom controls, SQLWindows translates WM_COMMAND messages that the parent receives into SAM_CustControlCmd and sends them to the custom control with the notification code in the wParam. For example, the WM_COMMAND message above causes a SAM_CustControlCmd with wParam containing BN_CLICK. SQLWindows ignores any value you Return when you process SAM_CustControlCmd.
Other messages
Custom control objects can send and receive other messages that you can use in SQLWindows applications to operate the control.
You derive other classes that have different styles from a base custom control class, such as deriving a vertical spin control class or a horizontal spin control class from a spin control base class that does not specify orientation. Put all source elements related to the custom control in a library: Custom control class definitions Support class definitions Constants External function declarations
The two main examples in this chapter use a class, wrapper functions, and a library with a custom control. 22-4 Developing with SQLWindows
Attributes
Attributes
The table below describes the attributes for a custom control. Some properties are not relevant for a given custom control. For example, some custom controls do not display a title or use scroll bars. You can change the DLL name and window class name in the Attribute Inspector.
Property Object Name Object Title Current DLL MS Windows Class Name Visible Description The name you use to refer to the custom control in statements. The name that appears as the custom control's title. Some controls use the title to encode settings. In this case, you can enter the settings in the Attribute Inspector. The name of the DLL that defines the window class. The name of the custom control's window class.
If Yes (default), the custom control is visible at runtime. If No, the custom control is not visible at runtime. At runtime, you can change the setting of this property with SalHideWindow and SalShowWindow.
Displays a cascading menu with the custom control's position (top and left) and size (width and height). This is only enabled for custom controls that have an editor interface (explained later in this chapter). If Yes, the custom control has a border. The default is No. If Yes, the custom control has an etched border that makes it appear 3-dimensional. If the display style of the parent form or dialog box is etched, then the border of the custom control is etched. SQLWindows draws an etched border using two shades of gray. The default is No. If Yes, the custom control is created with the WS_VSCROLL window style defined in WINDOWS.H. The default is No. If Yes, the custom control is created with the WS_HSCROLL window style defined in WINDOWS.H. The default is No.
22-5
Chapter 22
Custom Controls
Description If Yes, the custom control behaves like a group box: you can put other child objects in the custom control and SQLWindows does not clip or obscure them. The default is No.
None Group
The user cannot set the focus on the custom control using the Tab key (default). The first or last item in the group gets the focus when the user tabs. The user can then set the focus to an object within the group using the arrow keys. SQLWindows maps this setting to the WS_GROUP windows style defined in WINDOWS.H. The user can set the focus on the custom control with the Tab key. SQLWindows maps this setting to the WS_TABSTOP windows style defined in WINDOWS.H.
Tab
Tile to Parent MS Windows Style MS Windows Extended Style Background Color Text Color Font Name Font Size Font Enhancement
If Yes, the custom control fills the background of the parent object. SQLWindows automatically resizes the custom control when its parent is resized. A window style specific to the custom control. Read the documentation for the custom control. An extended window style specific to the custom control. Read the documentation for the custom control. The background color of the custom control. The color of text in the custom control. The font of text in the custom control. The font size of text in the custom control. The font enhancement (such as italic or bold) of text in the custom control.
Example
To find the interface for a custom control, read the documentation or the source code. This section illustrates an interface by showing the source code for a slider custom control and then the code in a SQLWindows application that uses the slider.
Example
Include file
There are four messages that the SQLWindows application can send to the slider custom control. You need to specify the values for the message numbers in the SQLWindows application. They are defined in the include file as:
#define SLDM_SETPOS WM_USER+101 // // // #define SLDM_GETPOS WM_USER+102 // // // #define SLDM_SETRANGE WM_USER+103 // // // #define SLDM_GETRANGE WM_USER+104 // // // wParam lParam Returns wParam lParam Returns wParam lParam Returns wParam lParam Returns = = = = = = = = = = = = wPos Not used TRUE Not used Not used (WORD)wPos Not used MAKELONG(wMin, wMax); TRUE Not used Not used MAKELONG(wMin, wMax);
The DLL sends a WM_COMMAND message with a notification code when the user moves the slider. You need to define this number in the SQLWindows application. This statement in the include file defines the number:
#define SLDN_POSCHANGE 1
The slider custom control has two styles that you can set. The numbers for these styles are defined in the include file as:
#define SLDS_VERTICAL 0x0001L #define SLDS_HORIZONTAL 0x0002L
You need to specify the window class name in the Attribute Inspector. The DLL defines this string in an include file:
#define SLIDERCLASS "SWSlider"
22-7
Chapter 22
Custom Controls
Window procedure
The window procedure shows how the DLL processes messages. The code fragment below shows the message processing for WM_LBUTTONUP and SLDM_SETPOS:
long FAR PASCAL SliderWndProc( HWND hWnd, unsigned message, WORD wParam, LONG lParam ) { ... switch ( message ) { ... case WM_LBUTTONUP: ... // Code that paints slider in new position ... // Notify parent of thumb position change SendMessage( GetParent( hWnd ), WM_COMMAND, GetWindowWord( hWnd, GWW_ID ), MAKELONG( hWnd, SLDN_POSCHANGE ) ); break; case SLDM_SETPOS: if ( ( wParam < THUMBMIN ) || ( wParam > THUMBMAX ) ) return( 0L ); ... // Code that paints slider in new position ... return( 1L ); case SLDM_GETPOS: ... case SLDM_SETRANGE: ... case SLDM_GETRANGE: ...
The code fragments above show message processing in two directions: the DLL receiving messages and sending messages. When the user moves the slider and releases the mouse button, the DLL gets WM_LBUTTONUP that it processes by repainting the slider and sending the parent WM_COMMAND with the notification code SLDN_POSCHANGE. SQLWindows then sends WM_COMMAND to the custom control itself as SAM_CustControlCmd with the notification code in the wParam. The SQLWindows application message processing is shown later in this chapter. The SQLWindows application can send the DLL SLDM_SETPOS to change the position of the slider. The DLL processes SLDM_SETPOS by repainting the slider and returning one to indicate that the message processing was successful. Note that the DLL returns zero if the range is not valid.
Example
SQLWindows application
This example uses classes and libraries. First, the library declares constants for the messages that the custom control sends or receives:
Global Declarations ... Constants System Number: WM_USER Number: SLDM_SETPOS Number: SLDM_GETPOS Number: SLDM_SETRANGE Number: SLDM_GETRANGE Number: SLDN_POSCHANGE
= = = = = =
+ + + +
The class defines functions that an application calls to operate the slider. In turn, the functions send messages to the slider. This is an example of using wrapper functions to hide the message processing for a custom control.
22-9
Chapter 22
Custom Controls
Note the SAM_CustControlCmd message processing. The message actions check for the SLDN_POSCHANGE notification code and send the control a SAM_ScrollBar message with the SB_ThumbPosition code in the wParam and the position of the slider in the lParam. This is an example of using a class to hide and simplify a custom control's interface; to a developer who creates an instance of the slider, it operates like a standard SQLWindows scroll bar. The application creates an instance of the custom control:
Form Window: frmSlider ... Contents Data Field: dfMin ... Data Field: dfMax ... Data Field: dfPos ... clsSlider: cc1 ... Message Actions On SAM_ScrollBar Set dfPos = lParam Pushbutton: pb1 ... Message Actions On SAM_Click Call cc1.GetRange( cc1, dfMin, dfMax ) Pushbutton: pb4 ... Message Actions On SAM_Click Call cc1.SetRange( cc1, dfMin, dfMax ) Pushbutton: pb2 ... Message Actions On SAM_Click Set dfPos = cc1.GetPos( cc1 ) Pushbutton: pb3 ... Message Actions On SAM_Click Call cc1.SetPos( cc1, dfPos )
The SAM_ScrollBar message actions set dfPos with the value of the lParam. The push buttons call class functions that operate the custom control.
Packing and unpacking numbers in lParam. Many custom controls pass and receive two numbers in the lParam. For example, the SLDM_GETRANGE message returns both the minimum and maximum value in lParam. You can unpack the numbers using SalNumberHigh and SalNumberLow:
Actions Set nRange = SalSendMsg( hWnd, SLDM_GETRANGE, 0, 0 ) Set nMin = SalNumberLow( nRange ) Set nMax = SalNumberHigh( nRange )
22-11
Chapter 22
Custom Controls
Window styles
MS windows style. The window style is a double-word value that SQLWindows passes to a window when it is created. The meaning of the bits in this double-word is defined by Windows. These attribute settings control these bits: WS_BORDER WS_GROUP WS_TABSTOP WS_HSCROLL WS_VSCROLL
For example, setting the Border attribute to Yes sets the WS_BORDER bit. The constant values for the WS_* styles are defined in WINDOWS.H. Some controls use the low-order word of the window style for class-specific styles. For example, the BUTTON class in USER32.EXE uses the BS_* styles in the loworder word to distinguish between a push button, radio button, and check box. You can get the style bits when you process a CREATE message. MS extended windows style. SQLWindows creates custom controls by calling CreateWindowEx with another double-word value that SQLWindows passes to a window when it is created. You also get the extended style bits when you process a CREATE message.
Colors
When a custom control receives a WM_PAINT message, it can send a WM_CTLCOLOR message to get the color that the developer sets:
case WM_PAINT hBrush = ( BRUSH )SendMessage(GetParent( hWnd ), WM_CTLCOLOR, hDC, MAKELONG( hWnd, 0 ) )
The hBrush is the background color. Use GetTextColor( hDC ) instead of GetParent( hWnd ) to get the text color. When a control sends WM_CTLCOLOR, SQLWindows returns the background color that the developer sets and calls SetTextColor with the text color that the developer sets.
Fonts
Custom controls that display text must process WM_GETFONT and WM_SETFONT:
SQLWindows sends WM_GETFONT to a control to find the font name. Process WM_GETFONT by returning the font handle. When a developer sets a font, SQLWindows sends the control WM_SETFONT. Process WM_SETFONT by storing the font handle and using it when the custom control paints text.
Interface
Through the interface, a custom control talks to the SQLWindows application and the application talks to the custom control. You can implement the interface through messages or functions or a combination. Message interface. A custom control DLL can have a message interface that operates the control. A control can both send and receive messages, depending on its nature. For example, if a custom control can display different shapes, it could have a SM_SETSHAPE message that the SQLWindows application can send to it with a number in the wParam that identifies the type of shape. Notification messages. When an event happens that is relevant to the control such as a click, double-click, or selection from list, send a WM_COMMAND message to notify the parent. Use WM_COMMAND as follows: wParam HIWORD( lParam ) LOWORD( lParam ) Window ID of the custom control Window handle of the custom control Notification code
For example, standard buttons send BN_CLICK with WM_COMMAND to tell the application that the user clicked a button. SQLWindows translates WM_COMMAND messages into SAM_CustControlCmd and sends them to the custom control with the notification code in the wParam. Function interface. You can write functions in the DLL that a SQLWindows application calls to operate the custom control. These functions take the custom control window handle as a parameter. Compared to messages, functions have the benefit of parameter type-checking. Also, functions can send messages to a custom control.
Designtime behavior
Some custom control objects need to behave differently at runtime and designtime. Since SQLWindows only sends SAM_Create at runtime, the application can use it to detect that it is in runtime. For example, an animation control does not need to be animated at runtime. When the control receives SAM_Create, send it a message:
22-13
Chapter 22
Custom Controls
If you write a property editor function, you can retrieve the mode from SQLWindows.
Validation
You can call SalValidateSet in the DLL. For more, read Calling SalValidateSet in a DLL on page 22-19. The SalValidateSet function is in SWIN*.DLL. For more about SWIN*.DLL, read Chapter 21, Calling External Functions in DLLs.
SQLWindows calls the function when a SQLWindows developer selects the Properties attribute. The function passes a variable-length data block that contains the settings and a window style back to SQLWindows. SQLWindows stores these in the outline and passes them to the function when a developer chooses the Properties attribute. You can define the format of the settings data block as you need for the custom control.
The include file SWCC.H contains the structures and macros you need to write the function. This is the function prototype:
WORD FAR PASCAL _export _loadds SWCustControlEditor( HWND const hWndDialogParent, LPSTR const lpszClass, HWND const hWndCustom, LPSWCCSETTINGS lpSettings, LPDWORD lpdwStyle; Important: You must specify this function name in the EXPORTS statement in the DLLs *.DEF file. SQLWindows disables the Properties attribute if it cannot find a function named SWCustControlEditor in the DLL. Also, SQLWindows disables the Properties item if the custom control does not have a window.
SQLWindows passes these parameters as input values for the function: hWndDialogParent lpszClass hWndCustom lpSettings The handle of the parent window of the modal dialog that this function creates. The name of the custom control class. The handle of the custom control instance. The current custom control settings. The definition of the LPSWCCSETTINGS struct is:
typedef struct tagSWCCSETTINGS { DWORD dwLength; HGLOBAL hMem; } SWCCSETTINGS; typedef SWCCSETTINGS FAR * LPSWCCSETTINGS;
The dwLength member is the length in bytes of the current settings. This is zero if settings have not been defined. The hMem member is a handle to global memory that contains the current settings. This is null if dwLength is zero. This memory block always contains as many bytes as indicated by dwLength. Define the format of the data that hMem points to as needed for the control. lpdwStyle The current window style bits that are passed to CreateWindow.
22-15
Chapter 22
Custom Controls
SQLWindows passes a pointer to the structure below in the lParam of the WM_CREATE and WM_NCCREATE messages. Use the macros below to get the members in this structure.
typedef struct tagSWCCCREATESTRUCT { int nReserved; UINT fUserMode: 1; // User mode or design mode UINT fUnused: 15; // Unused bits LPSWCCSETTINGS lpSettings; // Custom control settings } SWCCCREATESTRUCT; typedef SWCCCREATESTRUCT FAR* LPSWCCCREATESTRUCT;
In the function, use the macro below to extract the custom control settings from the lParam. The return value is a pointer to the LPSWCCSETTINGS structure. This pointer and the contents of LPSWCCSETTINGS are only valid while processing the CREATE message:
#define SWCCGETCREATESETTINGS( lparam ) \ (((LPSWCCCREATESTRUCT)((LPCREATESTRUCT)lparam)->lpCreateParams)->lp Settings)
Use the macro below to get the mode of the control. The return value is a Boolean: TRUE means the control is in user mode and FALSE means it is in design mode.
#define SWCCGETCREATEMODE( lparam ) ( BOOL ) \ (((LPSWCCCREATESTRUCT)((LPCREATESTRUCT)lparam)->lpCreateParams)->fUserMode) Important: You can only call these macros while processing the WM_CREATE and WM_NCCREATE messages.
You write the code for the function. Display a modal dialog where the user can change the custom control's window style or other settings. After it completes its processing, the function returns these values: lpSettings The new settings. The DLL can reallocate this memory block if necessary to increase its size. SQLWindows stores the data in this memory block in the outline when the function returns SWCC_NEWSETTINGS. Set dwLength to zero if the settings were not defined. The new window style bits. SQLWindows replaces the current window style with this value when the function returns SWCC_NEWSTYLE. Do not include these style bits in dwStyle because SQLWindows controls them: WS_CHILD WS_VSCROLL
lpdwStyle
Validation
WS_HSCROLL WS_TABSTOP WS_GROUP WS_BORDER WS_VISIBLE The return value of this function is one or more of the flags below combined with the '|' operator. The flags tell SQLWindows whether the DLL changed the settings or the style and how to update the custom control window:
#define #define #define #define // // // // // #define SWCC_RECREATEWINDOW 0x0008 // // #define SWCC_ERROR 0xffff // // SWCC_NEWSTYLE SWCC_NEWSETTINGS SWCC_NOCHANGE SWCC_PAINTWINDOW 0x0001 0x0002 0x0000 0x0004 The style changed The settings changed Neither style nor settings changed SQLWindows needs to repaint the custom control window SQLWindows needs to recreate the custom control window An error prevented the function from succeeding (such as out of memory)
Validation
You can enable SAM_Validate processing for a custom control. Call SalValidateSet to use validation with custom controls:
bOk = SalValidateSet( hWndCC, bValState, lParam )
In SQLWindows, changes in focus trigger validation. SalValidateSet tells SQLWindows that the focus is changing to a custom control so that SQLWindows can perform validation as needed.
Important: You must set the Tab stop attribute to Tab or Group so that the custom control can receive the focus.
You call SalValidateSet when the user tries to move the focus to the custom control. The parameters are: hWndCC bValState Window handle of the custom control Whether to validate this custom control when it loses the focus: If TRUE, SQLWindows sends SAM_Validate when the custom control loses the focus If FALSE, SQLWindows does not send SAM_Validate when the custom control loses the focus
22-17
Chapter 22
Custom Controls
lParam
Specify TRUE in bValState for controls that behave like editable objects. When bValState is TRUE, SQLWindows sends SAM_Validate to the object losing the focus: If validation succeeds, SalValidateSet returns TRUE and SQLWindows moves the focus to the custom control. Later, when the user moves the focus off the custom control, SQLWindows sends it SAM_Validate if its field edit flag is set to TRUE. If validation fails, SalValidateSet returns FALSE and SQLWindows sets the focus to the invalid object.
Validation
If wParam = EN_CHANGE Call SalSetFieldEdit( hWndItem, TRUE ) On SAM_Validate Call SalGetWindowText( hWndItem, sText, 1000 ) If sText = '' Call SalMessageBox( 'You must enter data in this field', 'Validation Error', MB_Ok ) Return VALIDATE_Cancel Else Return VALIDATE_Ok
The example below shows the message actions for a non-editable custom control:
On WM_SETFOCUS ! Sent after a window gets the input focus ! Send SAM_Validate to the object losing the focus If NOT SalValidateSet( hWndItem, FALSE, 0 ) ! If validation fails, return 0 so that Windows does not process ! WM_SETFOCUS further (which moves the focus) Return 0
22-19
Chapter 23
23-1
Chapter 23
Symbol scoping
This section explains SQLWindows' symbol name resolution rules. A symbol is a name that identifies an object, variable, constant, function, or class. The application elements where you can define symbols are: Global declarations Form windows Table windows Dialog boxes MDI windows Functions Classes
The part of an application where you can refer to a symbol using only its name is called its scope. In SQLWindows, the scope of a symbol is the application element that defines the symbol. The scope of a symbol includes all application elements in the defining element, nested to any level. For example, the scope of a form's window variable (such as num1) is the form itself and the form's child windows. Columns in the child table are also in num1's scope because the columns are in the defining form, nested 2 levels down.
External references
To refer to a symbol outside of its scope, you must make an external reference. An external reference refers to either: A variable, object, or function defined in a top-level window (at any level) from outside that top-level window A variable, object, or function defined in an MDI window from outside that MDI window
To make an external reference, you must qualify it by prefixing other names to the symbol name. Sections later in this chapter explain how to qualify references.
Symbol scoping
hWnd3.Form3 Function: F3 Number: num3 Actions If hWndForm = hWnd3 Set hWnd33.Form3.num3 = 33 Else Call hWnd3.Form3.F3( 33 )
hWnd33.Form3 Function: F3 Number: num3 Actions If hWndForm = hWnd3 Set hWnd33.Form3.num3 = 33 Else Call hWnd3.Form3.F3( 33 )
23-3
Chapter 23
In the diagram on the previous page, all external references are qualified references, but not all qualified references are external references. For example, this statement in Form1:
Set ChildTable1.numT = 9
is qualified, but is not external because it refers to a symbol nested in the current toplevel window. This means that there are two times when you must use qualified references: To make an external reference To refer to a child in its parent
Note: If the current context is a class, then its containing context is its direct base class.
This minimizes the times that you must qualify references. For example, you do not need to qualify a reference to a form window variable that you make from a child table column defined in the form window.
Symbol scoping
The scope of a derived class is logically contained in its base class for purposes of symbol resolution. Therefore, you do not need to qualify references in a derived class to access variables or functions defined in its base classes.
23-5
Chapter 23
The diagram below shows graphically how you can nest application elements: Application Internal Function Template Window Function Child Table Window Function
MDI Window Window Function Template Window Function Child Table Window Function
Unqualified references
Unqualified references
In an unqualified (or simple) reference, you only specify the name of the symbol.
Examples
Example strTemp MyPrint( ) dfStatus strArray[2] MSG_1 Type variable function object array element constant The square brackets used to access array elements are not part of the reference References to constants are always unqualified because constants are always global (you can only define constants in the global declarations section) The parentheses used to call a function are not part of the reference Comments
Qualified references
You use a qualified reference for a variable, object, or function in a top-level window (or MDI window) other than the current top-level window (or MDI window).
23-7
Chapter 23
In a qualified reference, you add a prefix that contains one or two other names to a symbol. You separate the names with periods:
hWnd1.frm1.df1
The names that you can use in the prefix are: Object names (template, MDI window, user-defined window, or user-defined variable) Window handles Class names
You combine these names in different ways to make these types of references: Object-qualified Fully object-qualified Handle-qualified Class-qualified Fully class-qualified
Note that an external reference is always a qualified reference, but that a qualified reference is not always an external reference.
Object-qualified reference
In an object-qualified reference, you qualify a symbol with an object name.
Syntax
object.symbol
where object is the name of the object that defines the symbol. If object is an instance of a class, then the object's class can define or inherit the symbol. The prefix object can be a: Object-qualified reference
Qualified references
Binding
An object-qualified reference is always early bound.
Examples
frmMain.strTemp frmCustomer.dfName frmMain.strArray[2] childtable1.colSalary frmMain.Print( ) frmMain.tbl1.col hWnd.frm1.tbl1.col
23-9
Chapter 23
You must qualify the reference because it is in the form window and is not in the scope of the child variable. In the example below, a form window makes a reference to a window variable defined in its child table window:
Form Window: frm1 ... Contents Data Field: df1 Child Table: tblChild ... Window Variables String: strInfo Window Variables Message Actions On SAM_Create Set df1 = tblChild.strInfo
Use an object-qualified reference in MDI windows to refer to: An MDI window's child form window if there is only one instance of the child form A child table window of an MDI window's child form window
Syntax
handle.object.symbol
handle A window handle or an expression that evaluates to a window handle. object The name of the object that defines the symbol. If object is an instance of a class, the object's class can define or inherit the symbol.
Qualified references
Errors
You get an error at runtime if handle does not refer to an instance of object.
Binding
A fully object-qualified reference is always early bound.
Examples
hWnd.form.var (hWndArray[1]).form.var hWndChildTbl.(ParentForm.ChildTable).var
Two windows exist with identical names (frm1) and identically-named variables (dfName). SQLWindows cannot determine the copy of dfName to which the dialog box dlg1 refers:
Dialog Box: dlg1 ... Window Variables String: strName Message Actions On SAM_Create Set strName = frm1.dfName
To eliminate the ambiguity, specify: The window handle with which the variable is associated (hWnd1 or hWnd2) The template name with which the variable is associated (frm1)
For example:
Message Actions On SAM_Create
23-11
Chapter 23
Handle-qualified reference
Important: This type of reference is provided for compatibility with existing applications. Gupta Technologies LLC discourages its use because it can make application code unstructured and difficult to maintain. Instead, use late-bound function calls.
In a handle-qualified reference, you qualify a symbol with a window handle. The compiler accepts handle-qualified references even when the design-time setting Require Qualified External References is set to No.
Syntax
handle.symbol
handle A window handle or an expression that evaluates to a window handle. symbol This must be a child object or variable name. This cannot be a window parameter.
Errors
You get an error when you compile unless all symbols with the same name in all templates (top-level windows), MDI windows, and child tables are the same type and the same underlying data type. You get an error at runtime if the object to which handle refers does not contain the symbol.
Binding
A handle-qualified reference is always late bound.
Examples
hWnd.dfEmployee (hWndArray[1]).dfEmp
Qualified references
Two windows exist with identical names (frm1) and identically-named variables (dfName). SQLWindows cannot determine the copy of dfName to which the dialog box dlg1 refers:
Dialog Box: dlg1 ... Window Variables String: strName Message Actions On SAM_Create Set strName = dfName
To eliminate the ambiguity, specify the window handle with which the variable is associated (hWnd1 or hWnd2).
Message Actions On SAM_Create Set strName = hWnd2.dfName
Class-qualified reference
In a class-qualified reference, you qualify a symbol with a class name. You can only make this type of reference in a class that inherits or defines the symbol. Chapter 21, Object-Oriented Programming, shows how to use class-qualified references.
Syntax
class.symbol
where class is the name of a class that defines or inherits the symbol.
Binding
A class-qualified reference is early bound unless you specify two periods before a function name: 23-13
Chapter 23
cls1..func1( )
Examples
clsDbField.bIsKeyField clsDbForm.print( ) clsDbForm..print( )
Syntax
handle.class.symbol
handle A window handle or an expression that evaluates to a window handle. class The name of a class that defines or inherits the symbol. The window handle that you specify must refer to an object that is an instance of class.
Binding
A fully class-qualified reference is early bound unless you specify two periods before a function name:
obj1.cls1..func1( )
Examples
hWnd.clsDbField.bIsKey (hWnd[1]).clsDbF.bKey hWnd.clsDbF..Insert( )
Design-time settings
There are three items in the Runtime tab of the Properties dialog (page 4-9) that are related to external references: Fully Qualified External References Reject Multiple Window Instances
Design-time settings
If both of these conditions are not true, then you get errors at runtime or the application misbehaves. These problems are difficult to diagnose. This setting sometimes determines how SQLWindows interprets parent object names, as the table below explains:
Reference hWnd.Variable Object.Variable Explanation The compiler always accepts no matter what the setting The compiler accepts if you make the reference in the object's scope no matter what the setting If you make the reference outside the object's scope, the compiler only accepts it if both of the following are true: Fully Qualified External References is off The objects name is unique
23-15
Chapter 23
For example, when you turn on Enable Runtime Checks Of External References, SQLWindows performs these checks for these expressions:
hWnd.frm1.var hWnd.frm1.fun( ) hWnd.cls1.var hWnd.cls1.fun( ) hWnd.cls1..fun( )
hWnd refers to a window whose type is frm1 hWnd refers to a window whose type is frm1 hWnd refers to a window which is an instance of the class named cls1 hWnd refers to a window which is an instance of the class named cls1 hWnd refers to a window which is an instance of the class named cls1 or is an instance of a class derived from cls1
Gupta Technologies LLC recommends that you turn on this option during application development and testing to help find programming errors. This option generates extra code which slightly impacts the performance and size of an application, so turn off runtime checks for production applications (before making an *.EXE). You can enable runtime checks to help diagnose incorrect behavior in production applications. Usually you make an *.EXE with runtime checks enabled only if an application misbehaves. Such an *.EXE causes an error message if there is a programming error that assigns an incorrect value to a window handle.
Advanced references
You can make references with more than one qualifying object name.
Nested objects
To make a global reference (from an unrelated scope) to something nested more than one level inside another object, you must specify all its parents names. For example:
mdi1.mdiform1.df1 frmMain.tbl1.col1 mdi1.mdiform1.tbl1.num1
Advanced references
The compiler requires that any qualifier to the left of an opening parentheses, if any, be a window handle expression. The example below does not require parentheses because hWndFrmMain refers to the object to which it is adjacent, frmMain:
hWndFrmMain.frmMain.tbl1.col1
is only accepted when the reference is in the scope of tbl1 (for example, when tbl1 is visible from the location of the reference). You can group more than two object names with casting parentheses:
hWndCol1.(frmMain.tbl1.col1).num1
The example above, if accepted by the compiler, implies that col1 must be a class object that inherits the instance variable num1. We know this because column objects cannot themselves define variables. The compiler does not accept this example because the element to the left of the parentheses must be a window handle expression and mdi1 is not:
(mdi1.(mdiform1.tbl1)).num1
Illegal!
This looks like a valid reference, but the compiler rejects it because it cannot tell which instance of the child form window the code refers to because it only specifies the MDI windows handle and there can be more than one instance of the same child form window:
hWndMdi1.mdi1.mdiChildForm1.df1
Illegal!
Make the reference valid by specifying a handle to the specific child form window:
hWndMdiChildForm1.(mdi1.mdiChildForm1).df1
This example shows a common use of an array reference where the array contains handles to all the active instances of an MDI child form window template:
hWndChildForms[2].(mdi1.mdiChildForm1).df1
23-17
Glossary
accelerator: A keyboard shortcut for choosing a menu item or pressing a push button. An accelerator causes an action. Alt+<char>, Ctrl+<char>, and Shift+<char> are examples. Contrast with mnemonic. accessor method: A method that sets or retrieves the value of a property. Most properties have a pair of accessor methods. Properties that are read-only may have only one accessor method. ActiveX: Microsoft's brand name for a set of Windows technologies and services that enable interoperability using COM. ActiveX control: A lightweight, in-process object with support for properties, property pages, methods, type information, and events. An ActiveX control typically implements IDispatch and type information, and can have events. An ActiveX control has an *.OCX extension. ambient properties: Exposed properties that define a container's surroundings, including default colors, fonts, and alignment. animate: A menu command that highlights each item in the outline as it executes. apartment model: A threading model that can be used only on the thread that created it. API (Application Programming Interface): A set of functions that a program uses to access a service. applet: A Java program that runs in the context of a Java-capable browser. Java applets extend the content of Web pages beyond just graphics and text. application: A SQLWindows program written for a user that applies to the user's work.
-1
Glossary
Application Actions: A section in the outline that contains procedural code that executes when the application receives messages. argument: See parameter. array: A set of elements of the same data type. You refer to an element in an array using a subscript (index). automation: An ActiveX mechanism for applications, development tools, and macro languages to control objects by setting and reading their properties, by invoking their methods, and by detecting their events. backend: See database server. base class: The class from which a given class is derived. A derived class inherits its base class' data structure and behavior. Also called superclass, ancestor, and parent class. Contrast with derived class. See also class, inheritance and OOP. behavior: The set of operations that an object can perform on its data. bind variable: A variable that associates data to a SQL statement. You can use bind variables in the VALUES clause of an INSERT statement, in a WHERE clause, or in the SET clause of an UPDATE statement. Bind variables associate data in an application to the database. binding: Associating a symbol with an object. See also early binding and late binding. bitmap: A series of bits where one or more bits correspond to each display pixel. For a monochrome bitmap, 1 bit corresponds to 1 pixel. In a gray-scale or color bitmap, multiple bits correspond to each pixel to represent shades of gray or color. bitwise: A bit-by-bit comparison of identically positioned bits in two numeric expressions. Boolean operator: An operator (AND, OR, NOT) that combines logical values to produce a result of TRUE or FALSE. Also called logical operator. breakpoint: A statement in an application where execution suspends so you can set and examine variables. browse: A mode where a user queries a database without necessarily making additions or changes. In a browsing application, a user needs to examine data before deciding what to do with it. A browsing application lets the user scroll forward and backward through data.
-2
browser: An application that knows how to interpret and display documents that it finds on the World-Wide Web. buffer: A memory area that holds data during input/output operations. cache: An area of memory that holds table window row data. call by reference: A parameter-passing technique where a function has the original value of a parameter, not a local copy. Contrast with call by value. call by value: A parameter-passing technique where a function has a copy of a parameter's value, but not the original value. The called function cannot change the original value; it can only change the temporary copy. Contrast with call by reference. case sensitive: A condition in which data must be entered in a specific lowercase, uppercase, or mixed-case format. cast: An action that converts an object from one type or class to another. cell: The intersection of a row and a column in a table window. CGI (Common Gateway Interface): A standard that specifies how Web servers communicate with other programs running on the server. With CGI, the Web server can start a program and pass it user-specific data (such as what host the user is connecting from or input the user has supplied using HTML form syntax). The program then processes that data and the server passes the programs response back to the Web browser. character: A letter, digit, or special character (such as punctuation mark) that represents data. class: A template that specifies the data and behavior of an object. Objects are created at run time and are instances of a class, while classes are a static description of a set of objects. You create classes in hierarchies, and inheritance lets you pass the data and behavior in one class down the hierarchy. See also base class, derived class, inheritance, object, and OOP. class function: A function that you write in a class definition. A class function is the implementation of an object's behavior. An object's functions are shared by all objects in the same class. Also called method or member function. class variable: Stores data that is shared by all objects in a class. Contrast with instance variable.
-3
Glossary
client: A computer that accesses shared resources on other computers running as servers on the network. Also called front-end or requester. See also: server and database server. The term client is also used to refer to applications in DDE and Report Builder. Clipboard: The holding place for what was last cut or copied. Data on the Clipboard can be inserted (pasted) into other Windows applications. code page: An internal table that the operating system uses to map symbols (letters, numbers, and punctuation characters) to a character number. Different code pages provide support for the character sets used in different countries. For example: Unicode. Coding Assistant: Displays the items that you can add at the current location in the outline. collapse: Hiding lower outline levels. collection: In COM, a group of related objects that can be indexed, either numerically like an array or by name. A collection lets you work with a set of similar things as a single group instead of as independent entities. column: In a table window, a complete vertical line of cells. See also table window and row. In a database, a data value that describes one characteristic of an entity. A column is the smallest unit of data that can be referred to in a row. A column contains one unit of data in a row of a table. A column has a name and a data type. Sometimes called field or attribute. See also database and row. column identifier: A columns position in the outline or its order of creation. It is a permanent, non-changeable number associated with a table window column. You specify one for the first column, two for the second column, and so on. A columns identifier does not change if you or the user changes the order of columns in a table window. Contrast with column position. column position: The visual position of a column. It is a relative, changeable number associated with a table window column. The first (left-most) column in a table window is one, the column to its immediate right is two, and so on. If you or the user changes the order of the columns in a table window, their column positions change to reflect the visual order. Contrast with column identifier. COM (Component Object Model): A specification that defines the binary-level compatibility and interoperability of components.
-4
comment: A non-executing line in an application that has an exclamation mark at the beginning of the line. Comments document what the application is doing. component: A distinct unit of code that delivers a well-specified set of services. An ActiveX component is a runtime instance of code, memory, resources, and executing state, either as a process or a DLL, that uses or provides ActiveX interfaces. constant: An unchanging, named value. Contrast with variable. contents: The objects in form windows, table windows, dialog boxes, MDI windows, and toolbars. context: State that is implicitly associated with a given MTS object. Context contains information about the object's execution environment, such as the identity of the object's creator and, optionally, the transaction encompassing the work of the object. The MTS run-time environment manages a context for each object. context row: The row whose column values are referenced when used as variables. This is usually the row with the focus. control: An object that has its own set of recognized properties and events. Controls can receive user input, display output, and trigger event procedures. You can manipulate most controls using methods. Some controls are interactive (responsive to user actions), while others are static (accessible only through code). cookies: A means by which, under the HTTP protocol, a server or a script can maintain state or status information on the client computer. A cookie can include information such as the way a Web page is customized or how a visitor shopped on a Web site, or it can be used to track repeat visits. creator: In MTS, a client that creates an object provided by a component (using CreateObject, CoCreateInstance, or CreateInstance). When a client creates an object, it is given an object reference that can be used to call the methods of that object. CSS (Cascading Style Sheets): Formatting descriptions that provide control over presentation and layout of HTML and XML elements. cursor: A work space in memory that is used for processing a SQL command. This work space contains the return code, number of rows, error position, number of select list items, number of program variables, rollback flag, and the command result. A cursor is part of a Sql Handle. Cursor is also a name for a mouse pointer.
Developing with SQLWindows
-5
Glossary
data binding: Associating an object in an application to a data source. data type: A characteristic of a variable or constant that determines the type of data it holds and how you manipulate it. database: A collection of interrelated or independent pieces of information stored together without unnecessary redundancy. Client applications can read and write a database. database server: A DBMS that a user interacts with through a client application on the same or a different computer. Also called backend or engine. DBMS (database management system): A software system that manages the creation, organization, and modification of a database and access to data stored within it. A DBMS provides centralized control, data independence, and complex physical structures for efficient access, integrity, recovery, concurrency, and security. DCOM (Distributed COM): DCOM is an object protocol that enables ActiveX components to communicate directly with each other across a network. DCOM is language neutral, so any language that produces ActiveX components can also produce DCOM applications. derived class: A class defined from an existing class (its base class). A derived class inherits its base class' data structure and behavior and it can change (override) the inherited data structure and behavior. It can also add its own data structure and behavior. All of the derived class' data structure and behavior-changed, new, and inherited-is inherited by its own derived classes. Also called descendant, subclass, and child class. Contrast with base class. See also inheritance and OOP. design window: A form window, table window, or dialog box at designtime. You use the Window Editor to add child objects to a design window. designtime: An environment in which you can create and change an application. Contrast with runtime. DHTML (Dynamic HTML): A technology that enables interactive HTML documents that do not rely on server-side programs or complicated sets of HTML pages to achieve special effects. DHTML achieves these effects by reformatting and redisplaying the changes on the user's computer, instead of reloading a document or loading a new document. This frees the user from having to wait for text and data to make a round-trip to and from the server. DHTML is made up of HTML 4.0, data binding, the Document Object Model (DOM), and Cascading Style Sheets (CSS). -6
Developing with SQLWindows
dialog box: A single-function window that displays data and messages and accepts input. See also modal dialog box, modeless dialog box, and system modal dialog box. diamond: The symbol that represents the beginning of an item in the outline. DIB (Device-Independent Bitmap): Windows SDK functions that define and manipulate color bitmaps so that they can be displayed appropriately on a device with a given resolution, regardless of the method used by the device to represent color in memory. disabled: A menu item or menu that cannot be chosen; the menu item or menu title appears dimmed or gray. DLL (Dynamic Link Library): A program library written in C or assembler that contains related functions of compiled code. The functions in a DLL are not read until runtime (dynamic linking). DNA (Distributed interNet Applications): A Microsoft framework for building three-tier, component-based applications that can be delivered over a network. DOM (Document Object Model): The standard maintained by the W3C (World Wide Web Consortium) that specifies how the content, structure, and appearance of Web documents can be updated programmatically with scripts or other programs. The object model for XML matches the Document Object Model for HTML so that script writers can easily learn XML programming. The XML DOM provides a simple means of reading and writing data to and from an XML tree structure. domain: In Windows NT, a group of computers and servers that share a common Security Accounts Manager (SAM) database and allow a user to log on to any resource in the domain with a single user ID and password. Contrast with workgroup. early binding: Associating a symbol with an object at compile-time. Also called static binding. Contrast with late binding. See also bind elevator box: See scroll box. embedding: To insert an object completely within an ActiveX client application. An embedded object contains a presentation format (bitmap or MetaFile), a data structure that identifies the server, and the native data provided by the server. A user can edit an embedded object directly in the client application. Editing an
-7
Glossary
embedded object starts the server and sends the native data back to that server. Gupta SQLWindows stores an embedded object as a blob of raw bytes in the application outline. encapsulation: This term has two related meanings: Combining data and procedures together in a class or object Making the behavior of a class or object visible while hiding the details of its implementation
Encapsulation lets a class or object provide a service in any way, without requiring cooperation or knowledge by other program elements. This objectoriented programming characteristic makes applications easier to maintain and extend. Also called data hiding or information hiding. See also class and OOP. engine: See database server. event: An asynchronous notification from an object that something has happened. event-driven program: A program that responds to user input by repeatedly checking for events. An event-driven program does nothing until it detects an event such as a mouse click. Program actions are based on events caused by the user, rather than a fixed script. exception: An error condition that prevents the normal flow of instructions. expand: Displaying lower outline levels. expression: An item or a combination of items and operators that yield a single value. An example is an arithmetic expression with operators such as + or - that yields the result of performing the operation. external function: A function in a DLL that you call from a SQLWindows application. external reference: A reference to a variable, an object, or a function in an application window (top-level window or MDI window) other than the current application window. extranet: A Web server that handles confidential intranet content and communications that are available on the public Internet to, for example, business partners and customers. fetch: To retrieve one or more rows of data from a database.
-8
File Handle: A data type that identifies an open file. firewall: A system that prevents unauthorized access to or from a private network. Firewalls can be implemented in both hardware and software, or a combination of both. All messages entering or leaving the network pass through the firewall, which examines each message and blocks those that do not meet specified security criteria. flag: A variable whose value indicates a condition. focus: See input focus. focus frame: A movable, dark border that highlights a row where the insertion bar is positioned. form window: A top-level window used for data entry and display. format: The appearance of data. Currency, percentage, decimal, date, time, invisible, numbers, and unformatted are examples. frontend: See client. FTP (File Transfer Protocol): You use FTP to connect to a computer on the Internet using an FTP program on your local computer, browse through files available on that computer, and then download or upload files. function: A routine that performs a task that needs to be done several times but at different places in an application. SQLWindows has 5 types of functions: built-in system functions, internal functions, window functions, external functions, and class functions. GDI (Graphics Device Interface): Windows SDK functions that perform deviceindependent graphics operations such as creating lines, text, and bitmaps on different output devices. GIF (Graphics Interchange Format): A Compuserve graphics format used to transfer graphics between different applications and different types of computers. GIF stores images in a bitmap (raster) format. global: A variable, function, or object known in all parts of an application. Constants are always global. See also local and scope. global declarations: A section in the outline that contains elements that are recognized in all parts of the application. grid: A pattern used to align objects in a design window. group separator: Separates two contiguous sets of radio buttons.
Developing with SQLWindows
-9
Glossary
GUI (Graphical User Interface): A graphics-based user interface with windows, icons, pull-down menus, a pointer, and a mouse. Microsoft Windows is an example of graphical user interfaces. GUID (Globally Unique IDentifier): A 128-bit number that is generated automatically and used to refer to a resource, component, directory entry, or other type of entity. Guaranteed to be unique. Pronounced either guid (rhymes with squid) or goo-id. handle: A number that identifies a window, a database connection, or an open file. An application gets a handle by calling a Sal* or Sql* function. The application then uses the handle in other functions to refer to the window, database connection, or file. An application does not know the actual value of the handle. hierarchy: The relationship between classes. See also base class, derived class, inheritance, and OOP. HTML (Hypertext Markup Language): A system of marking up, or tagging, a document so it can be published on the World-Wide Web. Using a generic markup language allows a single text file to be displayed on multiple computer platforms by many types of display software, or browsers. You incorporate HTML in a document to define the function (as distinct from the appearance) of different text elements. The appearance of these text elements is not defined at the authoring stage; a browser decides how to display the text elements. An HTML document can contain hypermedia such as pictures, graphics, sounds, and animation. HTTP (Hypertext Transport Protocol): A set of messages and replies a client and server use to communicate during a hypertext link. hWndForm: A variable that contains the handle of the parent. hWndItem: A variable that contains the handle of a child object. hypertext: Text containing links that, when clicked by a user, jumps to a different place, either in the same document or in another. icon: An image that represents an application or window. in-place activation: Activating an object provided by an ActiveX server. By doubleclicking the object, a user can interact with the application supplying the object without switching to a different application or window. The menus and toolbars of the server application merge with those of the application that contains the object. Also called visual editing.
-10
in-process server: An ActiveX server that runs in a client application's process space, usually as a DLL. inheritance: Arranging classes in a hierarchy so that classes can share the data and behavior of other classes without duplicating the code. A derived class automatically includes the data and behavior of one or more base classes. Derived classes can add their own data and behavior and can redefine inherited data and behavior. A derived class can inherit from one base class (single inheritance) or more than one base class (multiple inheritance). See also base class, class, derived class, and OOP. input focus: The area in a window that receives keystrokes or mouse actions. Also called focus. insertable object: An ActiveX object created by its server through the OLE Documents interface. Insertable objects are marked in the registry and appear in the Insert Object dialog. insertion point: Where the next characters that the user types appear. instance variable: A variable that contains data that is private to a specific object in a class. Also called field, member, and slot. Contrast with class variable. instantiation: See object. interface: The external view of an object which hides the code that implements its behavior. In COM, group of semantically related functions that provide access to a COM object. internal function: A global function that you write. Internet: If capitalized (Internet), the world-wide system for linking smaller computer networks together. Networks connected through the Internet use a set of communications standards called TCP/IP to communicate. The Internet provides file transfer, remote login electronic mail, news, World-Wide Web, and other services. If not capitalized (internet), any collection of distinct networks working as one. intranet: A private network that uses TCP/IP-based networking for host access, workgroup collaboration, desktop and network resource management, and custom applications to maximize the enterprise's productivity. ISP (Internet Service Provider): A commercial service with an Internet gateway that provides access to the Internet for organizations and individuals.
-11
Glossary
Java: An object-oriented language that can be used to create machine-independent applications and applets. JavaScript: A scripting language that was jointly created by NetScape and Sun. JavaScript programs are not compiled like Java applets. JavaScript programs are embedded in the HTML markup of a page. After the page is loaded, the browser interprets the JavaScript program and runs it. just-in-time activation: The ability for an MTS object to be activated only as needed for executing requests from its client. Objects can be deactivated even while clients hold references to them, allowing otherwise idle server resources to be used more productively. Also refers to MTS ability to deactivate an object after a period of inactivity. late binding: Associating a symbol with an object at runtime. Also called dynamic binding. Contrast with early binding. See also binding. library: A collection of SQLWindows objects such as form windows, dialog boxes, or class definitions that are shared by more than one application. link: In programming, to connect programs compiled or assembled at separate times so they can be executed together. local: A variable, function, or object that is known only in a single part of an application. See also global and scope. locale: A text string such as English (United States) that identifies a language and locality to allow programs to use language-specific formatting and processes. Can also be identified by a number called the localeID. logical operator: See boolean operator. LONG VARCHAR: In SQL, a column data type where the value can be longer than 254 bytes. Also called LONG. loop: Code that is executed repeatedly until a limit or condition is met. lParam: A parameter used with messages. The l stands for long which is its length (32 bits or two words). marshalling: Packing and sending method parameters across thread or process boundaries. MDI (Multiple Document Interface): A user interface model created by Microsoft. menu: A list of choices from which you can select an action. A menu appears when you click the menu title in the menu bar. -12
menu item: A choice in a menu or menu bar. message: The way that objects interact with each other. An object (the sender) sends a message to another object (the receiver) to make a request or notify it of something. The receiver can ignore it or take some action. Messages make it easy to reuse code. The internals of an object can change while the messages remain the same. Code changes are then highly localized. message actions: A section in the outline where you code actions that are responses to messages. MetaFile: Windows GDI commands that create text or images. MetaFiles are a convenient way to store graphics commands. method: A request to an object to perform an action. mnemonic: A keyboard sequence that moves the input focus to an object, menu, or menu item. Contrast with accelerator. modal dialog box: A dialog box that suspends the application until the user closes the dialog box. modeless dialog box: A dialog box that does not stop processing within other windows. mouse pointer: A graphic symbol that shows the location of the mouse on the screen. The mouse pointer is usually an arrow, but can change to other shapes during some tasks. Also called cursor. MTS (Microsoft Transaction Server): A windows NT service that acts as both an object broker for components and as a distributed transaction manager. MTS object, MTX server: A COM object that executes in the MTS run-time environment and follows the MTS programming and deployment model. multiuser: The ability of a database server to provide its services to more than one user at a time. null: A value that means the absence of data. Null is not considered equivalent to zero or to blank. The value of null is not considered to be greater than, less than, or equivalent to another value, including a null value. object: A window object is a visual element on the screen such as a table window, push button, or menu. An OOP object is a representation of a software entity such as a user-defined window or a user-defined variable. An object has the data structure and behavior
Developing with SQLWindows
-13
Glossary
specified by its class (which is its blueprint). Also called instance, occurrence, or instantiation. See also class, encapsulation, and OOP. object-oriented programming (OOP): Programming that uses objects which combine data and behavior. Objects use the data structure and behavior of their class. See also class, encapsulation, inheritance, object, and polymorphism. ODBC (Open DataBase Connectivity): An open standard originally developed by Microsoft to allow transparent data access to all kinds of data stored such as relational databases. Third parties create drivers to suit their own data store. OLE DB: A standard data access programming interface from Microsoft designed to replace ODBC, and provide wider coverage of different types of data stores. OLE Documents: The part of ActiveX that deals with embedding, linking, and editing objects. operator: A symbol or word that represents an operation to be performed on the values on either side of it. Examples of operators are: arithmetic (+, -, *, /), relation (=.!=, >, <, >=, <=), and logical (AND, OR, NOT). outline: The statements that define the objects and procedural logic in an application. outline items: Each line of text in an outline. parameter: A value for a function that defines the data or controls how the function executes. Also called argument or operand. polymorphism: The ability for different objects to respond to the same request in different ways. For example, both a push button and a scroll bar can respond to a paint message, but the actions they take are different. The sender does not need to know the type of object that is responding to the message. Also called overloading. See also OOP. pooling: A performance optimization based on using collection of pre-allocated resources, such as objects or database connections. Pooling results in more efficient resource allocation. populate: To fill a table window with data from a source such as a database, array, or file. popup menu: See menu. precedence: The default order in which operations are performed in an expression. profile: A set of format specifications. property: Data that defines the state of a component.
-14
proxy: An interface that provides parameter marshalling and communication for a client to call an object running in a different execution environment, such as on a different thread or in another process. The proxy is located with the client and communicates with a corresponding stub that is located with the object that is being called. Also, an internet server that runs on a firewall computer that controls client computers access to the Internet. Using a proxy server, a company can stop employees from accessing certain Web addresses, improve performance by storing Web pages locally, and hide the internal networks identity so that it is difficult for external users to monitor. query: A request for information from a database, optionally based on specific conditions. For example, a request to list all customers whose balance is greater than $1000. You give queries with the SQL SELECT command. receive data types: A data type that passes data to a function by reference so the function can change it. Report Builder: An application that lets you design, display, and print reports. result set: A set of rows retrieved from one or more tables or views during a query. row: In a table window, a complete horizontal line of cells in a table window. In a database, a set of related columns that describe a specific entity. For example, a row could contain a name, address, telephone number. Sometimes called record or tuple. See also table and column. RPC (Remote Procedure Call): A standard that allows one process to make calls to functions that are executed in another process. The process can be on the same computer or on a different computer in the network. RTF (Rich Text Format): A Microsoft format that uses ASCII characters to encode layout and format settings. For example, \ul1 is the code for underline. You use RTF to transfer a file from one application to another. You can specify RTF output when you call the SalReportPrintToFile function. run mode: A designtime mode in SQLWindows when you run and test an application. Also called user mode. runtime: The time during which a user executes a program. safe reference: A reference to the current object that is safe to pass outside the current object's context. SAL (SQLWindows Application Language): A procedural language for writing actions that execute at runtime.
-15
Glossary
SAM (SQLWindows Application Messages): A message that SQLWindows sends to an application or its objects when an event occurs. scope: The part of an outline where the name of a variable, function, or object is known. See also local and global. section: In an application outline, a group of contiguous statements; a parent item and all its children. serialization: In apartment-model threading, the process of queuing a property or method request until the threads that own the apartment of the current object finishes the method it is executing. server: A computer on a network that provides services to client applications. See also: client and database server. The term server is also used to refer to applications in DDE and Report Builder. In ActiveX, local/remote server runs in a separate process space from a client application, as an *.EXE. SGML (Standard Generalized Markup Language): An international standard for defining descriptions of structure and content of electronic documents. XML is a subset of SGML designed to deliver SGML-type information over the Web. shared property: A variable that is available to all objects in the same server process via the Shared Property Manager. The value of the property can be any type that can be represented by a variant. siblings: Child items with the same parent. single-user: A database server that can only provide its services to one user at a time. sizing pointer: A pointer you use to change the size of an object. SQL (Structured Query Language): A standard set of commands used to manage information stored in a database. These commands let users retrieve, add, update, or delete data. There are four types of SQL commands: Data Definition Language (DDL), Data Manipulation Language (DML), Data Query Language (DQL), and Data Control Language (DCL). Pronounced ess-que-ell or sequel. Sql Handle: A data type that identifies a connection to a database. See also cursor. SQL/API: Gupta Technologies LLC's API that lets a programmer develop a database application in the C programming language. The SQL/API has functions that a programmer calls to access a database using SQL commands. SQLBase: A relational DBMS that lets users access, create, update, and delete data. SQLWindows: A graphical SQL application development system for Microsoft Windows and Motif.
-16
stateless object: An MTS object can maintain internal state across multiple interactions with a client. Such an object is said to be stateful. An MTS object can also be stateless, which means the object does not hold any intermediate state while waiting for the next call from a client. statement: A unit in the application outline that specifies an action for the computer to perform. static variable: A variable defined in a function that retains its value in between calls to the function. string: A sequence of characters treated as a unit. stub: An interface that provides parameter marshalling and communication for an object to receive calls from a client that is running in a different execution environment, such as on a different thread or in another process. The stub is located with the object and communicates with a corresponding proxy that is located with the client that calls it. system function: A built-in SQLWindows function that performs an often-needed task. system modal dialog box: A dialog box that suspends all Window applications until the user closes the dialog box. table: The basic data storage structure in a relational database. A table is a twodimensional arrangement of columns and rows. Each row contains a like set of data items (columns). Also called relation. table window: An object that displays data in a tabular format (columns and rows). A table window can be a top-level or child window. TCP/IP (Transmission Control Protocol/Internet Protocol): Two main standards in the Internet suite of protocols. This protocol suite provides the standards, specifies the details of how computers communicate, and provides a set of conventions for interconnecting networks and for routing traffic over the Internet. thread: A path of execution through a program and the smallest unit of execution that Win32 schedules and allocates CPU time. A thread consists of a stack, the state of the CPU registers, and an entry in the execution list of the system scheduler. Each thread shares all of the processs resources. thread local storage (TLS): A Win32 mechanism that allows multiple threads of a process to store data that is unique for each thread. thumb: See scroll box.
-17
Glossary
TIFF (Tag Image File Format): A graphics format (developed by Aldus and Microsoft) used to transfer graphics between different applications and different types of computers. TIFF stores images in a bitmap (raster) format. top-level window: A form window, table window (that is not a child), or dialog box. type information: Standard descriptions of properties, methods, and events that an object supports as well as return types, parameter names, and parameter types. URL (Uniform Resource Locator): The address of a document on the World Wide Web. A URL has three parts: the protocol, the host name, and the path name to the documents. value: Data assigned to a constant or a variable. variable: A named item that can be any of a given set of values. Contrast with constant. visual editing: See in-place activation. W3C (World Wide Web Consortium): The international consortium founded in 1994 to develop standards for the Web. window: A rectangular area on the screen where an application receives input from the mouse or keyboard and displays output. A user can open, close, an move windows and can resize most windows. Several windows can be open at the same time. Window Editor: SQLWindows' drawing functions. You use the Window Editor to add child objects to a design window. window function: A function that you write in a top-level window (form window, dialog box, or table window) or in a MDI window. The scope of a window function is in actions in the window. Window Grabber: A mouse pointer that selects and moves an object. Window Handle: A data type that identifies a single instance of a particular window. workgroup: In Windows, an informal group of computers that share resources with each other. User authentication occurs on each computer in the workgroup. Other computers in the workgroup trust that each computer has performed this authentication. Contrast with domain. World-Wide Web (WWW): A group of Internet servers that share a set of protocols such as HTTP and conventions such as HTML. Using Web browsing software, you can activate hyperlinks in Web documents and jump from one location to another in any order you choose. You can also open documents on Web servers that contain many types of information--not just text but sound, animation, and video.
-18
wParam: A parameter used with messages. The w stands for word (16 bits) which is its length. XML (Extensible Markup Language): A subset of SGML that provides a uniform method for describing and exchanging structured data in an open, text-based format, and delivers this data using the standard HTTP protocol.
-19
Title:
Index
! (comments) 4-6, 4-33, 7-26 # (formatting character) 11-4 $ (formatting character) 11-5 % (formatting character) 11-5 * (formatting character) 11-5 *.APD extension 18-11 *.APL extension 18-3 *.APP extension 4-4 *.APT extension 4-4 *.EXE extension 4-4 *.TLB extension 20-26 , (formatting character) 11-5 . (formatting character) 11-5 ; (formatting character) 11-5 _ (formatting character) 11-5
Symbols
Numerics
0 (formatting character) 11-4
A
About SQLWindows (Help menu) 4-50 absolute screen location (dialog boxes) 5-11 accelerators 5-18 defined G-1 menu items 6-3 push buttons 5-27, 5-28 accessor method defined G-1 Actions tab 2-8 Active Coding Assistant 2-20 ActiveX see COM clients or COM servers defined G-1 ActiveX control defined G-1 ActiveX Explorer (Tools menu) 4-39 ActiveX Explorer menu Generate Deep 4-47 Generate Full 4-47 Generate Stub 4-47 Generation Option 4-47 Include APL 4-47 Library Help 4-47 Open Library 4-47 Refresh 4-47 Show CoClasses 4-48 Show Enumerations 4-48
Show Events 4-48 Show Functions 4-48 Show Get Properties 4-48 Show Interfaces 4-48 Show Put Properties 4-48 Show SAL Types 4-48 Add to List (Tools menu) 4-46 adding objects 5-2 Coding Assistant 5-2 Controls palette 5-2 Align Edges (Layout menu) 4-22 Align to Grid (Layout menu) 4-22 ambient properties defined G-1 animate 10-2 defined G-1 normal 4-27 slow 4-27 speed 4-32 apartment model defined G-1 API (Application Programming Interface) defined G-1 applet defined G-1 application defined G-1 Application Actions (outline item) 2-10 defined G-2 SAM_AppExit 9-7 SAM_AppStartup 9-8 SAM_SqlError 9-39, 12-22 SAM_Timer 9-41 setting SQL system variables 12-4 Application Description (outline item) 2-9 applications command line arguments 7-15, 7-32 compiling 4-4, 4-12, 4-13 debugging 4-26 deploying 3-2 executable 3-2 exiting 9-7 indented text 4-4 normal storage format 4-4 optimizing 4-14 production 3-2 resources (bitmaps, icons, cursors) 7-34 starting 9-8
Index-1
Index
testing 4-12 text 4-4 version information 4-16 argument defined G-2 arrays 7-15 defined G-2 dynamic 7-16, 7-17 functions 7-18 multi-dimensional 7-16 one-dimensional 7-15 referring to 7-16 referring to multi-dimensional arrays 7-17 setting bounds 7-16, 7-17 static 7-15, 7-17 storing window handles 7-18 AS/400 12-17 Attribute Inspector 2-17 Attribute Inspector (Tools menu) 4-38 attributes 2-16 setting 5-4 Auto Parameter Info 2-21 Auto variable window 10-9 automation 19-3, 19-30, 20-2 defined G-2
Boolean data type 7-3 data types treated as 7-9 Boolean operator defined G-2 Both (Layout menu) 4-24 Bottom (Layout menu) 4-23 Break (Debug menu) 4-26, 10-5 Break statement 7-21 breakpoints 4-27, 10-2, 10-3 defined G-2 display properties 4-33 immediate 10-4, 10-5 Breakpoints (Debug menu) 4-27 Bring To Front (Layout menu) 4-22 browse defined G-2 Browse All Classes (Tools menu) 4-40 browser defined G-3 buffer defined G-3 Build (Project menu) 4-20 Build Settings (Project menu) 4-13 BYTE (external data type) 21-9 C structures 21-23, 21-36 cache defined G-3 call by reference defined G-3 call by value defined G-3 Call Stack (Tools menu) 4-38 Call Stack window 10-10 Call statement 7-22 calling functions 7-22 Cascade (Window menu) 4-48 cascading menus 6-5 Case (Select Case statement) 7-24 case sensitive defined G-3 case sensitivity (SAL) 7-2 cast defined G-3 casting 8-22 CBTYPE.H 21-31 CDK (Component Developers Extension Kit)
B
backend defined G-2 background text 5-19 attributes 5-19 mnemonics 5-19 base class 8-4 defined G-2 Base Classes tab 2-13 behavior defined G-2 bind variables 7-14, 12-6 defined G-2 in classes 8-54 binding 23-7 defined G-2 bitmap defined G-2 bitmaps 7-34 bitwise G-2 Books Online (Help menu) 4-49 BOOL (external data type) 21-23
introduction 1-2 CDLL.LIB 21-30, 21-31 CDLLI*.DLL 21-31 cell defined G-3 CENTURA.H 21-31 CGI defined G-3 CHAR (external data type) 21-9 character defined G-3 check boxes 5-355-36 attributes 5-35 hiding and showing 5-36 SalHideWindow 5-36 SalShowWindow 5-36 SAM_Click 9-10 SAM_KillFocus 9-31 SAM_SetFocus 9-39 Check In (Project menu) 4-12 Check Out (Project menu) 4-11 child windows 5-6, 5-9, 5-17, 5-42 hWndItem 9-5 SAM_Close 9-12 SAM_Create 9-17 SAM_CreateComplete 9-17 SAM_Destroy 9-18 SAM_Help 9-30 SAM_Timer 9-41 class defined G-3 Class Definitions (outline item) 2-10, 7-29 class function defined G-3 class functions 7-29, 8-45 writing 7-29 class variable defined G-3 class variables 8-42 Class Variables tab 2-13 classes 8-2 adding buttons to Controls palette 2-25 assigning UDVs (user-defined variables) 8-21 base class 8-4 bind variables 8-54 browsing 4-40 child window classes 8-13 class functions 8-45
class variables 8-42 Controls palette 8-25 creating user-defined objects 8-18 creating user-defined variables (UDVs) 8-19 creating user-defined windows 8-24 defining 8-9 dialog box classes 8-13 dynamic instantiation 8-23 form window classes 8-13 functional classes 8-5, 8-10 general window classes 8-7 hierarchy 8-4 inheritance 8-3 instance variables 8-36 into variables 8-54 MDI window classes 8-13 message actions 8-26 multiple inheritance 8-5 MyValue 8-54 OBJ_Null 8-23 object destructors 8-23 SalObjCreateFromString 8-24 SalObjGetType 8-24 SalObjIsDerived 8-24 SalObjIsNull 8-23, 8-24 SalObjIsValidClassName 8-54 single inheritance 8-4 SqlVarSetup 8-54 this 8-39 user-defined variables (UDVs) 8-9 user-defined windows 8-8 window classes 8-6, 8-10 class-qualified references 23-13, 23-14 client defined G-4 Clipboard copying in main window 4-6 cutting in main window 4-6 defined G-4 functions 7-33 pasting in main window 4-6 Close All (Window menu) 4-49 Close Database Explorer (Database Explorer menu) 447 code page 4-17 defined G-4 Coding Assistant 1-4, 2-18, 5-2 adding a custom control to a window 22-3
Index-3
Index
adding class children 8-15 adding columns 15-7 adding comments 7-27 adding menus 6-2 adding objects 5-2 adding resources 7-34 adding user-defined variables (UDVs) 8-19 adding user-defined windows 8-25 defined G-4 layout 4-33 Microsoft Windows Messages 9-4 program-defined messages 9-3 selecting base classes 8-10, 8-12 specifying accelerators 5-18, 6-3 specifying external data types 21-7 Coding Assistant (Tools menu) 4-37 collapse defined G-4 Collapse (Edit menu) 4-7 Collapse Outline (Edit menu) 4-7 collection defined G-4 color for objects 5-47 columns see Chapter 14 adding 15-7 data type 15-8 defined G-4 enabling and disabling 15-9 flags 15-39 formats 15-9 hiding and showing 15-8 identifier 15-45 defined G-4 input masks 15-9 locking 15-47 maximum data length 15-8 moving 15-7 position 15-45 defined G-4 SalDisableWindow 15-9 SalEnableWindow 15-9 SalHideWindow 15-8 SalShowWindow 15-8 SAM_AnyEdit 9-6 SAM_CaptionDoubleClick 9-9 SAM_Click 9-10 SAM_ColumnSelectClick 9-13
SAM_DoubleClick 9-20 SAM_DropFiles 9-26 SAM_FieldEdit 9-30 SAM_KillFocus 9-31 SAM_SetFocus 9-39 SAM_Validate 9-41 sizing 15-7 validation 11-10 COM (Component Object Model) see also COM clients or COM servers automation 19-3 class ID (CLSID) 19-3 CoClass 19-5 contained objects 19-4 controls 19-4 defined G-4 dispatch ID (dispID) 19-3 Distributed COM (DCOM) 19-4 events 19-2 functions 19-2 globally unique identifier (GUID) 19-3 IDispatch 19-3 insertable objects 19-4 interface ID (IID) 19-3 introduction 19-2 marshalling 19-4 object models 19-3 properties 19-4 proxy 19-3 RPC (Remote Procedure Call) 19-4 type information 19-3 type libraries 19-3 COM clients see Chapter 19 ActiveX Explorer 19-9 ClassView 19-12 code generation options 19-13 InfoView 19-16 MembersView 19-15 selecting a type library 19-11 starting 19-10 toolbar 19-10 adding button to Controls palette 2-25 automation 19-30 automation.apl 19-7 collections 19-37 COM Proxy class 19-17, 19-41 container controls 19-27
controls 19-27 Controls palette button 19-7 creating components 19-6 dispatch interface 19-40 embedded objects 19-28 creating 19-28 events 19-33 exception handling 19-38 font classes 19-45 functional class 19-17 IDispatch 19-27 include libraries 19-40 in-place activation 19-36 insertable objects 19-27 libraries location 4-35 licensing 19-40 menu groups 19-37 menu merging 19-36 Object class 19-17, 19-40 OLE automation.apl 19-7 OleErrorInfo 19-38 outline structure 19-17 picture classes 19-45 properties 19-36 SafeArray class 19-44 SalActiveXAutoErrorMode 19-29, 19-38 SalActiveXClose 19-29 SalActiveXCreate 19-29 SalActiveXCreateFromData 19-29 SalActiveXCreateFromFile 19-29 SalActiveXDelete 19-29 SalActiveXDoVerb 19-30 SalActiveXGetActiveObject 19-29 SalActiveXGetData 19-30 SalActiveXGetObject 19-30 SalActiveXInsertObjectDlg 19-30 SalActiveXOLEType 19-30 stdole_Font 19-45 stdole_Picture 19-45 stdole_StdFont 19-45 stdole_StdPicture 19-45 toolbar merging 19-36 type libraries 19-11 using Microsoft Office components 19-19 Variant class 19-42 COM servers see Chapter 19
accessor methods 20-11 assigning 20-22 automation 20-2 types 20-17, 20-28 class factory 20-28 CoClass outline type 20-2 collections 20-7, 20-19 COM Class Wizard 20-2 configuring 4-18 connection points 20-28 creatable attribute 20-16 debugging 4-14, 4-27, 20-25 dispatch interfaces 20-28 dispinterfaces 20-28 dynamic instantiation 20-22 enumerations 20-20 events 20-13, 20-18 EXCEPINFO structure 20-23 GUIDs 20-28 IDispatch 20-28 IEnumVARIANT 20-28 in-process servers 4-13, 20-16 Interface outline type 20-2 internal implementation 20-28 IObjectControl 20-13 IUnknown 20-28 local servers 4-13, 20-16 MTS (Microsoft Transaction Server) 20-34 Build Settings 4-14, 20-16 deferred activation 20-36 early deactivation 20-36 IObjectContext 20-35, 20-37 IObjectControl 20-36, 20-37 ISharedProperty 20-39 ISharedPropertyGroup 20-39 ISharedPropertyGroupManager 20-39 object pooling 20-38 SalMTSCreateInstance 20-37 SalMTSDisableCommit 20-37 SalMTSEnableCommit 20-37 SalMTSGetObjectContext 20-37 SalMTSIsInTransaction 20-37 SalMTSIsSecurityEnabled 20-37 SalMTSSetAbort 20-37 SalMTSSetComplete 20-37 shared properties 20-39 stateless applications 20-38 new keyword 20-22
Index-5
Index
OBJ_Null 20-22, 20-23 outgoing interfaces 20-28 outline structure 20-15 properties 20-11 reference counts 20-23 registering 20-27 regsvr32.exe 20-27 SalObjIsNull 20-23 SalSetErrorInfo 20-23 sample applications 20-39 setting error information 20-23 setting to null 20-22 threading 4-18, 4-19, 20-28 None 20-30 apartment model 20-29 main single threaded apartment (STA) 20-30 multiple single threaded apartments (STA) 20-30 outlines and apartments 20-33 thread local storage (TLS) 20-29 type information 4-19, 20-26 unregistering 20-27 combo boxes 5-385-40 attributes 5-39 enabling and disabling 5-40 hiding and showing 5-39 input masks 5-40 maximum data length 5-40 SalDisableWindow 5-40 SalEnableWindow 5-40 SalHideWindow 5-39 SalListPopulate 12-27 SalShowWindow 5-39 SAM_AnyEdit 9-6 SAM_Click 9-10 SAM_DoubleClick 9-20 SAM_DragCanAutoStart 9-21, 9-22 SAM_DragEnter 9-23 SAM_DragExit 9-23 SAM_DragMove 9-24 SAM_DragNotify 9-24 SAM_DragStart 9-25 SAM_DropDown 9-26 SAM_DropFiles 9-26 SAM_FieldEdit 9-30 SAM_KillFocus 9-31 SAM_Print 9-32 SAM_SetFocus 9-39 SAM_Validate 9-41
sorted 5-40 string type 5-39 validation 11-10 command line arguments applications 7-15, 7-32 SalLoadApp 7-32 SQLWindows 2-32 comment defined G-5 Comment Items (Edit menu) 4-6 comments (!) 4-6, 4-33, 7-26 COMMIT statement 12-8, 12-9, 12-12, 12-25 Compile (Project menu) 4-12 compiling applications 4-4, 4-12, 4-13 Complete Word 2-20 component defined G-5 Component menu Details 4-21 Go To Item 4-20, 18-5 Large Icons 4-21 Libraries 18-4 List 4-21 Menu Editor 4-20 Merge 18-5 Merge Libraries 4-21 New 4-20 QuickObject Editor 4-20 Refresh 18-5 Refresh Libraries 4-21 Show Item Information 4-20, 18-5 Small Icons 4-21 Wizards 4-20 Components tab 2-8 constants 7-18 data types 7-2 defined G-5 naming conventions 7-20 system constants 7-19 Constants (outline item) 2-10 Constants tab 2-12 Contents 5-6, 5-17 contents defined G-5 context 23-4 defined G-5 context row defined G-5
Continue (Debug menu) 4-26 control defined G-5 control panel 5-47, 11-6 Controls (Tools menu) 4-38 Controls palette 2-23, 5-2 adding a custom control to a window 22-3 adding columns 15-7 configuring 2-25 creating COM components 19-7 creating instances of classes 8-25 conventions 1-18 cookies defined G-5 Cool Look 4-30 Copy (Edit menu) 4-6 creator defined G-5 CSS (Cascading Style Sheets) defined G-5 CStructAllocFarMem 21-42 CStructCopyBuffer 21-43 CStructCopyFromFarMem 21-43 CStructCopyToFarMem 21-42 CStructFreeFarMem 21-42 CStructGetByte 21-38 CStructGetDouble 21-39 CStructGetFarPointer 21-39 CStructGetFloat 21-38 CStructGetLong 21-38 CStructGetString 21-39 CStructGetWord 21-38 CStructPutByte 21-40 CStructPutDouble 21-41 CStructPutFarPointer 21-41 CStructPutFloat 21-41 CStructPutLong 21-40 CStructPutString 21-41 CStructPutWord 21-40 cursor defined G-5 cursors 2-13, 7-34 custom controls see Chapter 22 adding to a window 22-2 attributes 22-5 creating custom control classes 22-5 DLLs 22-2
editable 22-18 editor interface 22-14 non-editable 22-19 SalValidateSet 22-17, 22-19 SAM_Create 22-3 SAM_CustControlCmd 9-18, 22-3 SAM_Destroy 22-3 SAM_DropFiles 9-26 SAM_Timer 22-3 SAM_Validate 22-17 SWCustControlEditor 22-15 using classes and libraries 22-4 WM_COMMAND 22-4 writing 22-11 Cut (Edit menu) 4-6
D
data binding defined G-6 data fields 5-235-24 attributes 5-23 data types 5-23 enabling and disabling 5-24 formats 5-24 hiding and showing 5-23 input masks 5-24 mnemonics 5-23 SalDisableWindow 5-24 SalEnableWindow 5-24 SalHideWindow 5-23 SalShowWindow 5-23 SAM_AnyEdit 9-6 SAM_DragCanAutoStart 9-21 SAM_DragDrop 9-22 SAM_DragEnd 9-22 SAM_DragEnter 9-23 SAM_DragExit 9-23 SAM_DragMove 9-24 SAM_DragNotify 9-24 SAM_DragStart 9-25 SAM_DropFiles 9-26 SAM_FieldEdit 9-30 SAM_KillFocus 9-31 SAM_Print 9-32 SAM_SetFocus 9-39 SAM_Validate 9-41 validation 11-10 data sources
Index-7
Index
connecting 3-4 data types Boolean 7-3 constants 7-2 Date/Time 7-3 defined G-6 File Handle 7-8 Long String 7-8 Number 7-7 receive 7-2, 7-30, 21-7 Session Handle 7-7, 12-25, 13-2, 13-3 Sql Handle 7-7, 12-5 String 7-8 variables 7-2 Window Handle 5-49, 7-9 Database Explorer (Tools menu) 4-39 Database Explorer menu Close Database Explorer 4-47 Disconnect 4-47 New 4-40 Query 4-44 SQL Script 4-41 Stored Procedure 4-43 Table 4-42 View System Tables 4-47 database parameters 12-28 database server defined G-6 databases see chapter 12 defined G-6 Date/Time data type 7-3 arithmetic 7-4 DATETIME_Null 7-3 default format 7-3 formats 11-2 input masks 11-12 internal format 7-7 validation 11-8 DATETIME (external data type) 21-11 DB2 12-17 DBMS (database management system) defined G-6 DBP_AUTOCOMMIT 12-25, 12-30 DBP_BRAND 12-30 DBP_FETCHTHROUGH 12-30 DBP_LOCKWAITTIMEOUT 12-31 DBP_NOPREBUILD 12-32
DBP_PRESERVE 12-25, 12-32 DBP_ROLLBACKONTIMEOUT 12-33 DBP_VERSION 12-33 DCL (Data Control Language) 12-16 DCOM (Distributed COM) defined G-6 DDL (Data Definition Language) 12-13, 12-16 Debug menu Break 4-26 Breakpoints 4-27 Continue 4-26 Fast Animate 4-27 No Animate 4-27 Playback 4-27 Playback Rewind 4-27 Slow Animate 4-27 Step Into 4-26 Step Over 4-26 Stop Debugging 4-26 Debug toolbar 10-4 debugging see Chapter 10 animate normal 4-27 animation 10-2 applications 4-26 Break 10-5 breakpoints 10-2, 10-3 display properties 4-33 immediate 10-4, 10-5 Call Stack window 10-10 commands 10-5 DLLs 21-33 Expressions window 10-6 Messages window 10-6 run mode 10-2 SalCompileAndEvaluate 10-11, 10-12 SalContextCurrent 10-12 slow animate 4-27 speed 4-32 Step Into 10-5 Step Over 10-5 testing SQL statements 10-11 toolbar 10-4 variables 10-9 Variables window 10-6 watch variables 10-8 windows 10-5
Delete (Edit menu) 4-6 DELETE statement 12-12 deploy*.exe 3-2, 3-3 deploy*.wse 3-4 deploying an application 3-2 deployment files 3-2 derived class defined G-6 Description tab 2-13 design window defined G-6 designtime 1-4 defined G-6 Design-time Settings (outline item) 2-9 destructors 8-23 Details (Component menu) 4-21 DHTML (Dynamic HTML) defined G-6 dialog boxes 5-5, 5-95-11 absolute screen location 5-11 attributes 5-10 defined G-7 modal 5-9 modeless 5-9 owned 5-10, 5-11 ownerless 5-10, 5-11 SalCreateWindow 5-9 SalDestroyWindow 5-9 SalEndDialog 5-10 SalModalDialog 5-10 SAM_Close 9-12 system modal 5-10 diamond defined G-7 DIB (Device-Independent Bitmap) defined G-7 Diff/Merge (Tools menu) 4-40 disabled defined G-7 Disconnect (Database Explorer menu) 4-47 DLLs (Dynamic Link Libraries) see Chapter 21 BOOL 21-23 BYTE 21-9 C structures 21-23, 21-36 calling external functions 21-27 CBDLL.LIB 21-31 CBTYPE.H 21-31
CDLL.LIB 21-30 CDLLI*.DLL 21-31 CENTURA.H 21-31 CHAR 21-9 creating an import library 21-31 CStructCopyBuffer 21-43 CStructCopyFromFarMem 21-43 CStructCopyToFarMem 21-42 CStructFreeFarMem 21-42 CStructGetByte 21-38 CStructGetDouble 21-39 CStructGetFarPointer 21-39 CStructGetFloat 21-38 CStructGetLong 21-38 CStructGetString 21-39 CStructGetWord 21-38 CStructPutByte 21-40 CStructPutDouble 21-41 CStructPutFarPointer 21-41 CStructPutFloat 21-41 CStructPutLong 21-40 CStructPutString 21-41 CStructPutWord 21-40 custom controls 22-2 DATETIME 21-11 debugging 21-33 defined G-7 DOUBLE 21-9 DWORD 21-9 dynamic linking 21-3 export ordinal 21-5 External Functions (outline item) 21-4 FLOAT 21-9 HARRAY 21-9, 21-11, 21-19, 21-23 HFILE 21-23 HSQLHANDLE 21-23 HSTRING 21-11, 21-15 HWND 21-23 INT 21-9 LONG 21-9 LPBOOL 21-23 LPBYTE 21-10 LPDOUBLE 21-10 LPDWORD 21-10 LPFLOAT 21-10 LPHFILE 21-23 LPHSQLHANDLE 21-23 LPHSTRING 21-11, 21-15
Index-9
Index
LPHWND 21-23 LPINT 21-10 LPLONG 21-10 LPNUMBER 21-10 LPSTR 21-11, 21-13 LPVOID 21-11, 21-15 LPWORD 21-10 memory management 21-12 NUMBER 21-9 parameters 21-6 pass by reference 21-7 pass by value 21-7 passing UDVs (user-defined variables) 21-33 reference counts 21-12 returns 21-6 SalGetUDVData 21-35 SalStrGetBufferLength 21-16 SalUdvGetCurrentHandle 21-33 stack segment 21-32 strci*.dll 21-36 structPointer 21-23 subsegment allocation 21-13 SWinCvtDoubleToNumber 21-9 SWinCvtIntToNumber 21-9 SWinCvtNumberToInt 21-10 SWinCvtNumberToULong 21-10 SWinCvtNumberToWord 21-10 SWinCvtULongToNumber 21-9 SWinHStringLock 21-15 SWinHStringUnlock 21-15 SWinInitLPHSTRINGParam 21-15 SWinMDArrayDataType 21-19 SWinMDArrayGetBoolean 21-19 SWinMDArrayGetDateTime 21-19 SWinMDArrayGetHandle 21-19 SWinMDArrayGetHString 21-19 SWinMDArrayPutBoolean 21-19 SWinMDArrayPutDateTime 21-19 SWinMDArrayPutHandle 21-19 SWinMDArrayPutHString 21-20 SWinMDArrayPutNumber 21-20 SWinUdvLock 21-33 ThreadSafe 21-5 using CDLLI*.DLL 21-31 using external data types 21-8 when to use 21-2 WORD 21-9 writing 21-27
DML (Data Manipulation Language) 12-12, 12-16 DNA (Distributed interNet Applications) defined G-7 Docking windows 5-49 DOM (Document Object Model) defined G-7 domain defined G-7 DOUBLE (external data type) 21-9 Down (Layout menu) 4-23 drag-and-drop see Chapter 18 DWORD (external data type) 21-9 dynalibs 4-13, 18-6 *.APD extension 18-11 compiling 18-11 exporting items 18-8 using imported items 18-11 writing 18-8 dynamic instantiation CoClasses 20-22 UDVs (user-defined variables) 8-23 dynamic linking 21-3 dynamically linked libraries see dynalibs 18-6
E
early binding defined G-7 early-bound references 23-7 Edit menu Collapse 4-7 Collapse Outline 4-7 Comment Items 4-6 Copy 4-6 Cut 4-6 Delete 4-6 Expand All Level 4-7 Expand One Level 4-6 Find 4-7 Find Again 4-8 Insert Line 4-6 Move Down 4-7 Move Left 4-7 Move Right 4-7 Move Up 4-7 Outline 4-6 Paste 4-6
Properties 4-9 Replace 4-8 Uncomment Items 4-6 Undo 4-6 elevator box defined G-7 Else If statement 7-22 Else statement 7-22 embedding defined G-7 Enable Runtime Checks of External References 4-10 encapsulation defined G-8 engine defined G-8 Equal Sizing (Layout menu) 4-23, 4-24 ERROR.SQL 12-23 Even Spacing (Layout menu) 4-23 event-driven program defined G-8 events 1-5, 9-2 defined G-8 exception defined G-8 ! (comments) 4-6, 4-33, 7-26 executables 4-13 Execute (Project menu) 4-12 execution context 12-43 Exit (File menu) 4-5 expand defined G-8 Expand All Levels (Edit menu) 4-7 Expand One Level (Edit menu) 4-6 expressions 7-20 defined G-8 Expressions (Tools menu) 4-39 Expressions window 10-6 external functions 7-29 see Chapter 21 defined G-8 External Functions (outline item) 2-10, 21-4 external reference defined G-8 external references 23-2, 23-15 extranet defined G-8
F
Fast Animate (Debug menu) 4-27 fetch defined G-8 FETCH_Delete 12-11 FETCH_EOF 12-11 FETCH_Ok 12-11 FETCH_Update 12-11 File Handle defined G-9 File Handle data type 7-8 File menu Exit 4-5 most recently open 4-5 New 4-2 Open 4-3 Page Settings 4-4 Print 4-5 Save 4-3 Find (Edit menu) 4-7 Find Again (Edit menu) 4-8 firewall defined G-9 flag defined G-9 FLOAT (external data type) 21-9 focus defined G-9 focus frame defined G-9 fonts for objects 5-47 form pages 5-8 form units 5-48 form windows 5-5, 5-65-8 attributes 5-7 automatically creating 5-7 defined G-9 form pages 5-8 icon 5-8 SAM_Close 9-12 SAM_Print 9-32 formats see chapter 9 characters # 11-4 $ 11-5 % 11-5 * 11-5
Index-11
Index
, 11-5 . 11-5 ; 11-5 _ 11-5 0 11-4 scientific notation 11-5 columns 15-9 country profiles 11-6 data fields 5-24 Date/Time 11-2, 11-4 defined G-9 Long String 11-2 Number 11-2, 11-4 picture 11-3 profile-driven 11-2, 11-5 String 11-2 Formats (outline item) 2-10 frames 5-215-22 attributes 5-21 frontend defined G-9 FTP defined G-9 functional classes 8-5, 8-10 functions 7-28 actions 7-30 calling 7-22 class 7-29 defined G-9 external 7-29 internal 7-29 local variables 7-30 obsolete 3-6 parameters 7-30 returns 7-30 static variables 7-30 system 7-29 window 5-6, 7-29 Functions (Help menu) 4-49
GetLastError 19-38 GIF (Graphics Interchange Format) defined G-9 global defined G-9 global declarations defined G-9 Global Declarations (outline item) 2-10 global symbols 23-6 Go To Item (Component menu) 4-20, 18-5 grid activating 4-35 aligning 4-22 defined G-9 displaying 4-24, 4-35 Grid (Layout menu) 4-24 Grid group 4-34 group boxes 5-205-21 attributes 5-20 group separator defined G-9 GUI (Graphical User Interface) defined G-10 GUID (Globally Unique IDentifier) defined G-10 Gupta Team Developer introduction 1-2
H
handle defined G-10 handle-qualified references 23-12, 23-17 HARRAY (external data type) 21-9, 21-11, 21-19, 21-23 Height (Layout menu) 4-24 Help menu About SQLWindows 4-50 Books Online 4-49 Functions 4-49 Help Topics 4-49 Messages 4-49 QuickObjects 4-49 Visual Toolchest 4-49 Help Topics (Help menu) 4-49 HFILE (external data type) 21-23 hierarchy defined G-10 Horizontal Center (Layout menu) 4-23
G
GDI (Graphics Device Interface) defined G-9 general window classes 8-7 Generate Deep (ActiveX Explorer menu) 4-47 Generate Full (ActiveX Explorer menu) 4-47 Generate Stub (ActiveX Explorer menu) 4-47 Generation Option (ActiveX Explorer menu) 4-47
HSQLHANDLE (external data type) 21-23 HSTRING (external data type) 21-11, 21-15 HTML defined G-10 HTTP defined G-10 HWND (external data type) 21-23 hWndForm 7-14, 9-5 defined G-10 in messages 9-5 hWndItem 7-14, 9-5 defined G-10 in messages 9-5 hWndMDI 5-14, 7-14 hWndNULL 7-14 hypertext defined G-10
I
icon defined G-10 icons 7-34 identifiers maximum length 7-2 IDispatch 19-3 If statement 7-22 Include APL (ActiveX Explorer menu) 4-47 include libraries 18-2 *.APL extension 18-3 creating 18-3 display properties 18-5 displaying information 18-5 editing 18-4 file path 18-6 merging 18-5 opening 18-5 refresh when changed 18-5 refreshing 18-5 using 18-3 include library 4-13 indented text applications 4-4 Informix-Online 12-17 Informix-SE 12-17 Ingres 12-17 inheritance 8-3 defined G-11 in-place activation defined G-10
in-process server defined G-11 input focus defined G-11 input items 14-4 input masks see Chapter 11 characters 11-11 columns 15-9 combo boxes 5-40 data fields 5-24 Date/Time 11-12 functions 11-13 getting a fields value 11-12 Numbers 11-11 SalFmtGetInputMask 11-13 SalFmtKeepMask 11-13 setting a fields value 11-12 input message buffer 12-34 input variables 14-4, 14-17 Insert Line (Edit menu) 4-6 INSERT statement 12-12 insertable object defined G-11 insertion point defined G-11 installation program writing 3-4 instance variable defined G-11 instance variables 8-36 instantiation defined G-11 INT (external data type) 21-9 interface defined G-11 internal functions 7-29 defined G-11 writing 7-29 Internal Functions (outline item) 2-10, 7-29 Internet defined G-11 INTO variables 12-6 into variables 7-14 in classes 8-54 intranet defined G-11 isolation levels 12-37
Index-13
Index
J
Java defined G-12 JavaScript defined G-12 just-in-time activation defined G-12
K
keyboard shortcuts 2-26
L
Large Icons (Component menu) 4-21 late binding defined G-12 late-bound references 23-7 Layout menu Align Edges 4-22 Align to Grid 4-22 Both 4-24 Bottom 4-23 Bring To Front 4-22 Down 4-23 Equal Sizing 4-23, 4-24 Even Spacing 4-23 Grid 4-24 Height 4-24 Horizontal Center 4-23 Left 4-23 Preview Window 4-21 Right 4-23 Send To Back 4-22 Show Design Scroll Bars 4-26 Show Hidden Windows 4-26 Show Sample Text 4-25 Tab Order 4-25 Top 4-23 Vertical Center 4-23 Width 4-24 Layout tab 2-12 layout windows 2-11 Left (Layout menu) 4-23 libraries defined G-12 display properties 4-33
include 4-13 Libraries (Component menu) 18-4 Libraries (outline item) 2-9 Libraries tab 2-12 Library Help (ActiveX Explorer menu) 4-47 lines 5-22 attributes 5-22 link defined G-12 linking dynamic 21-3 static 21-3 List (Component menu) 4-21 list boxes 5-365-38, 9-39 attributes 5-37 hiding and showing 5-37 multiple selection 5-37 SalHideWindow 5-37 SalListPopulate 12-27 SalShowWindow 5-37 SAM_Click 9-10 SAM_DoubleClick 9-20 SAM_DragCanAutoStart 9-21 SAM_DragDrop 9-22 SAM_DragEnd 9-22 SAM_DragEnter 9-23 SAM_DragExit 9-23 SAM_DragMove 9-24 SAM_DragNotify 9-24 SAM_DragStart 9-25 SAM_DropFiles 9-26 SAM_KillFocus 9-31 sorted 5-37 List Members 2-22 local defined G-12 local variables 7-30 locale 4-17 defined G-12 Locals variable window 10-9 logical operator defined G-12 LONG (external data type) 21-9 Long String data type 7-8 bind variables 12-17 formats 11-2 INTO variables 12-17 maximum length 7-8
LONG VARCHAR defined G-12 loop defined G-12 Loop statement 7-23 lParam 7-14, 9-6 defined G-12 LPBOOL (external data type) 21-23 LPBYTE (external data type) 21-10 LPCHAR (external data type) 21-10 LPDATETIME (external data type) 21-11 LPDOUBLE (external data type) 21-10 LPDWORD (external data type) 21-10 LPFLOAT (external data type) 21-10 LPHFILE (external data type) 21-23 LPHSQLHANDLE (external data type) 21-23 LPHSTRING (external data type) 21-11 LPHSTRING (external data type)) 21-15 LPHWND (external data type) 21-23 LPINT (external data type) 21-10 LPLONG (external data type) 21-10 LPNUMBER (external data type) 21-10 LPSTR (external data type) 21-11, 21-13 LPVOID (external data type) 21-11, 21-15 LPWORD (external data type) 21-10
M
main window ActiveX Explorer menu 4-474-48 Component menu 4-204-21 Database Explorer menu 4-404-47 Debug menu 4-264-27 Edit menu 4-54-11 File menu 4-24-5 Help menu 4-494-50 Layout menu 4-214-26 menus see Chapter 4 Project menu 4-114-20 Tools menu 4-284-40 Window menu 4-484-49 marshaling defined G-12 MDI (Multiple Document Interface) defined G-12 MDI windows 5-6, 5-125-17 attributes 5-13 automatically creating 5-13
hWndMDI 5-14, 7-14 SAM_Activate 9-6 SAM_Create 9-17 SAM_CreateComplete 9-18 SAM_Help 9-30 SAM_ReportFetchInit 9-32 SAM_ReportFetchNext 9-33 SAM_ReportFinish 9-34 SAM_ReportNotify 9-34 SAM_ReportStart 9-35 SAM_Timer 9-41 table window 9-12 Windows menu 5-16, 6-7, 6-9 menu bar docking 2-5 resizing 2-7 undocking 2-5 Menu Editor 6-10 Menu Editor (Component menu) 4-20 menus see Chapter 6 adding 6-2 cascading 6-5 defined G-12 menu columns 6-6 menu item defined G-13 menu items 6-3 accelerators 6-3 Checked When 6-4 Enabled When 6-4 Menu Actions 6-4 mnemonics 6-3 SalDrawMenuBar 6-4 menu rows 6-6 menu separators 6-5 named menus 6-7 predefined 6-8 popup 6-2 creating dynamically 6-8 defined G-14 Enabled When 6-2 mnemonics 6-2 SalDrawMenuBar 6-2 SalTrackPopupMenu 6-8 status text 5-45, 6-2, 6-3, 6-9 SalTrackPopupMenu 5-45, 6-9 Windows menu 5-16, 6-7, 6-9
Index-15
Index
Merge (Component menu) 18-5 Merge Libraries (Component menu) 4-21 Message Actions 5-6 defined G-13 message actions in classes 8-26 multiple inheritance 8-29 single inheritance 8-26 message boxes 5-46 messages 1-5, 9-2 see Chapter 9 application-defined 9-3 defined G-13 lParam 7-14, 9-6 names 9-2 nonqueued 9-3 numbers 9-2 posting 9-3 processing 9-4 queued 9-3 SAM_* 9-2, 9-6 sending 9-3 system variables 9-5 types 9-2 WM_* 9-4 wParam 7-14, 9-6 Messages (Help menu) 4-49 Messages (Tools menu) 4-39 Messages window 10-6 MetaFile defined G-13 method defined G-13 mnemonics 5-18 background text 5-19 data fields 5-23 defined G-13 menu items 6-3 popup menu 6-2 modal dialog boxes 5-9 defined G-13 modeless dialog boxes 5-9 defined G-13 Most recently open (File menu) 4-5 mouse pointer defined G-13 Move Down (Edit menu) 4-7 Move Left (Edit menu) 4-7
Move Right (Edit menu) 4-7 Move Up (Edit menu) 4-7 MTS (Microsoft Transaction Server) 20-34 defined G-13 MTS object defined G-13 MTX server defined G-13 multiline fields 5-255-26 attributes 5-25 data types 5-25 enabling and disabling 5-26 hiding and showing 5-25 maximum data length 5-25 SalDisableWindow 5-26 SalEnableWindow 5-26 SalHideWindow 5-25 SalShowWindow 5-25 SAM_AnyEdit 9-6 SAM_DragCanAutoStart 9-21 SAM_DragDrop 9-22 SAM_DragEnd 9-22 SAM_DragEnter 9-23 SAM_DragExit 9-23 SAM_DragMove 9-24 SAM_DragNotify 9-24 SAM_DragStart 9-25 SAM_DropFiles 9-26 SAM_FieldEdit 9-30 SAM_KillFocus 9-31 SAM_Print 9-32 SAM_SetFocus 9-39 SAM_Validate 9-41 multiple inheritance 8-5 multiuser defined G-13 MyValue 7-14, 8-54
N
named cursors 12-45 named menus 6-7 Named Menus (outline item) 2-10 naming conventions constants 7-20 objects 5-4 variables 7-19 nArgCount 7-15, 7-32 New (Component menu) 4-20
New (Database Explorer menu) 4-40 New (File menu) 4-2 new keyword 8-23, 20-22 NEWAPP.APP 6-8 Next Error (Project menu) 4-12 No Animate (Debug menu) 4-27 normal storage format (applications) 4-4 notation conventions 1-18 null defined G-13 NUMBER (external data type) 21-9 Number data type 7-7 formats 11-2, 11-4 input masks 11-11 internal format 7-7 NUMBER_Null 7-7 validation 11-8 OBJ_Null 8-23, 20-22, 20-23 Object Compiler configuring 4-15 object destructors 8-23 Object Nationalizer 4-14 introduction 1-2 ObjectDestructor 8-23 object-oriented programming see Chapter 8 defined G-14 object-qualified references 23-8, 23-10 objects 1-2, 1-5 see Chapter 5 accelerators 5-18 adding 5-2 Coding Assistant 5-2 Controls palette 5-2 aligning 4-22 attributes 2-16, 5-4 class-based 8-2 color 5-47 Contents 5-6, 5-17 defined G-13 fonts 5-47 Functions 5-6 Message Actions 5-6 mnemonics 5-18 mouse pointers 5-3 naming conventions 5-4
properties 5-4 SAM_* messages 5-6 selection handles 4-23 sizing evenly 4-24 spacing evenly 4-23 tab order 4-25 top-level 5-5, 5-17 variables 5-50 Window Variables 5-6 obsolete functions 3-6 ODBC (Open DataBase Connectivity) defined G-14 OLE see COM clients or COM servers OLE DB consumer 12-26 see Chapter 13 connecting to a data source 13-3 password 13-3 server name 13-3 Session Handle 7-7, 13-2, 13-3 session properties 13-3 SqlClearImmediate 13-7 SqlCloseAllSPResultSets 13-4, 13-7 SqlCommit 13-7 SqlCommitSession 13-4, 13-7 SqlConnect 13-7 SqlConnectUsingCursor 13-7 SqlCreateSession 13-3, 13-4, 13-7 SqlCreateStatement 13-3, 13-4, 13-5, 13-7 SqlDisconnectWithoutCursor 13-8 SqlDropStoredCmd 13-8 SqlExists 13-8 SqlFreeSession 13-3, 13-5 SqlGetCmdOrRowsetPtr 13-5, 13-7, 13-8 SqlGetCursor 13-8 SqlGetDSOrSessionPtr 13-5, 13-7, 13-8 SqlGetErrorText 13-8 SqlGetErrorTextX 13-8 SqlGetNextSPResultSet 13-5, 13-7 SqlGetSessionErrorInfo 13-5 SqlGetSessionHandle 13-5 SqlGetSessionParameter 13-6 SqlGetStatementErrorInfo 13-6 SqlImmediate 13-8 SqlImmediateContext 13-8 SqlPLSQLCommand 13-8 SqlPrepareSP 13-6, 13-7 SqlRollbackSession 13-6
Index-17
Index
SqlSetIsolationLevel 13-8 SqlSetSessionParameter 13-6, 13-8 SqlStore 13-8 stored procedures 13-7 unsupported functions 13-7 user ID 13-3 OLE DB provider 13-2, 13-3 OLE DB providers 13-4 OLE Documents defined G-14 On statement 7-23 Open (File menu) 4-3 Open Library (ActiveX Explorer menu) 4-47 Open Windows List (Window menu) 4-49 operators 7-20 defined G-14 optimizing applications 4-14 option buttons 5-315-35 attributes 5-31 hiding and showing 5-31 images 5-33 SalHideWindow 5-31 SalShowWindow 5-31 SAM_Click 9-10 SAM_KillFocus 9-31 SAM_SetFocus 9-39 styles 5-32 Oracle 12-17 outline 2-8 Application Actions 2-10 Application Description 2-9 Class Definitions 2-10, 7-29 collapsing 4-7 Constants 2-10 Contents 5-6, 5-17 defined G-14 Design-time Settings 2-9 expanding 4-6 External Functions 2-10, 21-4 Formats 2-10 Functions 5-6 Global Declarations 2-10 Internal Functions 2-10, 7-29 Libraries 2-9 Menu Actions 6-4 Message Actions 5-6 Named Menus 2-10, 6-7 Resources 2-10
Variables 2-10 Window Defaults 2-10 Window Parameters 5-51 Window Variables 5-6 Outline (Edit menu) 4-6 outline items defined G-14 Outline tab font 4-33 text enhancements 4-33 Output (Tools menu) 4-37 output message buffer 12-36 owned dialog boxes 5-10, 5-11 ownerless dialog boxes 5-10, 5-11
P
Page Settings (File menu) 4-4 palettes docking 2-5 resizing 2-7 undocking 2-5 parameter defined G-14 Parameter Info 2-21 Parameters tab 2-13 pass by reference 7-30, 21-7 pass by value 7-30, 21-7 Paste (Edit menu) 4-6 picture messages 16-4 storing in a database 16-9 pictures see Chapter 17 attributes 16-2 enabling and disabling 16-2 functions 16-5 hiding and showing 16-2 SalDisableWindow 16-2 SalEditCanCopyTo 16-5 SalEditCopyTo 16-5 SalEditPasteFrom 16-6 SalEnableWindow 16-2 SalHideWindow 16-2 SalPicClear 16-11 SalPicGetDescription 16-10 SalPicGetString 16-7, 16-9, 16-10 SalPicSet 16-10 SalPicSetFile 16-7
SalPicSetFit 16-11 SalPicSetString 16-7, 16-9 SalSetFieldEdit 16-11 SalShowWindow 16-2 SAM_Click 9-10, 16-4 SAM_DoubleClick 9-20, 16-4 SAM_DragCanAutoStart 9-21 SAM_DragDrop 9-22 SAM_DragEnd 9-22 SAM_DragEnter 9-23 SAM_DragExit 9-23 SAM_DragMove 9-24 SAM_DragNotify 9-24 SAM_DragStart 9-25 SAM_DropFiles 9-26 Playback (Debug menu) 4-27 Playback Rewind (Debug menu) 4-27 polymorphism defined G-14 pooling defined G-14 populate defined G-14 popup menus see menus, popup precedence defined G-14 Preferences (Tools menu) 4-32 preview mode 2-12 Preview window 2-12 Preview Window (Layout menu) 4-21 Previous Error (Project menu) 4-12 Print (File menu) 4-5 printing SAM_Print 9-32 production applications 3-2 profile defined G-14 Project menu Build 4-20 Build Settings 4-13 Check In 4-12 Check Out 4-11 Compile 4-12 Execute 4-12 Next Error 4-12 Previous Error 4-12 Register Server 4-12
Unregister Server 4-12, 4-13 properties 2-16, 5-4 Properties (Edit menu) 4-9 property defined G-14 proxy defined G-15 push buttons 5-265-29 accelerators 5-27, 5-28 attributes 5-26 hiding and showing 5-27 pictures 5-27, 5-28 SalHideWindow 5-27 SalShowWindow 5-27 SAM_Click 9-10 SAM_KillFocus 9-31 SAM_Print 9-32 SAM_SetFocus 9-39 qualified references 23-2, 23-7 query defined G-15 Query (Database Explorer menu) 4-44 Quick Info 2-22, 10-10 QuickObject Editor (Component menu) 4-20 QuickObjects (Help menu) 4-49 radio buttons 5-305-31 attributes 5-30 hiding and showing 5-30 SalHideWindow 5-30 SalShowWindow 5-30 SAM_Click 9-10 SAM_KillFocus 9-31 SAM_SetFocus 9-39 receive data types 7-2, 7-30, 21-7 defined G-15 references see Chapter 24 class-qualified 23-13, 23-14 early-bound 23-7 external 23-2, 23-15 handle-qualified 23-12, 23-17 late-bound 23-7 object-qualified 23-8, 23-10 qualified 23-2, 23-7
Index-19
Index
settings 23-14 unqualified 23-7 Refresh (ActiveX Explorer menu) 4-47 Refresh (Component menu) 18-5 Refresh Libraries (Component menu) 4-21 Register Server (Project menu) 4-12 Reject Multiple Window Instances 4-10 relational databases see chapter 12 Replace (Edit menu) 4-8 Report Builder 14-2 defined G-15 Report Builder (Tools menu) 4-39 reports see Chapter 13 blocks 14-4 creating from table windows 14-20 error handling 14-8 input items 14-4 input variables 14-4, 14-17 runtime environment 14-5 SalReportClose 14-17 SalReportCmd 14-13 SalReportCreate 14-17 SalReportDlgOptions 14-9 SalReportGetDateTimeVar 14-18 SalReportGetNumberVar 14-18 SalReportGetObjectVar 14-18 SalReportGetStringVa 14-18 SalReportPrint 14-6, 14-7 SalReportPrintToFile 14-12 SalReportReset 14-15 SalReportSetDateTimeVar 14-18 SalReportSetNumberVar 14-18 SalReportSetObjectVar 14-18 SalReportSetStringVar 14-18 SalReportTableCreate 14-20 SalReportTablePrint 14-21 SalReportTableView 14-21 SalReportView 14-6, 14-12 SAM_ReportFetchInit 14-6 SAM_ReportFetchNext 14-7 SAM_ReportFinish 14-7 SAM_ReportNotify 14-18 SAM_ReportStart 14-6 templates 14-3 resources (bitmaps, icons, cursors) 7-34 Resources (outline item) 2-10
result set defined G-15 result sets 12-9 Return statement 7-24 Returns tab 2-13 Right (Layout menu) 4-23 right mouse button 2-13 ROLLBACK statement 12-9, 12-12, 12-25 row defined G-15 ROWIDs 12-38 RPC (Remote Procedure Call) defined G-15 RTF (Rich Text Format) defined G-15 run mode 10-2 defined G-15 runtime 1-4 defined G-15
S
safe reference defined G-15 SAL (SQLWindows Application Language) 1-3 see Chapter 7 defined G-15 SalActiveXAutoErrorMode 19-29, 19-38 SalActiveXClose 19-29 SalActiveXCreate 19-29 SalActiveXCreateFromData 19-29 SalActiveXCreateFromFile 19-29 SalActiveXDelete 19-29 SalActiveXDoVerb 19-30 SalActiveXGetActiveObject 19-29 SalActiveXGetData 19-30 SalActiveXGetFileName 19-30 SalActiveXGetObject 19-30 SalActiveXGetProgID 19-30 SalActiveXInsertObjectDlg 19-30 SalActiveXOLEType 19-30 SalArrayAvg 7-18 SalArrayDimCount 7-18 SalArrayGetLowerBound 7-18 SalArrayGetUpperBound 7-18 SalArrayIsEmpty 7-18 SalArrayMax 7-18 SalArrayMin 7-18 SalArraySetUpperBound 7-18
SalArraySum 7-18 SalColorGet 15-45 SalColorSet 15-45 SalCompileAndEvaluate 10-11, 10-12 SalContextCurrent 10-12 SalCreateWindow 5-49 dialog boxes 5-9 form windows 5-7 MDI windows 5-13 table windows 15-3 window parameters 5-51 SalCursorSet 7-34 SalCursorSetFile 17-5 SalDestroyWindow 9-12 dialog boxes 5-9 SalDisableWindow columns 15-9 combo boxes SalDisableWindow 5-40 data fields 5-24 multiline fields 5-26 pictures 16-2 SalDlgChooseColor 5-46 SalDlgChooseFont 5-46 SalDlgOpenFile 5-46 SalDlgSaveFile 5-46 SalDragDropDisableDrop 17-3, 17-4 SalDragDropEnableDrop 17-4 SalDragDropGetSource 17-4 SalDragDropGetTarget 17-4 SalDragDropStart 17-3, 17-5 SalDragDropStop 17-5 SalDrawMenuBar 6-2, 6-4 SalDropFilesAcceptFiles 17-10 SalDropFilesQueryFiles 9-26, 17-10 SalDropFilesQueryPoint 9-26, 17-10 SalEditCanCopyTo 16-5 SalEditCanCut 15-50, 16-5 SalEditCanPaste 7-33, 15-50, 16-5 SalEditCanUndo 16-5 SalEditClear 16-5 SalEditCopy 7-33, 15-50, 16-5 SalEditCopyString 7-33 SalEditCopyTo 16-5 SalEditCut 7-33, 15-50 SalEditPaste 7-33, 15-50, 16-5 SalEditPasteFrom 16-6 SalEditPasteString 7-33
SalEditUndo 16-5 SalEnableWindow columns 15-9 combo boxes 5-40 data fields 5-24 multiline fields 5-26 pictures 16-2 SalEndDialog 5-10, 9-12 SalFmtGetInputMask 11-13 SalFmtKeepMask 11-13 SalFmtSetInputMask 11-13 SalFontGet 15-45 SalFontSet 15-45 SalFormUnitsToPixels 5-48 SalGetFirstChild 5-49 SalGetNextChild 5-49 SalGetUDVData 21-35 SalGetWindowText 15-44 SalHideWindow check boxes 5-36 columns 15-8 combo boxes 5-39 data fields 5-23 list boxes 5-37 multiline fields 5-25 option buttons 5-31 pictures 16-2 push buttons 5-27 radio buttons 5-30 scroll bars 5-42 table windows 15-5 SalIsNull 11-14 SalListPopulate combo boxes 12-27 list boxes 12-27 with stored commands 12-42 SalLoadApp command line arguments 7-32 SalMDIArrangeIcons 5-16 SalMDICascade 5-15 SalMDITile 5-15 SalMessageBox 5-10, 5-46 SalModalDialog 5-9, 5-10 window parameters 5-51 SalMTSCreateInstance 20-37 SalMTSDisableCommit 20-37 SalMTSEnableCommit 20-37 SalMTSGetObjectContext 20-37
Index-21
Index
SalMTSIsInTransaction 20-37 SalMTSIsSecurityEnabled 20-37 SalMTSSetAbort 20-37 SalMTSSetComplete 20-37 SalNumberToWindowHandle 9-9 SalObjCreateFromString 8-24 SalObjGetType 8-24 SalObjIsDerived 8-24 SalObjIsNull 8-23, 8-24, 20-23 SalObjIsValidClassName 8-54 SalParentWindow 5-16 SalPicClear 16-11 SalPicGetDescription 16-10 SalPicGetString 16-6, 16-7, 16-9, 16-10 SalPicSet 7-34, 16-10 SalPicSetFile 16-7 SalPicSetFit 16-11 SalPicSetString 16-7, 16-9 SalPixelsToFormUnits 5-48 SalPostMsg 9-3 SalQueryArrayBounds 15-19 SalQueryFieldEdit 15-51, 16-11 SalQuit 9-12 SalReportClose 14-17 SalReportCmd 14-13 SalReportCreate 14-17 SalReportDlgOptions 14-9 SalReportGetDateTimeVar 14-18 SalReportGetNumberVar 14-18 SalReportGetObjectVar 14-18 SalReportGetStringVar 14-18 SalReportPrint 9-35, 14-6, 14-7 SalReportPrintToFile 14-12 SalReportReset 14-15 SalReportSetDateTimeVar 14-18 SalReportSetNumberVar 14-18 SalReportSetObjectVar 14-18 SalReportSetStringVar 14-18 SalReportTableCreate 14-20 SalReportTablePrint 14-21 SalReportTableView 14-21 SalReportView 9-35, 14-6, 14-12 SalSendMsg 9-3 SalSendMsgToChildren 9-3 SalSendValidateMsg 11-9 SalSetErrorInfo 20-23 SalSetFieldEdit 15-51, 16-11 SalSetWindowText 15-44
SalShowWindow check boxes 5-36 columns 15-8 combo boxes 5-39 data fields 5-23 list boxes 5-37 multiline fields 5-25 option buttons 5-31 pictures 16-2 push buttons 5-27 radio buttons 5-30 scroll bars 5-42 table windows 15-5 SalStatusGetText 5-45 SalStatusSetText 5-45 SalStatusSetVisible 5-45 SalStrGetBufferLength 21-16 SalTBarSetVisible 5-44 SalTblAnyRows 15-14, 15-15, 15-17 SalTblClearSelection 15-44 SalTblColumnAverage 15-33, 15-46 SalTblColumnSum 15-32, 15-46 SalTblCopyRows 7-33, 15-51 SalTblCreateColumn 15-31, 15-46 SalTblDefineRowHeader 9-36, 15-5, 15-47, 15-48 SalTblDefineSplitWindow 15-49 SalTblDeleteRow 15-20, 15-51 SalTblDeleteSelected 15-14 SalTblDestroyColumns 15-32 SalTblDoDeletes 15-14 SalTblDoInserts 15-15 SalTblDoUpdates 15-17 SalTblFetchRow 15-25 SalTblFindNextRow 15-16, 15-17, 15-22, 15-23, 1539, 15-40 SalTblFindPrevRow 15-40 SalTblGetColumnText 15-46 SalTblGetColumnTitle 15-45 SalTblGetColumnWindow 15-46 SalTblInsertRow 15-14, 15-21, 15-50 SalTblKillEdit 15-15, 15-17, 15-21, 15-23, 15-44 SalTblKillFocus 15-43 SalTblPasteRows 7-33, 15-50 SalTblPopulate 9-28, 15-13, 15-25, 15-26, 15-27, 15-30, 15-31 with stored commands 12-42 SalTblQueryColumnFlags 15-39 SalTblQueryColumnID 15-46
SalTblQueryColumnPos 15-46 SalTblQueryColumnWidth 15-45 SalTblQueryContext 15-20 SalTblQueryLockedColumns 15-47 SalTblQueryRowHeader 15-48 SalTblQueryScroll 15-44 SalTblQuerySplitWindow 15-49 SalTblQueryTableFlags 15-37 SalTblQueryVisibleRange 15-44 SalTblReset 15-18 SalTblScroll 15-44 SalTblSetCellTextColor 15-45 SalTblSetColumnFlags 15-39 SalTblSetColumnPos 15-46, 15-47 SalTblSetColumnText 15-46 SalTblSetColumnTitle 15-45 SalTblSetColumnWidth 15-45 SalTblSetContext 15-20, 15-22, 15-24, 15-25 SalTblSetFlagsAnyRows 15-16, 15-18, 15-39 SalTblSetFocusCell 15-15, 15-21, 15-43 SalTblSetFocusRow 15-43 SalTblSetLockedColumns 15-47 SalTblSetRange 15-19, 15-25, 15-28, 15-33, 15-34 SalTblSetRow 15-43 SalTblSetRowFlags 15-16, 15-17, 15-18, 15-22, 1524, 15-39 SalTblSetTableFlags 9-13, 15-37 SalTblSortRows 15-33, 15-46 SalTimerSet 9-41 SalTrackPopupMenu 6-8 menu status text 5-45, 6-9 SalUdvGetCurrentHandle 21-33 SalValidateSet 22-17, 22-19 SalWinHelp 9-30 SalYieldEnable 7-36 SalYieldQueryState 7-36 SalYieldStartMessages 7-35 SalYieldStopMessages 7-35 SAM (SQLWindows Application Messages) 1-3 see Chapter 9 defined G-16 SAM_AnyEdit 9-6, 15-42 SAM_AppExit 9-7 SAM_AppStartup 9-8 SAM_CacheFull 9-8, 15-36, 15-37 SAM_CaptionDoubleClick 9-9, 15-41 SAM_Click 9-10, 15-42, 16-4 SAM_Close 9-12, 15-43
SAM_ColumnSelectClick 9-13, 15-41 SAM_CornerClick 9-14, 15-48 SAM_CornerDoubleClick 9-14, 15-48 SAM_CountRows 9-16, 15-34 SAM_Create 9-17 custom controls 22-3 SAM_CreateComplete 9-17 SAM_CustControlCmd 9-18, 22-3 SAM_Destroy 5-15, 9-18 custom controls 22-3 SAM_DockChange 9-19 SAM_DoubleClick 9-20, 15-42, 16-4 SAM_DragCanAutoStart 9-21, 17-5 SAM_DragDrop 9-22, 17-6 SAM_DragEnd 9-22, 17-6 SAM_DragEnter 9-23, 17-6 SAM_DragExit 9-23, 17-6 SAM_DragMove 9-24, 17-7 SAM_DragNotify 9-24, 17-6 SAM_DragStart 9-25, 17-5 SAM_DropDown 9-26 SAM_DropFiles 9-26, 17-10 SAM_EndCellTab 9-27, 15-41 SAM_FetchDone 9-28, 15-28 SAM_FetchRow 9-28, 15-19, 15-28, 15-29, 15-30 SAM_FetchRowDone 9-29, 15-28, 15-30, 15-32 SAM_FieldEdit 9-30, 15-43 SAM_Help 9-30 SAM_KillFocus 9-31, 15-43 SAM_Print 9-32 SAM_ReportFetchInit 9-32, 14-6 SAM_ReportFetchNext 9-33, 14-7 SAM_ReportFinish 9-34, 14-7 SAM_ReportNotify 9-34, 14-18, 14-19 SAM_ReportStart 9-35, 14-6 SAM_RowHeaderClick 9-36, 15-48 SAM_RowHeaderDoubleClick 9-36, 15-48 SAM_RowValidate 9-37, 11-9, 15-42 SAM_ScrollBar 9-38 SAM_SetFocus 9-39, 15-43 SAM_SqlError 9-39, 12-18 SAM_Timer 9-41 custom controls 22-3 SAM_User 9-4 SAM_Validate 9-30, 9-41, 11-9, 11-14, 15-32, 15-43 custom controls 22-17 Save (File menu) 4-3 scope 23-2
Index-23
Index
defined G-16 scroll bars 5-415-42 attributes 5-42 hiding and showing 5-42 SalHideWindow 5-42 SalShowWindow 5-42 SAM_KillFocus 9-31 SAM_ScrollBar 9-38 SAM_SetFocus 9-39 section defined G-16 Select Case statement 7-24 SELECT statement 12-8, 12-9 Send To Back (Layout menu) 4-22 serialization defined G-16 server defined G-16 Session Handle data type 7-7, 12-25, 13-2, 13-3 Set statement 7-25 SGML (Standard Generalized Markup Language) defined G-16 shared property defined G-16 shortcuts 2-26 Show CoClasses (ActiveX Explorer menu) 4-48 Show Design Scroll Bars (Layout menu) 4-26 Show Enumerations (ActiveX Explorer menu) 4-48 Show Events (ActiveX Explorer menu) 4-48 Show Functions (ActiveX Explorer menu) 4-48 Show Get Properties (ActiveX Explorer menu) 4-48 Show Hidden Windows (Layout menu) 4-26 Show Interfaces (ActiveX Explorer menu) 4-48 Show Item Information (Component menu) 4-20, 18-5 Show Put Properties (ActiveX Explorer menu) 4-48 Show SAL Types (ActiveX Explorer menu) 4-48 Show Sample Text (Layout menu) 4-25 siblings defined G-16 silent.ini 3-4 single inheritance 8-4 single threaded apartment 4-18 single-user defined G-16 sizing pointer defined G-16 slow animate 4-27 speed 4-32
Slow Animate (Debug menu) 4-27 Small Icons (Component menu) 4-21 SQL (Structured Query Language) see Chapter 12 bind variables 12-6 character conversion 12-45 combo boxes 12-27 COMMIT statement 12-8, 12-9, 12-12, 12-25 database access cycle 12-3 database parameters 12-28 DBP_AUTOCOMMIT 12-25 DBP_PRESERVE 12-25 DCL (Data Control Language) 12-16 DDL (Data Definition Language) 12-13, 12-16 defined G-16 DELETE statement 12-12 DML (Data Manipulation Language) 12-12, 12-16 error processing 12-17 application-defined 12-18 default 12-18 ERROR.SQL 12-23 execution context 12-43 input message buffer 12-34 INSERT statement 12-12 INTO variables 12-6 isolation levels 12-37 list boxes 12-27 Long String 12-17 multistep interface 12-3, 12-4 multiuser databases 12-38 named cursors 12-45 output message buffer 12-36 result sets 12-9 ROLLBACK statement 12-9, 12-12, 12-25 ROWIDs 12-38 SAM_SqlError 12-18 SELECT statement 12-8, 12-9 single-step interface 12-3, 12-15 Sql Handle 12-5 multiple 12-13 SQL.INI 12-37 sqlcch 12-26 SqlClearImmediate 12-15 SqlClose 12-45 SqlCommitSession 12-25 SqlConnect 12-4, 12-5 SqlCreateSession 12-25 SqlCreateStatement 12-25
SqlDatabase 12-4 SqlDirectoryByName 12-28 SqlDisconnect 12-5 SqlDropStoredCmd 12-41 SqlError 12-20 SqlErrorText 12-20 SqlExecute 12-7 SqlExecutionPlan 12-28 SqlExists 12-28 SqlExtractArgs 12-20 SqlFetchNext 12-9 SqlFetchPrevious 12-9 SqlFetchRow 12-9 SqlFreeSession 12-25 SqlGetErrorPosition 12-20 SqlGetErrorText 12-21 SqlGetErrorTextX 12-21 SqlGetModifiedRows 12-12 SqlGetParameter 12-29 SqlGetParameterAll 12-29 SqlGetResultSetCount 12-9 SqlGetRollbackFlag 12-21 SqlGetSessionParameter 12-25, 12-27, 12-29 SqlImmediate 12-15 SqlIsolationLevel 12-37 SqlNoRecovery 12-33 SqlOpen 12-45 SqlOutMessage 12-34 SqlPassword 12-4 SqlPrepare 12-7 SqlPrepareAndExecute 12-7, 12-8 SqlResultSet 12-34 SqlRetrieve 12-41 SqlRollbackSession 12-25 SqlSetInMessage 12-29 SqlSetIsolationLevel 12-29, 12-37 SqlSetLockTimeout 12-29 SqlSetOutMessage 12-29 SqlSetParameterAll 12-29 SqlSetResultSet 12-9 SqlSetSessionParameter 12-26, 12-27, 12-29 SqlStore 12-41 SqlUser 12-4 SqlVarSetup 12-43 stored commands 12-41 chained 12-42 with SalListPopulate 12-42 with SalTblPopulate 12-42
table windows 12-27 testing statements 10-11 transactions 12-24 multi-connection 12-25 troubleshooting 12-45 UPDATE statement 12-12 variables in statements 7-14 When SqlError statement 12-18 Sql Handle defined G-16 Sql Handle data type 7-7, 12-5, 12-13 SQL Script (Database Explorer menu) 4-41 SQL Server 12-17 SQL.INI 12-37 SQL/API defined G-16 SQLBase 12-17 defined G-16 sqlcch 12-26 SqlClearImmediate 12-15, 13-7 SqlClose 12-45 SqlCloseAllSPResultSets 13-4, 13-7 SqlCommit 13-7 SqlCommitSession 12-25, 13-4, 13-7 SqlConnect 12-4, 12-5, 13-7 SqlConnectUsingCursor 13-7 SqlCreateSession 12-25, 13-3, 13-4, 13-7 SqlCreateStatement 12-25, 13-3, 13-4, 13-5, 13-7 SqlDatabase 12-4, 12-33 SqlDirectoryByName 12-28 SqlDisconnect 12-4, 12-5 SqlDisconnectWithoutCursor 13-8 SqlDropStoredCmd 12-41, 13-8 SqlError 12-20 SqlErrorText 12-20 SqlExecute 12-7 SqlExecutionPlan 12-28 SqlExists 12-28, 13-8 SqlExtractArgs 9-40, 12-20 SqlFetchNext 12-9 SqlFetchPrevious 12-9 SqlFetchRow 9-28, 12-9 SqlFreeSession 12-25, 13-3, 13-5 SqlGetCmdOrRowsetPtr 13-5, 13-7, 13-8 SqlGetCursor 13-8 SqlGetDSOrSessionPtr 13-5, 13-7, 13-8 SqlGetErrorPosition 12-20 SqlGetErrorText 12-21, 13-8
Index-25
Index
SqlGetErrorTextX 12-21, 13-8 SqlGetModifiedRows 12-12 SqlGetNextSPResultSet 13-5, 13-7 SqlGetParameter 12-29 SqlGetParameterAll 12-29 SqlGetResultSetCount 12-9 SqlGetRollbackFlag 12-21 SqlGetSessionErrorInfo 13-5 SqlGetSessionHandle 13-5 SqlGetSessionParameter 12-25, 12-27, 12-29, 13-6 SqlGetStatementErrorInfo 13-6 SqlImmediate 12-15, 13-8 SqlImmediateContext 13-8 SqlInMessage 12-33 SqlIsolationLevel 12-33, 12-37 SqlNoRecovery 12-33 sqlnwkcn.apl 12-27 SqlOpen 12-45 SqlOutMessage 12-34 SqlPassword 12-4, 12-34 SqlPLSQLCommand 13-8 SqlPrepare 12-7 SqlPrepareAndExecute 12-7, 12-8 SqlPrepareSP 13-6, 13-7 SqlResultSet 12-34 SqlRetrieve 12-41 sqlrlo 12-17 SqlRollbackSession 12-25, 13-6 SqlSetInMessage 12-29 SqlSetIsolationLevel 12-29, 12-37, 13-8 SqlSetLockTimeout 12-29 SqlSetOutMessage 12-29 SqlSetParameterAll 12-29 SqlSetResultSet 12-9 SqlSetSessionParameter 12-26, 12-27, 12-29, 13-6, 13-8 SqlStore 12-41, 13-8 SQLTalk (Tools menu) 4-40 SqlUser 12-4, 12-34 SqlVarSetup 8-54, 12-43 SQLWindows defined G-16 description 1-2 user interface 2-2 SQLWindows Application Language see SAL SQLWindows Application Messages see SAM
sqlwlo 12-17 standard dialogs 5-46 stateless object defined G-17 statements 7-21 Break 7-21 Call 7-22 defined G-17 Else 7-22 Else If 7-22 If 7-22 Loop 7-23 On 7-23 Return 7-24 Select Case 7-24 Set 7-25 When SqlError 7-26 While 7-26 static linking 21-3 static variables 7-30 defined G-17 Static Variables tab 2-13 statistics 4-9 applications 4-9 status bar 2-3 status bars 5-45 menu status text 5-45, 6-2, 6-3, 6-9 SalStatusGetText 5-45 SalStatusSetText 5-45 SalStatusSetVisible 5-45 Step Into 10-5 Step Into (Debug menu) 4-26 Step Over 10-5 Step Over (Debug menu) 4-26 Stop Debugging (Debug menu) 4-26 stored commands 12-41 with SalTblPopulate 15-31 Stored Procedure (Database Explorer menu) 4-43 stored procedures OLE DB consumer 13-7 strArgArray 7-15, 7-32 string defined G-17 String data type 7-8 formats 11-2 maximum length 7-8 structPointer (external data type) 21-23 stub
defined G-17 SWCustControlEditor 22-15 SWinCvtDoubleToNumber 21-9 SWinCvtIntToNumber 21-9 SWinCvtLongToNumber 21-9 SWinCvtNumberToDouble 21-9 SWinCvtNumberToInt 21-10 SWinCvtNumberToLong 21-10 SWinCvtNumberToULong 21-10 SWinCvtNumberToWord 21-10 SWinCvtULongToNumber 21-9 SWinCvtWordToNumber 21-9 SWinHStringLock 21-15 SWinHStringUnlock 21-15 SWinInitLPHSTRINGParam 21-15 SWinMDArrayDataType 21-19 SWinMDArrayGetBoolean 21-19 SWinMDArrayGetDateTime 21-19 SWinMDArrayGetHandle 21-19 SWinMDArrayGetHString 21-19 SWinMDArrayGetNumber 21-19 SWinMDArrayPutBoolean 21-19 SWinMDArrayPutDateTime 21-19 SWinMDArrayPutHandle 21-19 SWinMDArrayPutHString 21-20 SWinMDArrayPutNumber 21-20 SWinUdvLock 21-33 Sybase 12-17 symbol 23-2 symbol resolution 23-4 system constants 7-19 system functions 7-29 defined G-17 system modal dialog boxes 5-10 defined G-17 system variables 7-14 database 12-4, 12-33 relation to messages 9-5
T
Tab Order (Layout menu) 4-25 tab views 2-3, 2-7 table defined G-17 Table (Database Explorer menu) 4-42 table windows see Chapter 14 see also columns
adding columns 15-7 attributes 15-3, 15-5 automatically creating 15-3 averaging 15-32 cache 15-4, 15-6, 15-35 child 15-4 Clipboard 15-50 context row 15-24 creating reports 14-20 defined G-17 dynamic 15-31 flags 15-37 focus cell 15-44 focus frame 15-10 focus row 15-43 hiding and showing 15-5 icon 15-4 Max Rows in Memory 15-4, 15-6, 15-35 messages 15-40 moving columns 15-7 populating 15-25 programming techniques 15-12 row flags 15-38 row header 15-47 SalColorGet 15-45 SalColorSet 15-45 SalCreateWindow 15-3 SalFontGet 15-45 SalFontSet 15-45 SalGetWindowText 15-44 SalHideWindow 15-5 SalQueryFieldEdit 15-51 SalSetFieldEdit 15-51 SalSetWindowText 15-44 SalShowWindow 15-5 SalTblAnyRows 15-14, 15-15, 15-17 SalTblClearSelection 15-44 SalTblColumnAverage 15-33, 15-46 SalTblColumnSum 15-32, 15-46 SalTblCreateColumn 15-31, 15-46 SalTblDefineRowHeader 9-36, 15-5, 15-47, 15-48 SalTblDefineSplitWindow 15-49 SalTblDeleteRow 15-20, 15-51 SalTblDeleteSelected 15-14 SalTblDestroyColumns 15-32 SalTblDoDeletes 15-14 SalTblDoInserts 15-15 SalTblDoUpdates 15-17
Index-27
Index
SalTblFetchRow 15-25 SalTblFindNextRow 15-16, 15-17, 15-22, 15-23, 15-39, 15-40 SalTblFindPrevRow 15-40 SalTblGetColumnText 15-46 SalTblGetColumnTitle 15-45 SalTblGetColumnWindow 15-46 SalTblInsertRow 15-14, 15-21, 15-50 SalTblKillEdit 15-15, 15-17, 15-21, 15-23, 15-44 SalTblPopulate 9-28, 15-13, 15-25, 15-26, 15-27, 15-30, 15-31 SalTblQueryColumnFlags 15-39 SalTblQueryColumnID 15-46 SalTblQueryColumnPos 15-46 SalTblQueryColumnWidth 15-45 SalTblQueryContext 15-20 SalTblQueryRowHeader 15-48 SalTblQueryScroll 15-44 SalTblQuerySplitWindow 15-49 SalTblQueryTableFlags 15-37 SalTblQueryVisibleRange 15-44 SalTblReset 15-18 SalTblScroll 15-44 SalTblSetCellTextColor 15-45 SalTblSetColumnFlags 15-39 SalTblSetColumnPos 15-46, 15-47 SalTblSetColumnText 15-46 SalTblSetColumnTitle 15-45 SalTblSetColumnWidth 15-45 SalTblSetContext 15-22, 15-24, 15-25 SalTblSetFlagsAnyRows 15-16, 15-18 SalTblSetFocusCell 15-15, 15-21, 15-43 SalTblSetFocusRow 15-43 SalTblSetLockedColumns 15-47 SalTblSetRange 15-19, 15-25, 15-28, 15-33, 15-34 SalTblSetRowFlags 15-16, 15-17, 15-18, 15-22, 15-24, 15-39 SalTblSetTableFlags 9-13, 15-37 SalTblSortRows 15-33, 15-46 SAM_AnyEdit 15-42 SAM_CacheFull 9-8, 15-36, 15-37 SAM_CaptionDoubleClick 9-9, 15-41 SAM_Click 9-10, 15-42 SAM_Close 9-12, 15-43 SAM_ColumnSelectClick 9-13, 15-41 SAM_CornerClick 9-14, 15-48 SAM_CornerDoubleClick 9-14, 15-48 SAM_CountRows 9-16, 15-34
SAM_CreateComplete 9-17 SAM_DoubleClick 9-20, 15-42 SAM_EndCellTab 9-27, 15-41 SAM_FetchDone 9-28, 15-28 SAM_FetchRow 9-28, 15-19, 15-28, 15-29, 15-30 SAM_FetchRowDone 9-29, 15-28, 15-30, 15-32 SAM_FieldEdit 9-30, 15-43 SAM_KillFocus 9-31, 15-43 SAM_RowHeaderClick 9-36, 15-48 SAM_RowHeaderDoubleClick 9-36, 15-48 SAM_RowValidate 9-37, 11-9, 15-42 SAM_SetFocus 9-39, 15-43 SAM_Validate 15-32, 15-43 sizing columns 15-7 sorting 15-33 split windows 15-49 SQL functions 12-27 SqlFetchRow 9-28 summing 15-32 table range 15-33 TBL_Error 15-40 TBL_FillAllBackground 9-28 TBL_RowHdr_Visible 9-36 top-level 5-5, 15-3 user interface 15-9 validation 11-9 WM_* messages 15-52 TBL_FillAllBackground 9-28 TBL_RowHdr_Visible 9-36 TCP/IP defined G-17 Team Object Manager introduction 1-2 Team Object Manager (Tools menu) 4-39 template 23-5 templates 4-35 testing applications 4-12 text applications 4-4 this 8-39 thread defined G-17 thread local storage (TLS) 20-29 defined G-17 threading 4-18 custom settings 4-19 ThreadSafe 21-5 thumb defined G-17
TIFF (Tag Image File Format) defined G-18 Tile Horizontally (Window menu) 4-48 Tile Vertically (Window menu) 4-49 toolbars 2-4, 5-425-45 attributes 5-43 configuring 4-30 custom 2-7, 4-31 displaying 4-30 docking 2-5 resizing 2-7 SalTBarSetVisible 5-44 undocking 2-5 Toolbars (Tools menu) 4-30 Tools menu ActiveX Explorer 4-39 Add to List 4-46 Attribute Inspector 4-38 Browse All Classes 4-40 Call Stack 4-38 Coding Assistant 4-37 Controls 4-38 Database Explorer 4-39 Diff/Merge 4-40 Expressions 4-39 Messages 4-39 Output 4-37 Preferences 4-32 Report Builder 4-39 SQLTalk 4-40 Team Object Manager 4-39 Toolbars 4-30 User Tools 4-28 Variables 4-38 tooltips 4-30 Top (Layout menu) 4-23 top-level objects 5-5, 5-17 top-level window defined G-18 top-level windows SAM_Activate 9-6 SAM_Create 9-17 SAM_CreateComplete 9-17, 9-18 SAM_DragCanAutoStart 9-21 SAM_DragDrop 9-22 SAM_DragEnd 9-22 SAM_DragEnter 9-23 SAM_DragExit 9-23
SAM_DragMove 9-24 SAM_DragNotify 9-24 SAM_DragStart 9-25 SAM_Help 9-30 SAM_ReportFetchInit 9-32 SAM_ReportFetchNextt 9-33 SAM_ReportFinish 9-34 SAM_ReportNotify 9-34 SAM_ReportStart 9-35 SAM_Timer 9-41 transactions 12-24 multi-connection 12-25 tree view 2-3 type Information 4-19 type information defined G-18 type safe casting 8-22
U
UDVs (user-defined variables) 8-9 assigning 8-21 dynamic instantiation 8-23 new keyword 8-23 object destructors 8-23 passing to external functions 21-33 setting to null 8-23 Uncomment Items (Edit menu) 4-6 Undo (Edit menu) 4-6 unqualified references 23-7 Unregister Server (Project menu) 4-12, 4-13 UPDATE statement 12-12 URL defined G-18 User Tools (Tools menu) 4-28 user-defined windows 8-8
V
validation 11-7 see chapter 9 columns 11-10 combo boxes 11-10 custom 11-9 data field 11-10 Date/Time 11-8 default 11-8 input mask 11-10 input masks characters 11-11
Index-29
Index
Date/Time 11-12 functions 11-13 getting a fields value 11-12 Number 11-11 SalFmtGetInputMask 11-13 SalFmtKeepMask 11-13 setting a fields value 11-12 Number 11-8 SalIsNull 11-14 SalSendValidateMsg 11-9 SAM_RowValidate 11-9 SAM_Validate 11-9, 11-14 table windows 11-9 value defined G-18 variables data types 7-2 debugging 10-9 declaring 7-10, 7-11 defined G-18 how initialized 7-11 in SQL statements 7-14 naming conventions 7-19 objects 5-50 references 7-11 child symbols 7-13 duplicate symbols 7-12 multiple instances 7-13 system variables 7-14 when valid 7-11 Variables (outline item) 2-10 Variables (Tools menu) 4-38 Variables tab 2-12 Variables window 10-6 version information 4-16 Vertical Center (Layout menu) 4-23 View System Tables (Database Explorer menu) 4-47 visual editing defined G-18 Visual Studio debugging DLLs 21-33 Visual Toolchest (Help menu) 4-49
When SqlError statement 7-26, 12-18 While statement 7-26 Width (Layout menu) 4-24 window defined G-18 window classes 8-6, 8-10 Window Defaults (outline item) 2-10 Window Editor defined G-18 window functions 7-29 calling 7-31 defined G-18 writing 7-29 Window Grabber defined G-18 Window Handle defined G-18 getting 5-49 storing in arrays 7-18 Window Handle data type 5-49, 7-9 Window menu Cascade 4-48 Close All 4-49 Open Windows List 4-49 Tile Horizontally 4-48 Tile Vertically 4-49 window parameters 5-51 Window Variables 5-6 windows child 5-6, 5-9, 5-17, 5-42 WINDOWS.H 9-4 Wizards (Component menu) 4-20 WM_COMMAND 9-18 custom controls 22-4 WORD (external data type) 21-9 workgroup defined G-18 World-Wide Web defined G-18 wParam 7-14, 9-6 defined G-19
W
W3C (World Wide Web Consortium) defined G-18 watch variable 10-8 When SqlError 9-40
X
XML (Extensible Markup Language) defined G-19
Y
Y2K 7-6
Index-31