Professional Documents
Culture Documents
Training Guide
Copyright 2004 Data Access Corporation DATA ACCESS WORLDWIDE 14000 S.W. 119 Avenue Miami, Florida 33186 USA Revision Date: January 8, 2004 * This manual applies to Visual DataFlex Revision 9.1 Part No.: 917900 .
COPYRIGHT NOTICE Copyright 2004 DATA ACCESS CORPORATION. All rights reserved. No part of this publication may be reproduced, or distributed, transmitted, transcribed, stored in a retrieval system, or translated into any human or computer language, in any form or by any means, electronic, mechanical, magnetic, optical, manual, or otherwise, or disclosed to third parties without the express written permission of Data Access Corporation, 14000 SW 119 Avenue, Miami, Florida, 33186, USA.
DISCLAIMER Data Access Corporation makes no representation or warranties, expressed or implied, with respect to the software or this publication, or any Data Access Corporation product, including but not limited to warranties of merchantability or fitness for any particular purpose. Data Access Corporation reserves to itself the right to make changes, enhancements, revisions and alterations of any kind to this manual and / or its accompanying software without obligation to notify any person, institution, or organization of such changes, enhancements, revisions, and alterations.
TRADEMARKS DataFlex is a registered trademark of Data Access Corporation. Crystal Reports is a registered trademark of Seagate Corporation Microsoft Windows is a registered trademark of Microsoft. Multi-Edit is a registered trademark of American Cybernetics All other brand and product names are trademarks or registered trademarks of their respective companies.
Table of Contents
Table of Contents
Introduction ..................................................................................................................... 19
How to Use the Manual .........................................................................................................20 Classroom Environment: .......................................................................................................20 Self Taught Method: ..............................................................................................................20 Reading List To Excel Quickly..............................................................................................21
Table of Contents
Database Builders Lock........................................................................................................55 Using Context Sensitive Help ................................................................................................56 The Fields Tab.......................................................................................................................57 Good File Relationships are the Key! ....................................................................................57 The Index Tab........................................................................................................................58 The Parameters Tab ...............................................................................................................59
Table of Contents
Base Containers Tab page ...................................................................................................102 Data Containers Tab-page ...................................................................................................103 Non-Visible Tab page..........................................................................................................104 Object Placement Tools.......................................................................................................106 Alignment Palette Tool........................................................................................................107 Popup Menus .......................................................................................................................108 Arrange Objects Tool ..........................................................................................................109 Nudge Objects Tool.............................................................................................................110 Resolution Check Tool ........................................................................................................111 Object-Order Definition Tool ..............................................................................................112 Drag Lock ............................................................................................................................113 Lost Objects in the Studio (recovering objects not visible on screen) .................................115 Cutting & Pasting Objects to Different Containers..............................................................116 Anchors & Min/Max Size....................................................................................................118
Table of Contents
Manual Code That the Studio Can Read..............................................................................155 1. Manual Code in the .SRC file (via the Studio) ................................................................155 2. Manual Code in Visual Objects (via the Studio) .............................................................156 3. Manual Code in the DataDictionary Objects (via the Studio)..........................................157
Table of Contents
Entry & Exit Messages ........................................................................................................209 Auto-Assigning Numbers.....................................................................................................212 External Structure ................................................................................................................213
Table of Contents
10
Table of Contents
Self Access Method Works by Delegation ..........................................................................275 Relaying a Message (Breaking Encapsulation sort of)..................................................276 Neighborhoods.....................................................................................................................278 Broadcast Command............................................................................................................280 Delegate Send ......................................................................................................................281 Using Online Documentation Commands.........................................................................282 Changing Behavior of Existing Messages ...........................................................................283 Augmenting a Message........................................................................................................283 Canceling a Message ...........................................................................................................284 Overriding a Message ..........................................................................................................284 Adding (creating) a Message ...............................................................................................284 Using Online Documentation Procedures.........................................................................285 Using Online Documentation Class Hierarchy .................................................................286 Local Variables....................................................................................................................287 On_Key Commands.............................................................................................................288 Properties (creating) ............................................................................................................289 Properties (Set & Get Commands) ......................................................................................290 Object Properties .................................................................................................................290 Item Properties.....................................................................................................................291 Procedures ...........................................................................................................................292 Functions .............................................................................................................................293 Functions as Expressions .....................................................................................................294 Categories of Messages .......................................................................................................295 Delegation & the Importance of Container Objects.............................................................296 On Procedures (Events)....................................................................................................298 Using OnClick Event ...........................................................................................................299 Using OnActivateApp Event ...............................................................................................299 Using OnMaxText Event .....................................................................................................299 Creating Buttons ..................................................................................................................300 Creating Checkboxes & Radios ...........................................................................................301 Data Access Corporation 11
Table of Contents
Table of Contents
Lesson 13........................................................................................................................ 365 DDs Local Buffers & Procedures .......................................................................... 365
Changing Field Values - DataDictionarys Local Buffers ...................................................366 Optimizing Field_Exit_Msg ................................................................................................368 Important DataDictionary Procedures .................................................................................373 Procedure Creating ..............................................................................................................374 Procedure Update & Backout ..............................................................................................375 Functions Validate_Save & Validate_Delete.......................................................................376 Procedures Save_Main_File & Delete_Main_File ..............................................................377
Lesson 13 Lab ........................................................................................................... 378 Lesson 14........................................................................................................................ 385 Classes Within the Studio........................................................................................ 385
Building New Subclasses.....................................................................................................386 Switching Classes the Studio Uses ......................................................................................388 Creating SubClass Layering.................................................................................................389 Templates (Speeding Development)....................................................................................392 DFS files ..............................................................................................................................393 Saving a DFS: ......................................................................................................................394 Inserting a DFS ....................................................................................................................395
13
Table of Contents
DFO Files ............................................................................................................................396 Using Subclasses in the Studio ............................................................................................399 Local & Global directories ..................................................................................................401
Table of Contents
Lesson 2 - Discover Answers...............................................................................................447 Lesson 3 - Discover Answers...............................................................................................449 Lesson 4 - Discover Answers...............................................................................................452 Lesson 5 - Discover Answers...............................................................................................454 Lesson 6 - Discover Answers...............................................................................................455 Lesson 7 - Discover Answers...............................................................................................456 Lesson 8 - Discover Answers...............................................................................................457 Lesson 9 - Discover Answers...............................................................................................459 Lesson 10 - Discover Answers.............................................................................................463 Lesson 11 - Discover Answers.............................................................................................464 Lesson 12 - Discover Answers.............................................................................................465 Lesson 13 - Discover Answers.............................................................................................466 Lesson 14 - Discover Answers.............................................................................................468 Lesson 15 - Discover Answers.............................................................................................471 Lesson 16 - Discover Answers.............................................................................................472
Table of Contents
Table of Contents
17
Table of Contents
18
Introduction
Introduction
Discovering Visual DataFlex is a training guide designed to introduce users to Visual DataFlex object-oriented Windows programming. The manual was written for Visual DataFlex to be used in a classroom environment or as a Self-taught study guide. Visual DataFlex revision 9.1 will be required when using this manual since the packages and features of this revision are used. Some familiarity with DOS, Microsoft Windows and general computer skills is necessary to accomplish the labs. The manual covers items ranging from beginning to advanced level skills. Students with prior object oriented and or DataFlex programming experience may wish to jump over sections. Review the topics covered in a Lesson to determine if you wish to skip a lesson. If you do skip Lessons, the Lab sections normally will have to be completed since each Lab builds on prior work.
19
Introduction
DOS Object Oriented Programmers Appendix C OOP Core Information Prior VDF Users Appendix C Prior VDF Users
Classroom Environment: A hands-on classroom is the recommended setting for using this manual. The Self-study method is possible, but classroom interaction and the aid of an instructor will enhance the learning process. If you are interested in locating a class near you, please call one of our Training Centers. Visit our Web site for contact information.
Self Taught Method: This manual can also be used as a Self-study guide. Before beginning, check the next few pages to ensure you have all needed equipment/software. The manual is broken up into Lessons, Labs and Did You Discover? questions. The Did You Discover? sections are NOT quizzes! Some of the topics are not even covered in the lesson. They are intended as extra information and to challenge the students. Do not use them as a test of your knowledge, but as an additional learning tool to cover more information. You will find the answers to these questions in Appendix A. Included on the training CD that comes with the training manual is a FinishedExampleZip.Exe file. This Self-extracting zip file contains all the files created throughout the course of the manual, as they will appear at the end of the manual. If you have any problems, unzip this file into a separate directory so you may compare your files to them.
20
Introduction
21
Introduction
More books to read: Book Title The Windows Guidelines for software design Visual Interface Design Windows 32 API Bible XML in 24 Hours MSDN (internet) Ask your Bookstore for this ISBN number 1-55615-679-0 0-471-13419-8 1-57169-009-3 0672319500
http://msdn.microsoft.com
22
Lesson 1
Getting Ready
This lesson ensures that we have the required equipment and software. The setup CD that comes with this manual has all the needed files that are used throughout the manual
23
Requirements
Computer Intel Pentium based PC or higher Computer mouse installed 32 Meg RAM (64 MB NT; 2000; XP; 2003) bare minimum Microsoft Windows 98 SE; ME; NT4; 2000, XP, 2003 Visual DataFlex revision 9 .1 with Documentation installed. (200 MB Hard Disk space required for full installation) Crystal Reports & DataFlex for Crystal Driver (this is optional if you do not have these products you may skip this section in the reporting lesson) SVGA 800x600 or higher resolution
Figure 1
Note: The Workspace Wizard uses theProjects folder as the default location for new workspaces. This manual will use this projects directory, but it is suggested that you change this location and point it to an area where you wish all your development work to be done.
* New service packs (when available) can be downloaded from http://www.dataaccess.com/ web page from the Download pull-down area.
24
Symbols: Many look very similarattention to detail is necessary! Symbol Description Click the right mouse button. Click the left mouse button. Double click the left mouse button. Press the Escape Key. Press the Enter Key (Return Key) Control Key Press the Shift Key Press the Tab Key Press the Page Up Key Press the Page Down Key Left Dragging: Hold left mouse key down while moving the mouse to a new location and then releasing.
] [ / E R C S T u d ;
25
Informative Text:
Informative data will be displayed in this font and will be used to explain topics. Do not confuse informative text with instructions/commands. Text in this printing style is used to explain topics. Even if screen shots are included no action is required on your computer.
Code:
The lab exercises will be making many modifications to the generated code. A file called Code_Mod.TXT is available on the CD that accompanies this manual. When asked to make code modifications, open this file in your editor and cut and paste the modifications into the application. Code Available = Code_Mod.TXT
Object Outer_container is a dbcontainer3d // Areas that are shadowed are areas of interest, // or to show where code has been added or modified. // The comment partial code addition/modification will appear next to addition/modification partial // a line when only part of the code has been added or modified. Object Customer_Name is a dbForm Set Location to 5 12 Set Size to 45 5 : // A colon is used to show the code has been abbreviated End_Object
Notes:
Notes will be displayed like this. If a note is directed to only certain students (example: for users of prior revisions of DataFlex) it will state this in parentheses at the beginning of the note so students can skip over notes that do not pertain to them.
26
Naming Conventions
It is recommended that you use Hungarian notation when naming classes; objects; properties; constants and variables. This will increase readability of your code and will eliminate the problem of duplicating names.
Prefix c o p C_ g
Meaning Class Object Property Constant Global variable Local variable (no prefix) SubPrefix (for properties; constants; global and local variables b d h i n r s v Sub-SubPrefix (for handles) ho ie
Sample cSuperEditor oPrintButton piCounter C_Version gsMaxUsers iTeamCount Meaning Boolean (true/false) Date Handle Integer Number Real String Variant Handles for object IDs Integer enumerators*
All prefixes except for Constants (C_) are lowercase. * Enumerators are the replacement value of a parameter constant.
27
Lesson 1 Lab
Description: Preparation work to get hardware and software ready:
Tasks: Ensure that your computer has VDF 9.1 installed and you meet all the hardware and software requirements listed in this lesson.
28
Sample Name A Local Boolean Variable A Local Integer Variable A Global Integer Variable A Global String Variable A Class An Object An Integer Property A String Property A Variant Property A Constant A Local Integer Variable (used to hold an object ID)
29
30
Lesson 2
Creating Workspaces & Database Files
This lesson gives a brief outline of the application to be created. Creating workspaces and the use of Database Builder for creating the database structure are covered.
31
5. Create Templates 6. Create complex Views (add manual code to increase functionality) 7. Add more bells and whistles to our existing application 8. Create Batch Processing 9. Multiple methods of creating reports
32
Note: The Company file will NOT be added until a later lesson.
33
INDEX# FIELDS DES U/C ------ --------------- --- --1 CODE NO YES
34
----------------------------------------------------------------------------DATE: 06/01/2002 TIME: 12:38 PAGE: 1 FILE DEFINITION FOR FILE: DEPT (# 10) ----------------------------------------------------------------------------DRIVER NAME : DATAFLEX FILE ROOT NAME : Dept USER DISPLAY NAME : Dept DATAFLEX FILE NAME : DEPT ----------------------------------------------------------------------------RECORD LENGTH : 1152 ( USED: 1053 ) MAX NUMBER OF RECORDS : 100 ( USED: 3 ) FILE COMPRESSION : NONE RE-USE DELETED SPACE : YES In another lab, we will add LOCKING TYPE : FILE HEADER INTEGRITY CHECKING : YES another field and link it to TRANSACTION TYPE : CLIENT ATOMIC RECORD IDENTITY INDEX : 0 ( 0 , 0 ) the Company file. FILE LOGIN PARAMETER : SYSTEM FILE : NO ----------------------------------------------------------------------------NUM --1 2 3 4 5 FIELD NAME --------------DEPT_CODE NAME NUMBER_OF_EMPL BUDGET COMMENTS TYPE SIZE OFFST IX ---- ----- ----- -ASC 4 1 1 ASC 20 5 NUM 2.0 25 2 NUM 6.2 26 TEX 1024 30 RELATES TO FILE.FIELD ---------------------------------
INDEX# FIELDS DES U/C ------ --------------- --- --1 DEPT_CODE NO YES 2 NUMBER_OF_EMPL RECNUM NO NO NO NO
LENGTH LEVELS SEGMENTS MODE ------ ------ -------- ------4 1 1 ON-LINE 4 1 2 ON-LINE
35
DEPT.FIELD_1 (10,1)
INDEX# FIELDS DES U/C ------ --------------- --- --1 CODE NO NO 2 3 LAST_NAME FIRST_NAME DEPT LAST_NAME FIRST_NAME SOC_SEC_NUMBER LOGGED LAST_NAME FIRST_NAME RECNUM SOC_SEC_NUMBER NO NO NO NO NO NO NO NO NO NO NO YES YES YES YES YES NO NO NO NO NO NO
LENGTH LEVELS SEGMENTS MODE ------ ------ -------- ------2 2 1 ON-LINE 40 53 4 5 2 4 ON-LINE ON-LINE
44
ON-LINE
ON-LINE
36
----------------------------------------------------------------------------DATE: 06/01/2002 TIME: 12:38 PAGE: 1 FILE DEFINITION FOR FILE: TIMECARD (# 60) ----------------------------------------------------------------------------DRIVER NAME : DATAFLEX FILE ROOT NAME : TimeCard USER DISPLAY NAME : TimeCard DATAFLEX FILE NAME : TIMECARD ----------------------------------------------------------------------------RECORD LENGTH : 384 ( USED: 265 ) MAX NUMBER OF RECORDS : 10000 ( USED: 0 ) FILE COMPRESSION : NONE RE-USE DELETED SPACE : YES LOCKING TYPE : FILE HEADER INTEGRITY CHECKING : YES TRANSACTION TYPE : CLIENT ATOMIC RECORD IDENTITY INDEX : 0 ( 0 , 0 ) FILE LOGIN PARAMETER : SYSTEM FILE : NO ----------------------------------------------------------------------------NUM --1 2 3 4 5 6 7 FIELD NAME --------------EMPL_CODE DATE HOURS MINUTES IN_OR_OUT MEMO REASON_CODE TYPE SIZE OFFST IX ---- ----- ----- -NUM 4.0 1 1 DAT 6 3 1 NUM 2.0 6 1 NUM 2.0 7 1 ASC 1 8 3 TEX 256 9 ASC 1 265 4 DES --NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO U/C --NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO RELATES TO FILE.FIELD --------------------------------EMPL.FIELD_1 (20,1)
INDEX# FIELDS ------ --------------1 EMPL_CODE DATE HOURS MINUTES IN_OR_OUT RECNUM 2 DATE HOURS MINUTES EMPL_CODE RECNUM IN_OR_OUT EMPL_CODE RECNUM REASON_CODE EMPL_CODE RECNUM
10
ON-LINE
ON-LINE
ON-LINE
37
ON-LINE
38
----------------------------------------------------------------------------DATE: 06/01/2002 TIME: 12:38 PAGE: 1 FILE DEFINITION FOR FILE: SYSFILE (# 200) ----------------------------------------------------------------------------DRIVER NAME : DATAFLEX FILE ROOT NAME : SysFile USER DISPLAY NAME : SysFile DATAFLEX FILE NAME : SYSFILE ----------------------------------------------------------------------------RECORD LENGTH : 39 ( USED: 39 ) MAX NUMBER OF RECORDS : 1 ( USED: 0 ) FILE COMPRESSION : NONE RE-USE DELETED SPACE : YES LOCKING TYPE : FILE HEADER INTEGRITY CHECKING : YES TRANSACTION TYPE : CLIENT ATOMIC RECORD IDENTITY INDEX : 0 ( 0 , 0 ) FILE LOGIN PARAMETER : SYSTEM FILE : YES ----------------------------------------------------------------------------NUM --1 2 3 FIELD NAME --------------CORP_NAME LAST_EMPL_NUM LOCAL_STATE TYPE SIZE OFFST IX ---- ----- ----- -ASC 35 1 NUM 4.0 36 ASC 2 38 RELATES TO FILE.FIELD ---------------------------------
39
Workspace Subdirectories
A workspace is the work area for your application. Workspace subdirectories will keep all of our application files neatly separated. The directory structure after a new workspace is created for the ABC Corporation would have eight subdirectories (AppHtml; AppSrc; Bitmaps; Data; DDSrc; Help; IdeSrc; Programs).
Figure 2
Used by the Workspace the Look at Wizards as the default area options to create the workspace dialog Close the
Figure 3
Note Keeping the workspace name and application name the same will simplify things. 40 Data Access Corporation
To separate your many applications into structured grouping you can create multiple divisions to organize your workspaces. The Order workspace is organized under the DAW | Examples | Windows divisions. It was created in the sub-directory structure of Examples | Windows | Order
File | Select Workspace After you are done looking at this dialog then close it using the X close button at the top.
Figure 4
Figure 5
41
This chart shows in which subdirectory your files will be located. Workspace Directory: AppHtml AppSrc Extension & Description of Files Contained in the Directory: Application Html (for web applications) Studio Data Files abData CFG WorkspaceName.cfg holds embedded resources DG Dialog files INC Include files MN Menu files Precompiled package files: FLP Precompiled package (with P option) PKI Precompiled package (with P option) FLD Precompiled package (with PZ option) PKD Precompiled package (with PZ option) PRP Precompiled package (with PF option) PKG Custom Package/Class files PRN Compiling list when f option used RV Report View files SL Selection list files SRC Source code files TRC Trace files created by using debugger TRE Studios temporary files VW View files Bitmap files the application uses, such as Company Logos; icons (.ICO); and movies. These are only needed if they where NOT embedded within the EXE. User Files? No No
Bitmaps
42
Extension & Description of Files Contained in the Directory: Filelist.CFG Lists all data file names DAT Data files HDR Header files K# Index (Key) files RPT Crystal Report files TAG Field name file VLD Variable Length Data (If using other databases, they would also be stored here) DataDictionary Data Files DDDATA DD Data Dictionary files FD File Definition DEF ASCII Definition files Help files created for your application IDEClasses.DFC Studios Class-List for workspace BMP Bitmaps for the New Classes DFC DataFlex Class files DFO DataFlex Object Preference files DFS DataFlex Subcomponent files TPD Template Dialog files TPL Template List files TPR Template Report files TPV Template View files EXE OCP WS Compiled Code ActiveX control preference files Holds pathing & application information
DDSRC
No
Help IDESrc
Yes No
Programs
Yes
Note: The workspace subdirectories help the developer separate the files required by the user from the files only required by the developer. The last column indicates the directories required by the End Users. These directories must be deployed with your application. Data Access Corporation 43
44
Figure 6
45
Creating Workspaces
Our first task when starting a new application will be to create a new workspace.
Figure 7
46
Figure 8
Figure 9
47
The prompt button allows you to browse directories to make a selection. We will leave the default location.
Figure 10 Warning: Most of the time you will have your own directory area where you will store your workspaces.
[ Learn More [ OK
Figure 11
48
Upon completion of the workspace wizard, this is what has happened: Our new Finished Example workspace directory and eight subdirectories have been created. The Studio default workspace has been changed to our newly created workspace. A few files have been inserted into these subdirectories that are used by the Studio (abData & ddData) and other files such as a blank Filelist.CFG. (If any of these files already exist in these directories, they will NOT be over-written). The new files that will be used to create all new workspaces are copied from the \Usr\New directory. The workspace has been registered in the workspace.ini file located in the \Bin directory. This allows the Studio to keep track of all workspaces and can be modified using the Studios Workspace pulldown menu and option Properties or Workspace Manager.
Figure 12
A WorkspaceName.WS file was created in the \Programs directory. This file is shown on the next page.
49
Workspace Pathing In order to locate files a special .WS file is created in the \Programs directory. The contents are listed below. . i.e.; The DataPath is used to find the database table files. Multiple directories can be listed by separating them with a semicolon. Class.VDF.Finished Example.WS
[Workspace] Home=..\ AppSrcPath=.\AppSrc AppHTMLPath=.\AppHtml BitmapPath=.\Bitmaps IdeSrcPath=.\IdeSrc DataPath=.\Data DDSrcPath=.\DdSrc Description=Finished Example HelpPath=.\Help ProgramPath=.\Programs FileList=.\Data\Filelist.cfg
The Goal
Looking at the finished application will give us a better understanding of the code that we will be building. The manual code additions will be more meaningful if you see the finished application in operation.
We will use a Self-extracting zip file that will install the finished version of the program. This will allow us to see what we are building and have completed files to compare to if help is needed.
Close all VDF utilities Insert training CD into drive [ Start [ Run Use the browse button to point to your CD drive then double click on Finished ExampleZip.EXE Do not change Unzip to folder unless you created the workspace in a different location [ Unzip Button
Figure 14
51
Open Windows Explorer Go to the Drive and directory where your workspace is created [ Finished Example [ Programs / Finished Example.exe
Figure 15
52
Figure 16
Things to note: New Employee records automatically have the next available number assigned The Departments and Employee Views show only the associated Employees in the grid that belong to the Department record in the top of the view. Click on the prompt buttons. These are buttons with three dots on them . Running totals in the Dept and Company records update when a new Empl/Dept record is updated. Process a few employees out with the Logging out View Then use the button to batch process the remaining employees out. Use the Report Pull-Down to check out the reports that will be created.
53
Figure 17
Figure 19
The Green/Red lock toggles to indicate when the file structure (first 3 tabs) can be altered. Green indicates an exclusive lock on the file, giving a green light to change the file structure.
The last four tabs will be disscussed in a later lesson. They create the DataDictionary file (.DD). Changes to these last four tabs can be made with the lock set to red or green.
55
[ Lock Icon (so it is green) [ Parameters Tab [ Client Atomic 1 Scroll down to the Transaction Type explanation
Figure 20
56
[ Fields Tab
57
[ Index Tab
Figure 22
A prompt is available to make adding segments to an index easier. Click on the Name>> label to popup the field list. Pressing F4 (the prompt key) or Insert Button also brings up this popup.
58
[ Parameters Tab
Figure 23
59
Lesson 2 Lab
Description: Practice creating a workspace and database tables:
Figure 24
60
[ Next
Figure 25
[ Select Group [ Class [ VDF [ OK CorporationX Record Keeping for CorporationX [ Next
Figure 26
61
[ Next button
The prompt button allows you to browse directories to make your selection.
Figure 27
[ OK
Figure 28
62
Figure 29
63
Creating a Database Table from Scratch Our first added file will be the SysFile.
Figure 30
64
Within DBB
File | New 200 SysFile [ OK
Figure 31
Enter the fields from the chart [ Parameters tab [ System file File | Save [ OK [ OK
Figure 32
Size 35 4 2
65
Adding Database File Names Directly into Filelist If the database tables already exist, you can just add them to the current Filelist.CFG. This will not wipe out the existing data in these files.
Figure 33
Figure 34
66
Figure 35
67
Use a .DEF File to Create a Database Table Loading TimeCard & Wk_Sum files from .DEF files will create empty database tables with defined fields and indexes.
Figure 36
80 Wk_Sum Wk_Sum.def [ OK
Figure 37 Warning! Make sure the file number is correct according to the chart or you will get an Unable to commit the Structure changes error. This error says that the .DEF that you are using has a relationship to a file number that does not exist.
68
[ Save Button
Figure 38
Figure 39
69
Figure 40
70
Database Builder creates a DataDictionary file (.DD file) every time it creates a database file. We will cover these DD files in depth in another lesson but for now, we need to connect the Data Dictionarys together properly. This is done by the required child and required parent lists that will Combobox match the file relationships.
Use the combobox to open all files except DataFlex error file [ Yes to any question on creating new .DD files
Figure 41
71
[ Empl File Dialog [ Structures tab [ Delete Button until all files are removed in the section called Required Child files [ Magic Wand button Repeat these steps in the section called Required Parent files Save the file
Figure 42
If files are listed in any of these areas, it is best to remove them and then press the wand button. The magic wand will add files to the area but it will not remove files that are there incorrectly. (incorrect files could have been added manually or by relationships that no longer exist).
The SysFile is a system file (a one record file). It will not be listed as a Required Child or Parent file since it has no file relationships. Therefore, it does not need the structures tab updated.
72
2. The lock in the upper right corner must be green to make changes to the first three tab pages. When opening a file it always comes up in red - Is there a way to default it to green?
3. When adding a new field in Database Builder, are the Add and Insert buttons required to add a new field?
4. When loading a complete file structure (with many relationships) into a new Filelist.CFG, is it important to load the .DEF files in any special file number position? Why?
73
5. Write down 3 different ways to open a database file in DDB. (open, not create)
6. What is End User Mode and how do you set up Database Builder in End User Mode? (hint look this up in the on-line help under the index tab)
74
75
Lesson 3
Building Views & Components
The Studio is a powerful utility that allows you to not only generate Views and Selection Lists but also generate and maintain a full application.
Popup Menu Arrange Objects Tool Nudge Objects Tool Resolution Check Tool Object-Order Definition Tool Drag Lock Lost Objects in the Studio Cutting & Pasting Objects Anchors & Min/Max Size Lab 3 Creating Selection Lists Attaching Selection Lists Using Application Wizard Creating the Empl View without Wizards Attaching a New View to the Application Compiling Code & Testing Adding Pictures to Records
Selection Lists
Selection Lists or Lookup Lists as they are also called allow the user to call up a list to make a selection from one of the existing records in the database. The selection list is called up by clicking on the prompt button or pressing F4 while the cursor is in that object.
When your program is running this is what a selection list will look like:
Selection List
Figure 43
78
1. Within the Studio, create the Lookup List New Lookup Button The New Lookup button will create a blank lookup ready to add the file.fields to display. We will see this later in the lab
Figure 44
Figure 45
79
Figure 46
80
Figure 47
MDI (Multiple Document Interface) style is where the application window has a number of iconizable document windows which fit within it. This saves clutter on the desktop since iconizing or moving the parent window iconizes or moves all the child windows. MDI contrasts with SDI (Single Document Interface) in which windows are not constrained within one parent window, and normal practice is to run one instance of the application per document.
MDI Application Wizard Use this option to start the wizard that will build your MDI Application shell and one or more views Basic Application Use this option to create a very basic interface. The sample is a Hello World, which can be built upon to meet your application requirements. MDI Application Use this option to create the MDI application without starting the wizard.
81
TestStudio [ Next
Figure 48
[ Next
Figure 49
82
TestView [ Next
Figure 50
[ Next
Figure 51
83
Figure 52
Normally all Data Dictionarys in the file structure are selected. Later, we will learn that this view will only allow employee records to be saved but not deleted.
84
Employee [ Next
The main data dictionary is the central file used in the view (it is not the childmost file). More on this topic later.
Figure 53
Figure 54
85
[ Finish
Figure 55
/ TestView
Double clicking on the view name will open the view. TestView
Figure 56
86
Resize the container objects as shown by selecting the objects and dragging the corners larger.
Make sure you experiment with all the tools The purpose of the Test Application is to practice using the Studio tools!
Figure 57
87
Button Bar
Many of the options for the Menu Pull-downs are available from the button bar
Move your mouse over the buttons on the button bar to see the tool tip of each button [ second to the last button on bottom row to open the Code Explorer
Figure 58
88
Tools Pull-Down
The Tools pull-down lists the many tools available to us. These tools allow you to enhance the views that the wizard has started, or totally create views without the help of the wizard. There are hot keys listed in many of the pull-downs, learning these will increase your productivity. There is also a list of hot keys listed Appendix B. Open the first three tools. They are used in the basic building of the objects in the view
Tools | Database Selector Tools | Object Properties Tools | Controls Palette As we cover the tools experiment with them to see how to create objects within a view
Figure 59
89
The top row of buttons allows you to select from the most-commonly-used data-aware objects. Double Clicking on the file icon will expand the file to show the field list. Selection of a range of fields is done by clicking on the first field in the range and then shift clicking on the last field in the range. This will selected all fields between. The fields will be displayed in the same order that they are listed in the Database Selector. They can then be rearranged to your desired location.
Figure 60
90
DDO Tree Button The DataDictionary Object Button calls up an important dialog. Many complex topics stem from this dialog. We will be calling up this dialog in many labs. In Lesson 6 we will fully discuss the linkage between DataDictionarys. In Lesson 8 we will see this dialog again when troubleshooting problems. For now, simply look over what is available concentrating on two main topics: 1. The Main DDO is the central file for finding. In our sample program the Main DDO is the Empl DDO. The file relationship does NOT determine the Main DDO. It is also not necessarily the child-most file. You determine the Main DDO by determining the main file for finding in the view. Therefore, you must determine how the view will operate. In our example, when an Employee record is found all other files will fill in their corresponding record(s). We will see later that all Client (Child) DataDictionarys to the Main DDO should normally be constrained to the Main DDO. 2. Normally all the Data Dictionarys in the file structure are listed. Notice the child files to the Empl file are not listed. This was done to demonstrate that deleting records would not be allowed, we will correct this in another lesson.
Expand the view by clicking on all the + symbols and seeing what is available [ Close button
Figure 61
91
[ Automatic Class Selection button / Dept Icon to expand the field list [ Dept.Dept_Code field ; Dept_Code field to the view
; Dept Code object larger (by dragging the left or right side)
Figure 62
92
Before we start on this topic, lets explain the term Record Buffer. For each database file opened in a program, a section of memory large enough to hold one record is set aside. This memory storage area is refered to as a Record Buffer. When a record is read it is placed into this record buffer (memory area). During a save operation the data is moved from the screen to the record buffer and then moved from the record buffer to the hard drive. Whenever you reference a file.field name (ex: Move Miami to Customer.City), you are referencing the record buffer memory area for that field. The database should be locked when making changes to the record buffer.
During a save operation, the parent related field(s) is moved from the Parent record buffer to the Child record buffer. If a child related field is used in a view, it will be overwritten by the data from the parent during the save operation. In this example the Dept_Code is the relating field. Empl.Dept field relates to Dept.Dept_Code. When referencing the Dept code, you should place the field from the parent (Dept.Dept_Code). The save operation will move the Dept_Code data from the parent record buffer to the child record buffer. If we mistakenly entered the Child related field, the Studio (when generating the code) will replace it with the Parent related field and add a note in the source code that this correction replacement was made.
Label Property
Figure 64
94
Many Object Properties will have a popup listing the valid choices. Simply right click on the property line to see the list of valid entries.
] Right Click on Form_Border [ Border_None ] Label_Justification_Mode [ jMode_Top ] Right Click Color Experiment with the color settings on different objects for a full explanation refer to the on-line help
Figure 65
Notice in the TestView where the labels are positioned. Your labels may be offset to the left with a large space between the label and the object. We will learn how to change this default in later lesson when we talk about DFOs. For now changing the Label_Col_Offset property to 0 and Label_Justification_Mode property to jMode_Right will adjust the label to the object.
95
[ Database Tab
The Database tab-page of the Object Properties dialog is used to assign values to entry items (file.fields or expressions) and connect the currently selected DataEntry object to a DataDictionary object. This page is only used by DEOs (Data Entry Object db classes). If the current object is not a DEO, all items on this tab page will be shadowed.
Figure 66
Data Source Use the radios to connect a file.field, an expression or variable. If the selected object is row-based, (e.g. dbGrid), use the spin buttons to rotate through the columns of the object and change the file.field or expression for each column in turn.
The bottom part of the Database tab page is used to set and display the appropriate DDO server for the object. The server will provide the save/find/clear&delete functionality to the object. We will cover this in detail in another lesson on connecting DEOs to DDOs. Since save operations propagate up, we will leave the Server set to Empl_DD.
Note: A file.field can be changed into an expression by adding parentheses. Adding parentheses around the Dept.Dept_Code will shadow the object, disallowing user entry during runtime.
96
Figure 67
Base and Base Containers tab pages contain non-data-aware controls. Data and Data Containers tab pages contain data-aware controls. Non Visible tab page contains non-visual or modal controls.
97
Figure 68
dbTabDialog
It is a good habit to always rename the object name to a meaningful name. The object name is how you will refer to the object when sending messages directly to it. The Language Guide & Appendix C have the suggested naming conventions. All object names should start with a lowercase o.
98
Figure 69
Controls on this page are general-purpose and are not data-aware. Base objects can be placed inside of Data or Base type containers. Class Name Edit Button Checkbox SpinForm LineControl Radio ComboForm Classes that objects can be built from: A multi-line text-based control. The control automatically wraps words between lines and has a vertical and horizontal scrollbar. Used to create a user event. Used to toggle a Boolean value. Displays data and permits the incrementing and reduction of available values. Draws a 3-D line on a container. Can only be used within a RadioGroup container, to show the current selection from a group of mutually exclusive options. Combines the functionality of the Form class with that of a standard Windows drop-down list. This class is used when it is appropriate to supply a form with a list of static options. Simple class to enter single-line information. Used to display a bitmap. Displays multi-row, multi-column lists, Used to display a list of values in a single column. Used to display a text in a container. You may not need to use this class too often, as the Label property of most classes provides the functionality automatically. A control to provide users with a visual control to 'slide' through a range of values. A control to show the progress on a lengthy process. A control to displays an AVI animation clip without audio. A control to display a hierarchical list of items that can expand and collapse the associated list of sub items.
99
Figure 70
Controls on this page are data-aware and are used to display data from, and enter data into, a database. Data-aware objects can be placed only inside of data-aware containers. Class Name dbEdit dbCheckbox dbSpinForm dbComboForm Classes that objects can be built from: Displays database data on multiple lines. Used with Text fields. Displays Boolean-style database data in a checkbox. Displays database data and permits the incrementing and reduction of available values. Combines the functionality of the dbForm class with that of a standard Windows drop-down list. This class is used when it is appropriate to supply a dbForm with a list of static options. dbForm dbBitmap dbGrid dbList dbTrackBar Displays database data on one line. Displays the bitmap file listed in the database field. A multi-row, multi-column object to enter data into. A multi-row, multi-column object to view data in. Displays database data on a track bar
Note: The db prefix added to the above class names flags them as data-aware classes.
100
Right click on the first tab page Select Add Tab page
Figure 71
WU[ Data Tab page on the Controls Palette ; Drag a dbGrid into tab page2 and enlarge it ; Drag these fields from the Database Selector to the dbGrid Code Last_Name First_Name To delete a tab page: Select tab page2 Right click on tab page2 Select the Delete Tab page option
dbGrid
Figure 72 Data Access Corporation 101
Figure 73
Controls on this page are containers designed to hold non-data-aware controls. Class Name Group RadioGroup Container3d TabDialog Classes that objects can be built from: Used to contain non-data-aware controls. Visually drawn with a 3d-line border with a label in the top left corner. Used to group Radio objects within a Group. A general-purpose container that has a 3-D appearance. A container that holds Tab page objects. It is very useful for conserving screen space.
102
Data Containers Tab-page Data Containers are used to group data-aware DEOs (data-entry objects). They must be placed inside a db-type container themselves (dbView or dbContainer or ReportView).
Figure 74
Controls on this page are containers used to hold other data-aware controls. Class Name dbGroup dbContainer3d dbTabDialog Classes that objects can be built from: A container with a label in its top-left corner. A container with a border that makes it visually appear raised. Tabs are a great way to display large amounts of data neatly on the screen. The dbTabDialog holds a single dbTab page object and allows you to add more dbTab pages. A container to contain and provide coordinated access to dbTabView objects. Each TabView displays a standalone view with its own DataDictionary structure. Use the dbTabDialog to display many TabViews on multiple unrelated datafiles (like maintenance views), where you can consolidate the number of views in your overall application. A container to group Radio objects whose value is of a single data-entry element.
dbTabDialogView
dbRadioGroup
103
Figure 75
Controls on this page do not create a visual control during runtime or create a modal control that will have to be called. They will generate a visual icon in the Studio so you may click on it to add manual code in the code editor. Class Name BusinessProcess OpenDialog SaveAsDialog FontDialog Classes that objects can be built from: To perform a batch process on an applications database files. To provide access to the Windows file-open dialog. It permits users to select an existing file or enter a name to create. To provide access to the Windows file-save dialog. Objects of this class enable users to enter file names. To permit users to select fonts. It is an encapsulation of the Windows Common Font Dialog. All aspects of the dialog can be set before it is displayed, and queried upon its return. The PrintDialog class is a wrapper for the Windows Print dialog box. This dialog box is used to specify the properties of a print job. This class is intended to be used with the CrystalReport class exclusively The Array class is a general storage device. It is used to store all data types and its size grows dynamically to accommodate the storage requirements. Data elements in the array are accessed by an integer index. To assemble and maintain a set of unique values, with operations to add, remove, and find elements.
PrintDialog
Array
Set
104
dfTimer cImageList
Objects of this class can be used to trigger an event after a certain amount of time has passed. An imagelist is a collection of images of the same size, each of which can be referred to by its index. Imagelists are used to efficiently manage large sets of images, which can then be shared by multiple objects. A single imagelist object can provide images to the TreeView, cToolbar and TabDialog classes. The ColorDialog class provides an interface to the Windows standard Color dialog. The dialog will maintain its own list of custom colors and return the selected RGB color. Simple MAPI consists of functions for sending mail, receiving mail and sending documents. Consider MAPI as a transport mechanism for mail and fax messages. To create a simple object without any special methods found in superclasses. You can use cObject to create your own subclasses.
ColorDialog
cMapiHandler
cObject
105
Close all open tools, then: Tools | Alignment Palette Tools | Arrange Objects Tools | Nudge Object Tools | Resolution Check As we cover the tools experiment with each of them to see how to arrange objects within a view. Remember this is only a test view and its whole purpose is to test the tools!
Figure 76
106
Figure 77
4 | 5
The first four buttons justify the tagged objects to match an edge of the first selected object. Therefore, it is important which object is selected first. 1. Align tagged objects to the left 2. Align tagged objects to the right 3. Align tagged objects to the top (left justify) (right justify) (top justify)
The last four buttons equally space the tagged objects. Buttons 5 & 6 space objects equally between the first and last objects selected. Buttons 7 & 8 space the objects within the container object. Buttons 7 & 8 also rearrange and list the objects in the order that they are tagged. When spacing more than three objects, it may be better to use the Arrange Object tool. This is because when placing the objects evenly within the space if a remainder exist, the last object cannot be placed correctly. 5. Align tagged objects from top to bottom 6. Align tagged objects from left to right 7. Align tagged objects from top to bottom in parent object 8. Align tagged objects from left to right in parent object
Note: The last two buttons are the only alignment tools that will rearrange the objects in the order they were selected. This allows you to quickly rearrange objects just by selecting them in the desired order.
107
Popup Menus
Right Click on an object. Alignment can be done from the popup menu.
Figure 78
108
This tool is used to resize and/or space objects. Activate one or both parts of the tool with the Active checkbox. After you apply the change to the selected objects, uncheck the Active checkbox and your X Y settings are still available.
Figure 79
Note: The Alignment Palette described earlier can either space the objects between the first and last tagged object or within the parent object. The Arrange Object tool will leave the first tagged object in place and then apply the exact X or Y coordinate spacing between other tagged objects. This method will give better results in some situations. This will be noticeable when more than three objects are selected and the available free space to divide among the objects cannot be done equally.
109
Repositioning objects can be done by selecting a group of objects and dragging them to a new location or selecting the objects and using the Nudge Objects tool.
Figure 80
More precision is one advantage of the Nudge Objects tool. Dragging an object to the left or right will often result in a small up or down movement from the drag. Using the Nudge Objects tool will give you movement in only one direction. Increasing the number in the middle will nudge the object
faster.
110
Note: This is an estimate since not all video cards and drivers follow standards
Figure 81
111
The tab key will move us to the next entry object in a running application. This tool allows us to change the keyboard navigation of the cursor through the objects in our view. Simply select the object and then use the up/down arrow buttons to reposition the objects. Objects cannot be moved outside their group/container object. When you move a container, all nested objects will move with it.
Tools | Object-Order Definition [ Dept_Dept_Code [ Up Arrow Button until it is the second object from the top
Figure 82
[ OK
112
Drag Lock
This important feature will protect your view from accidental changes of object movement. Drag Lock will lock the objects in place. This will allow you to double click on the objects without accidentally moving them. You will not be able to drag the objects around with the mouse but you will be able to select them and move them with the arrow keys.
The drag lock indicator is an Studio control and once set, it affects all components in the Studio. The Studio does not store the setting of this indicator so it must be set each time the Studio is opened.
Press the Ctrl+L until the lock is off in the Status Bar
The remaining options on the Tools pulldown menu will be covered in other lessons. Items are shadowed (not available) depending on if an application is opened or closed.
Figure 85
114
Figure 86
/ tab page object will bring up the Code Explorer (Studio editor) [ on the non-visible object in the Code Explorer object tree [ Object Properties dialog Enter 5,5 for the location R
Figure 87
115
Figure 88
Try cutting and pasting multiple objects, using the Control key to multiselect objects.
Note: For multiple sequential selection, select the first item and then, , hold the shift key down while selecting the last item. In order to make multiple random selections, hold down the Control key while making additional selections. Data Access Corporation
Figure 89
116
Save and Close the Test_Studio application Briefly, look over the other pull-down options to see what is available
Figure 90
117
Here are the basic steps you will need to take Allow the Container to be resized. Set the Containers Border_Style to Border_Thick (otherwise it cannot be resized) Anchor the nested objects within the container. Set with the peAnchor property. Determine the Min and Max size limits that the container should be allowed to grow or shrink to and still be useful. Set with the piMinSize and piMaxSize properties. Test compile button TestView Object
Drag a Button to the bottom right corner [ TestView Object and change the Border_Style to Border_Thick [ Test -Run Button When the program comes up running -- Resize the View (MinSize & MaxSize) and notice how the objects do NOT resize or relocate [ X Close button and return to the Studio
Button
Figure 91
118
[ TestView Object Within the Object Properties dialog change the piMaxSize and piMinSize Plus or Minus 100 the Size property
If Size = 170,300 then make Max = 270, 400 Min = 70, 200
Figure 92
119
Figure 93
120
Lesson 3 Lab
Description: We start by making required selection lists (lookups) and attaching them to the appropriate field. Then we use the MDI Application Wizard to create an outer container that will contain the menu bar and status bar. The wizard also creates our first view. We will then create the next view manually without the aid of wizards. The third view will use the View Wizard. We will then test our application. Tasks:
Figure 94
121
Tools | Database Selector [ Add DDO button [ Dept DataDictionary [ Select button [ Yes to Main DDO [ Close button
Figure 95
122
/ Dept (to expand list) [ Automatic Class Selector button [ Dept_Code field [ Name Field ; these fields into the grid ; the right side of the Name column wider [ Outer Lookup Object Change the label to Department Lookup
Figure 96
123
Save Button
[ Save button Dept Department Lookup Dept_SL G[ Deferred Object [ Save button Close all the tools File | Close Component
There is a Magic Wand button in the DataDictionary Figure 97 Builder that will speed up connecting a selection list to a field. We will use this button in the next few pages. The Magic Wand button can only default these values, if we follow these naming conventions for both the Filename and Object Name: Suggested Naming Convention FileName Description The root database filename. The filename will have the extension of .SL added but it is not typed into the form when saving. A descriptive word for the file (many times just the filename) and the word Lookup. The word Lookup will flag these components as a Selection List. The root database table name with a _SL added.
Object Name
The deferred view checkbox will make our application faster at startup. Instead of creating all objects in memory at startup, it will not create the object until it is used for the first time.
124
[ New Standard Lookup button Repeat the above steps to create a Selection List (Lookup) for the Employee file showing: Code; Last_Name; First_Name fields. Save it Using naming convention listed in the chart above Close all the tools
Figure 98
125
Database | Database Builder (or the 5 button from the end on the button bar)
th
Figure 99
126
File | Open [ Empl file [ Open button [ Field Settings [ Code field [ Validation/Lookup Tab [ Magic Wand button (middle button)
Figure 100
Wand Button
If you cannot find the selection list using the Magic Wand use the Find Object & Package (1st) button to locate it. The same Selection List can be attached to multiple fields. Here is a slightly different way to attach a list. The Magic Wand will only work if the filename follows the suggested naming convention.
[ Last_Name field [ Find Object & st Package button (1 button) [ Empl.SL [ Open [ Save button [ OK File | Close
Figure 101
127
[ File comboform Arrow [ Dept This will Open the Dept file - attach the selection list to Code and Name fields Save and Return to the Studio
Figure 102
128
If an existing program is open select File | Close Program File |New Program
Figure 103
[ OK
Figure 104
129
CorporationX [ Next
Figure 105
[ Next
Figure 106
130
DeptView [ Next
Figure 107
[ Next
Figure 108
131
Figure 109
Figure 110
132
[ Finish
Figure 111
133
/ DeptView
Figure 113
Enlarge the Dept_Code Object [ Test compile and run component in the debugger button Notice that you can save new records but you cannot delete records we will correct this in another Lesson
You could also select File | New Component and select the Blank View from the DataEntry View tab page but that would take longer.
Figure 114
Tools | Database Selector [ Add DDO button [ Empl DataDictionary [ Select button [ Yes to make it the Main DDO Notice the parent file (Dept) is also opened. Save operations propagate up so parent files will open automatically
Using the many tools covered in this lesson create the Empl View similar to this screen (do not forget the dbContainer3d object) Use the Object Properties Tool to change the View Label to Employee View Enlarge the Empl.Code & Dept.Dept_Code objects Position the objects in the location shown using the Alignment Tool Use the ObjectOrder Tool to change the navigation
Figure 116
Note: Remember what we discussed in the lesson! The related parent field is used in the view, not the child related field. This is because during a save operation DataFlex will do an Attach prior to the save. This operation will move the related field from the parent to the child. If we were to actually use the Empl.Dept field here, then the blank parent record buffer would be moved to the Child Empl.Dept field causing the Empl.Dept field to be blank. The Studio will swap the field for us when it generates the code if we use the wrong one.
The reason we continue to make the Dept Code objects larger is that later we will be setting the field option to CapsLock, which will require a larger object.
136 Data Access Corporation
From the Controls Palette ; a dbTabDialog to the bottom of the view and resize it
Figure 117
] dbTagDialog (for the menu popup) [ Add Tab Page [ Add Tab Page Within the Object Properties dialog: [ each tab page (white selector squares) & set Labels to: Personal Information Work Information Picture ID
Figure 119
; fields to Work Information Tab page Enlarge the Pay_Type field we will be adding a validation table to it in another lesson.
Figure 120
138
] (right click) Pay Type [ Object Properties ] (right click) Prompt_Button_ Mode [ pb_PromptOn This prompt button will not operate until the validation table is added.
Figure 121
[ Automatic Class Selector (Wand) button at the top of the Database Selector Tool ; Picture_ID field to the Picture ID Tab page [ Bitmap button at the top of the Database Selector Tool ; Picture_ID field to the Picture ID Tab page
Figure 122
139
[ dbBitmap Object Within Object Properties Tool [ Initial Folder C:\Program Files\Visual DataFlex 9.1\Projects\Class\VDF\ CorporationX\Bitmaps
The Initial Folder property lists the initial directory, which will be displayed by the common file-open dialog. When we run the program, we will see this dialog when we add a bitmap file to an employee record. Figure 123
Note: The Initial_Folder property can be set dynamically to the current workspace \bitmap area. If you dont want to hardcode the Initial_Folder property add this to the Code Explorer: Set Initial_Folder of (CurrentBitMapPath (ghoWorkSpace))
Appendix B has examples of code to solve problems when using multiple directories in your Bitmap path and to limit the bitmap filename to 15 characters. If the end-user selecst a bitmap that is outside the current path, it is suggested that programmably the developer may wish to copy the bitmap to the current Bitmap path.
140
Close
Figure 124
141
Figure 125
Add a Component
142
[ Compile and debug-run program button (this will compile and run our application) After the program comes up running Open both views by selecting them from the View pull-down
Figure 126
Things to Notice How the tab pages switch. Confirmation Messages during a save. How Selection Lists operate. How multiple Views can be opened simultaneously.
Test the Application noting the items in the chart
143
Run the application and open the Empl View Create a new employee record [ Picture ID tab page / the Bitmap object the popup dialog will allow us to locate our bitmap file. Since our initial folder was set to: C:\Program Files\Visual DataFlex 9.1\Projects\Class\VDF\C orporationX\Bitmaps this is the default directory that the dialog will show Select a .BMP file [ Save Button Close program when done testing
Figure 127
144
2. What is Epoch and what has it to do with entering dates in a VDF application?
3. Predict and check the results of entering the following dates, with Epoch turned on and set to 30? 01/01/00 06/20/52 12/25/30
4. What would happen to the tab dialogs if the dialog box was not big enough to hold all three tabs? (add more tabs or shorten the tab dialog box to find out)
5. What would happen if you shortened the length of the last name window so that the entire last name entered wouldnt fit in the window?
6. Run the program, and type in a last name of WWWWWWWWWW (type capital Ws until you reach the limit (which is the length of the field). Notice that it had to scroll to the right. Clear with the F5 key, and type in a last name of iiiiiiiiii (all small letters is to the limit). How do you determine what the size of a control should be?
145
7. When using the Object-Order Definition tool, is it important where Textbox objects are listed?
8. Run our program, and open up the Employee Entry View. Find a Record, then place the cursor on the parent window (Dept) and press Shift+F2 to delete. Wait! What is going to be deleted? The Department or the Employee? Why?
146
Lesson 4
Generated Code
We will start to look over all the code that the Studio has generated for us. This will give us a better understanding of how VDF code works. The Studio editor allows manual code to be easily added throughout your application.
147
] Anywhere within the Code Explorer [ Toggle Full Source Use the code in the editor to follow along the code explanation on the next few pages
Figure 128
148
//DFAllEnt.PKG
Use Windows
...
//AB-IgnoreStart Use DfAllEnt.pkg #REPLACE CURRENT$WORKSPACE "Class.VDF.CorporationX" // Project Object Structure // Main is a Panel // // Client_Area is a AppClientArea oAbout is a AboutDialog
// Register all objects Register_Object Client_Area Register_Object Main Register_Object oAbout //AB-IgnoreEnd
//AB-StoreTopStart Use cApplication.pkg // Set date attributes as needed Set_Date_Attribute sysdate4_State to (TRUE) Set_Date_Attribute Date4_State Set_Date_Attribute epoch_value to (TRUE) to 30
Object oApplication is a cApplication Set psCompany to "My Company" Set psProduct to "My Product" Set psVersion to "1.0"
These three properties can be customized to your application. Showing your Company; Product; and Version
149
//Set psHelpFile To "HelpName.hlp" // Please provide the name of your Windows help file. Procedure OnCreate Send DoOpenWorkspace (CURRENT$WORKSPACE) End_Procedure End_Object // oApplication Use Help_Ids.inc //Developer should provide this file of help context links. Use Std_Help.pkg //AB-StoreTopEnd //AB-IgnoreStart //AB-IgnoreEnd Object Main is a Panel Set Label to "CorporationX" Set Size to 150 300 //AB-MenuAutogen //AB-IgnoreStart DFCreate_Menu Main_Menu #INCLUDE File_PM.inc DFCreate_Menu "&View" ViewPopupMenu is a ViewPopupMenu On_Item "&DeptView \aCtrl+1" On_Item "&Employee View \aCtrl+2" End_Pull_Down Set Status_Help To "Available Views" #INCLUDE Navi_PM.inc #INCLUDE Win_PM.inc #INCLUDE HelpA_PM.inc End_Menu //AB-IgnoreEnd //AB-ToolbarPackage Use DefaultToolbar.pkg // Tool-Bar object. //AB-End Send Activate_DeptView Send Activate_oEmpl_View
Main Panel
150
Object Client_Area is a AppClientArea //AB-ViewStart Use DeptView.vw Use Empl_View.VW //AB-ViewEnd End_Object // Client_Area
//Dept.VW
use Dept.DD use Empl.DD
//Dept.DD //Empl.DD
//Empl.VW
use Empl.DD
//AB-IgnoreStart On_Key Key_Ctrl+Key_1 Send Activate_DeptView To Client_Area On_Key Key_Ctrl+Key_2 Send Activate_oEmpl_View To Client_Area //AB-IgnoreEnd //AB-StatusBarPackage Use DefaultStatusbar.pkg // Status-Bar object. //AB-End //AB-StoreStart Use DfAbout.pkg Object oAbout is an AboutDialog Set ProductName To "CorporationX" Set Copyright To "Copyright: <add code here>" Set Author End_Object Procedure Activate_About Send Popup_Modal of oAbout End_Procedure //AB-StoreEnd End_Object // Main To "Author: <add code here>"
//Use the Standard Status bar and About packages Properties to customize your about dialog
At this point the user interface is started and the activate message is sent to the Main_Menu object, which paints the image on screen making it the top image and gives the focus to this object.
Note: (instructors) This is a good place to point out the corresponding Studio areas from the Program tree that appear whenever a program is opened. Data Access Corporation 151
Things to note! The main program is a shell where modular sections of code are included (via the USE Command) The first file brought in by the USE command is the DFAllEnt.PKG. This Package file contains Class definitions (the code to make the tools work). The .PKG files are not always classes; sometimes they are support packages that perform special functions. The View files end with the extension .VW. These View files are the heart and soul of the program. They are modular sections of code that can operate independently. Each can be compiled and run separately within the Studio. Also note that all the views have the same command USE EMPL.DD. This file is needed in each view so it will operate correctly when using the view separately in a test program. When all the views are added together in the main program, the EMPL.DD file is only included into the program once! If a change has to be added to the code in the EMPL.DD file, it only needs to be modified in the one place and after re-compiling will affect all the views. Modular code allows us to use the same code over and over agiain. These modular code sections seem confusing at first. The real benefit is gained when you modify or debug your code. This is similar to the fact that it is harder to troubleshoot a computer that has everything built into the motherboard. If the serial port is a separate card, you can repair it without worrying about breaking the Disk Controller. However, if everything is on the motherboard, fixing one problem can often break other parts.
Note: (for everyone) The USE command assumes a .PKG extension, if no extension is given.
Note: (for DataFlex procedural programmers) The Use command is very similar to the #INCLUDE compiler directive that you may have used in your code. The main difference is that the #INCLUDE would include a file numerous times, but the USE command will only bring in a file once. Note: (for DataFlex procedural programmers) A Menu program with RunProgram wait and Chain wait commands is comparable to what we now call views.
152
Activating Views
Views can be activated by the view pulldown menu or by Accelerator keys. The message name MUST be the same in both the .SRC file and the .VW file.
// This is the .SRC file DFCreate_Menu "&View" ViewPopupMenu is a ViewPopupMenu On_Item "&EMPL VIEW\aCtrl+1" Send Activate_EMPL_VIEW // This is the Empl.VW File ... Object Client_Area is a AppClientArea // Include all views Use EMPL_VIEW.vw DEFERRED_VIEW Activate_Empl_View FOR ; ; Object Empl_View is a dbView Set Label to "Employee Entry View"
Start_UI
153
Creating Templates
Templates save time in the design of components. In this example, we create a template that can be used when needing multiple views of a standard size. Templates can be Local or Global: Local meaning they are only accessible to one workspace; Global meaning will be accessible to all workspaces.
[ New Standard View button from the button bar Enlarge the view to just inside the 640 x 480 grid lines [ File | Save As Template | Local Enter file name of View640x480 [ Save button Close the View
Figure 129
File | New Component Notice the new template listed [ Cancel Button
Note: The Visual DataFlex language uses double slashes // to flag comments in your code. Therefore, these markers will be considered as comments by the Compiler, but have special meaning to the Studio.
OuterComponent
Figure 131
155
Open the EmplView [ oEmpl_Code object Notice that the selected object stays in sync with the shadowed object in the editor
Code added to the top of the Object Code added to the bottom of the Object
Figure 132
Selected object will be highlighted All objects start with an Object command and end with an End_Object. The Studio will add all its code where the Green Line is located. This means you have the ability to add manual code in the Code Explorer above or below where the Studio places all its generated code, such as the properties from the Object Properties dialog and nested objects.
Normally, you can simply add all your custom code below this green line. However, sometimes it is important that the added code is placed at the top of the object. E.g., if you were creating a new property that nested child objects would need, it would have to be created before the nested child objects try to use the new property.
156
Also notice that the Data Dictionary objects are also accessible even though they are not visible objects. We will be adding manual code to many objects later, in the lab [ Close this view
Figure 133
157
List of the Studio (AB = Application Builder) markers. Normally you will not need to type these, since the Studio will add these markers for you when you modify within the Studio editor in Outline View mode.
Marker Source Code File Commands for the Studio only Studio generated code for the compiler only Sample //AB/ Project project-name //AB/ command Location First non-blank line in your source code These are various commands that the Studio must understand that must be ignored by the compiler The Studio does not use this area but generates it for the compiler only. Any changes made here will be overwritten by the Studio. Manual Edits No No
//AB-IgnoreStart //AB-IgnoreEnd
No
//AB-DDOStart //AB-DDOEnd
Only defined and registered Data-Dictionary Objects are allowed Top and bottom edit area of the visual objects Yes
Manual-Code-Area
Note: The main edit areas are the bottom code areas and do not have the word bottom within the marker name but the Top edit area does contain the word Top just prior to the Start/End.
158
Lesson 4 Lab
Description Our next view will need manual code additions. The view style will be an invoice style. This style has a parent (order header) record displayed at the top of the view and a grid below filled with the child (order detail) records. Since this style of view is often needed, we will first create a view template that adds the manual code additions to make the view operate correctly. We will then use this template to create our Dept/Empl View. Then in later lessons we will again use our view template. Tasks The order example is a sample application. It may be helpful to run this example to understand how it operates. The order view looks like this:
This step can be skipped if you are familiar with the Order Example.
Windows Start | Programs | Visual DataFlex 9.1 | Sample Applications | Order Entry System Open the Order Entry view & test it
Figure 134
Notice that you cannot enter the grid unless the header is saved Close the example and return to the Studio
159
[ New Standard View Button Use the Controls Palette to create the 5 objects as shown Use the Object Properties Tool to change the object name & object labels as shown in the chart. Only the required items that need to be renamed are listed.
Figure 135
Object Name
oDetail_Grid
160
At this point in the manual DO NOT TO TRY TO UNDERSTAND ALL THE MANUAL CODE ADDITIONS! We will cover the syntax of code in other lessons at this point simply concentrate on how the views are working!
Manual code segments that will be added to our Header/Grid (Invoice Style) Template can be cut from a file called Code_Mod.TXT located on the CD that came with this manual.
When manual code is added to a template it is important to make it as generic as possible. This will increase the usefulness of the template to help us create many new views. This also means there may be a few items that may require customization to make our template function in a new workspace with new database tables. You will notice these types of customizations are described in the remark area within the code.
Manual Code Features that will be added are: Custom Save & Delete messages Save_Header procedure (ensures header is saved before entering grid) Switch Procedure for last object in header Append_A_Row (allows entering only at the end of the grid) Child_Entering in the Grid (sends the Save_Header procedure) Auto_Regenerate_State set to false (table will not resort when new records are added) Child_Table_State set to true (to ensure the row is always saved)
161
Lab dividers will show which lab the code is for. Cut & paste dividers show where to start and end a cut & where to paste it
Note: In the manual code you will start to see the use of * and + to combine variables and constaints. Ex: Move ("Delete Entire" * (psHeaderName(Self)) + ?") to sDel_String The * will leave a space between and the + will not.
162
/ the oView object (dbView) and Cut & Paste the corresponding code into the bottom area
Figure 137
This is the code to cut & paste. After pasting always compare the code printed in the manual to the code pasted into the object.
//------------------------------------------------------------------// Add to the oView object - below the green line // To customize our template set the defaults of top 2 properties: //------------------------------------------------------------------// Enter the Header descriptive filename // Example: Order --> not OrderHea // The file name will be used to name the view (Order or Transaction) // It will also customize our messages so they will say "Save this Order" // or "Save this Transaction". If the print button is used it will // expect a Crystal report called psHeaderName.RPT --> (Order.RPT) Property String psHeaderName Public "Order"
// Enter the File.Field of the header key field // Example: OrderHea.Order_number for the order example Property String psFileField Public "Order.Order_Number"
163
// This is a small limit to our template but most key fields are either ASCII or Integer // Then update the default setting for the property psType_Header_Key Get_Attribute DF_Field_Type of hFile iField to iType If (iType = DF_ASCII) Set psType_Header_Key to "S" // its default setting is "I" End_Procedure //Activate
//----------------------------------------------------------------------// Change: Create custom confirmation messages for save & delete. // Create the new functions and assign verify messages to them. //----------------------------------------------------------------------Function Confirm_Delete_It Returns Integer Integer iRetVal String sDel_string Move ("Delete Entire" * (psHeaderName(Self)) + "?") to sDel_string Get Confirm sDel_string to iRetVal Function_Return iRetVal End_Function // Only confirm on the saving of new records Function Confirm_Save_It Returns Integer Integer iRetVal iSrvr iRec
164
Move ("Save New" * (psHeaderName(Self)) * "record?") to sSav_String Get Confirm sSav_string to iRetVal Function_Return iRetVal End End_Function // Define alternate confirmation Messages Set Verify_Save_MSG Set Verify_Delete_MSG to GET_Confirm_Save_It to GET_Confirm_Delete_It
//------------------------------------------------------------------// Change: Table entry checking - attempt to save header record // // before entering a table (this is called by table. Return a non-zero if the save failed (i.e., don't enter table)
//------------------------------------------------------------------Function Save_Header Returns Integer Integer iRec bChanged iSrvr String sError_String Get Server to iSrvr // The Header DDO. // Are there any current changes? Get Current_Record of iSrvr to iRec // The current header rec#. Get Should_Save to bChanged
// If there is no record and no changes we have an error. If (iRec=0 AND bChanged=0) Begin // no rec Move ("First Create & Save a" * (psHeaderName(Self)) * "Record") to sError_String Error DfErr_Operator sError_String Function_Return 1 // a non-zero return val will stop the save End // Attempt to Save the current Record // Request_Save_No_Clear does a save without clearing. Send Request_Save_No_Clear // The save succeeded if there are now no changes, and we // have a saved record. Should_Save tells us if we've got changes. // We must check the DataDictionary's Current_Record property to see if // we have a record. If it is 0, we had no save. Get Should_Save to bChanged // is a save still needed Get Current_Record of iSrvr to iRec // current record of the DD
165
166
Note: (Everyone) In an Invoice Style view it is important to restrict the users navigation into the grid without first displaying a Parent/Header record in the top of the view. In our template we will ensure a header parent record is displayed and saved before allowing the user to enter the grid. This will be accomplished by the Save_Header procedure, which safeguards against creating orphan Child/Detail records.
This step will allow entry into the parent field only if it is a new record.
From the Code_Mod.txt file, highlight & cut the appropriate code (shown below) [ Parent object to select it; paste code in the bottom area
Figure 138
//------------------------------------------------------------------// Add to Parent (odbForm) object - below the green line // If Header record exists, disallow entry in Related Parent window. //------------------------------------------------------------------Procedure Refresh Integer iMode Integer iSrvr iCrnt Get Server to iSrvr // get the DataDictionary Get Current_Record of iSrvr to iCrnt // get record in DataDictionary // Set displayonly to true if iCrnt is non-zero Set Enabled_State to (iCrnt = 0) Forward Send Refresh iMode // do normal refresh // don't leave us sitting on a displayonly window If (iCrnt and Focus(Self)=Self) Send Next End_Procedure
167
This step modifies (overrides) the behavior of the Switch message (sent when we press the F6 key or click in the grid). Under some view structures if a user is in the last object of the header and presses the F6 key, the Switch message would allow them into the table without a valid parent record. To guard against this we will send the Activate message instead of the normal switch message.
From the Code_Mod.txt file, highlight & cut the appropriate code (shown below) [ Last object to select it; paste code in the bottom area
Figure 139
//------------------------------------------------------------------// Add to the Last (oDbForm3) object - below the green line // Normal switch behavior is to attempt to keep looking for additional // objects to switch to. If we can't switch to the detail table, we // want to stop! So just do a simple activate. This solves the problem // of the Save Header not being called if we press F6 (switch) on the // last object. //------------------------------------------------------------------Procedure Switch Send Activate of oDetail_Grid End_Procedure
168
This step will make the grid operate correctly for our application. The Append_A_Row will allow us to add records only to the bottom of the grid. Since we are only adding records to the grid bottom there is no need to sort the table after each save, so we will set the Auto_Regenerate_State off. The Child_Table_State will ensure the row is always saved. The Child_Entering will send our Save_Header procedure.
From the Code_Mod.txt file, highlight & cut the appropriate code (shown below) [ oDetailGrid object to select it; paste code in the bottom area
Figure 140
//------------------------------------------------------------------// Add to oDetail_Grid (dbGrid) object - below the green line // Change: Table entry checking. // // // Set Child_Table_State to True which will cause table to save when exiting and attempt to save header when entering. to TRUE // Saves when exit object
//------------------------------------------------------------------Set Child_Table_State
// Called when entering the table. Check with the header if it // has a valid saved record. If not, disallow entry. //
169
Delegate Get Save_Header to iRetVal // Check with header to see if it is saved. Function_Return iRetVal End_Function //------------------------------------------------------------------// Change: Assign Add-Mode key to Append_A_Row // // Create new behavior to support Append_A_Row Optimize the table refresh // if non-zero do not enter
//------------------------------------------------------------------On_Key KAdd_Mode Send Append_A_Row // Hot Key for KAdd_Mode= Shift+F10 // prepare to add new record by Jumping to blank row at end of grid. Procedure Append_A_Row Send End_Of_Data Send Down End_Procedure // The way this table is set up, items can never be added out // of order. New items are always added to the end of the table. // By setting Auto_Regenerate_State to False we are telling the // table to never bother reordering after adding records. This is // a minor optimization. Set Auto_Regenerate_State to False // table is always in order // // Q: how would a keyboard do this? down 1 line to empty line // A: Go to end of table and
170
File | Save as Template | [ Global Invoice_Style [ Save Button Close this component
Figure 141
171
Figure 142
172
We will not need the Parent related object. Right Click on it (the popup menu will appear) select Delete Tools | Database Selector [ Add DDO [ Empl DataDictionary [ Select button [ No to MainDDO popup question [ Main DDO combo and Select Dept [ Close button
Figure 143
173
] Right Click on the first object (the popup menu will appear). Select Properties Use the Object Properties dialog st to label the 1 dbForm to Code [ Database tab page [ browse () button in the Data Source area Select Dept.Dept_Code
Figure 144
[ OK Repeat the above steps on the other dbForm, changing the label to Budget and the source to Dept.budget field
Browse Button
174
Grid Options
Use the Database Selector tool to add the remaining fields to both the top section and to the grid
] (right click) on the grid (for the popup menu) [ Grid Options
Figure 145
Changing the column size can be done by dragging the line in the grid header
[ Hire_Date [ Down Arrow Key until Hire_Date is listed last Make sure the Main file is Empl file and the index is Index.3 [ OK button
Changing Navigation
Change the label of the View to Dept/Empl View Change the object names (object name, not label) of the first and last objects to oDept_Code and oDept_Budget Use the Object-Order tool to correct the navigation of the objects, make them match the screen shot [ OK button
Figure 147
176
Here we have to customize the template by setting the default values of four properties.
/ The outer view container to bring up the editor Change the default values of the two properties as shown in the table below
Figure 148
177
[ Save the view filling in the data as shown [ Test/Run current view button Attach the view to the overall application as shown in the previous lab
Figure 149
Warning: If you get ompiling errors such as Bad Image Errors Look for a single slash /-----//---------
Things to Notice Activate the Selection Lists Notice the Scroll bars added to all scrollable areas Confirmation Messages for saves and deletes You should not be able to navigate to the grid until a header record is displayed. Try leaving the header blank and: Press F6 from the header (F6 is the switch key) Click into the grid Press tab from the last object in the header Find a header record and then in the grid pressing Shift+F10 (the Add Mode key) will jump to the bottom of the grid. The grid columns can be resized
178 Data Access Corporation
Test the Application noting the items in the chart
2. In the DataFlex language, how do you continue a command line to the next line?
3. Within the DeptEmpl View, go to the grid and enter some test data, but do not save with the F2 key. . . click on a window in the header . . . can you exit the line item without a save occurring? What if you use the down arrow or up arrow? Does the save occur?
4. When the Studio generates the code for an Object the Green Line in the Code Editor will be replace with what?
5. When you find a Department record (in the header section), only the employees for that Department are found and displayed. How does the program know to show only related records in the dbGrid?
179
6. Create a new view with two dbForm controls, one showing the Empl.Code and the other one showing the Empl.Last_Name. Make the dbForm for the Empl.Code control using the Database Selector. Make the dbForm for the Empl.Last_Name using the Controls Palette. When you compile and run your new view did both of your controls show data when you find records? What extra step do you have to do with the Controls Palette when creating data-aware controls?
180
Lesson 5
Data Dictionarys Part 1
This lesson covers how to use the DataDictionary Builder utility (which is incorporated into Database Builder). This utility will allows you to create and edit the DataDictionary files painlessly. Making selections and setting checkboxes generates most code for you. When reading this lesson, no changes should be made to the files until the Lab at the end of the lesson.
Auto-Assigning Numbers External Structure Lab 5 Building Data Dictionarys for All Database Files Setting Field_Options Setting Field Validation Validation Tables Setting Field Masking Setting Appearance Tab Setting Status Help Field_Default_Value Auto-Assigning Numbers Changing an Objects Class
Note: (for OOP programmers) The same rules we learned in earlier revisions using DataSets will still apply with DataDictionarys. Our familiar DataSet procedures (creating; update; backout) still apply in the DataDictionary. Your application will work with a mixture of views using DataSets and views using DataDictionarys. Just do not mix DataSets and DataDictionarys in the same view. DataDictionarys are much more powerful. If you have existing applications with DataSets, it is recommended to take the time to convert them to DataDictionarys.
182
Business Rules
Business Rules are rules that must be followed before changes are allowed to the database.
Examples: Verify important facts before allowing saves and deletes. Do not allow a parent record to be deleted if it has related child records. Auto-assign a number for all new records being saved.
Since these are things that happen during saves and deletes, we subclass the DataDictionary Class and add all these rules in our new class.
Business Rules are built into the subclass so they affect ALL views. If the rule should only affect one view then that rule should NOT be in the class, but in the DataDictionary Object within the view that it should affect.
183
//CallCust.VW
Object Customer_DataDictionary is a Customer_DataDictionary End_Object
//CustGrid.VW
Object Customer_DD is a Customer_DataDictionary End_Object
//Customer.VW
Object Customer_DD is a Customer_DataDictionary : Set Field_Default Field Customer.State to FL End_Object : Object Customer_State is a dbForm End_Object
Note: (Procedural programmers) If you are having problems with the concepts of Objects and Classes refer to the appropriate section in Appendix C.
184
In order to know when and how to use the many options in the DataDictionarys, you must know what is available. The rest of the lesson exposes you to the many options that the DataDictionary can contain. Use this lesson as a reference as you complete the lab and when you create future projects.
Note: (everyone) Database Builder is the entire utility. DataDictionary Builder has been incorporated within Database Builder and is the last four tabs. Field Settings Methods Options Structures
185
Field Settings
The six tab pages under the Field Setting tab page are settings that are made at the field level. Be sure to indicate the correct field before setting these options.
Field Options
Warning! If you wish to see these screens on your computer, open any file in Database Builder Utility. No changes should be made until the lab at the end of the lesson or if you see commands printed in this style font (with the horizontal lines at the top and bottom)!
Figure 150
The KeyField option is normally placed on uniquely indexed fields. When a field is flagged as a KeyField and the Protect_Key_State is True (the default), the user will not be allowed to change the value of the field. Example Code Created:
Procedure Define_Fields Forward Send Define_Fields Set Field_Options Field Empl.Code Set Field_Options Field Empl.Code Set Field_Options Field Empl.Code : to DD_AUTOFIND to DD_KEYFIELD to DD_NOPUT
Note: (Prior database developers) Key fields are similar to the Primary Key concept of other databases
186
Note: (Prior DataFlex Users) In prior DataFlex versions we placed the entry options within the DEOs. They are now placed in the DataDictionary (DD File). This will assure data consistency in our databases. Entry options Range & Check will be covered later in this lesson.
Description
AutoFind AutoFind_GE CapsLock DisplayOnly FindReq ForcePut KeyField NoEnter NoPut Retain RetainAll Required SkipFound Zero_Suppress AutoBack AutoClear AutoReturn Points= n Thousands
DD_AutoFind DD_AutoFind_GE DD_CapsLock DD_DisplayOnly DD_FindReq DD_ForcePut Set Key_Field_State DD_NoEnter DD_NoPut DD_Retain DD_RetainAll DD_Required DD_SkipFound DD_Zero_Suppress Not Windows behavior* Not Windows behavior* Not Windows behavior* done with masking done with masking
Find Equal a record automatically Find Greater or Equal a record automatically Uppercase all data in window No entry and no put to record buffer Found indicator must be true to continue Force data from window to record buffer To protect a field from being changed No navigation to data-entry window allowed No put of data to record buffer Keep data in window (clearable) Keep data in window (not clearable) Requires an entry Skip entry if found indicator is true Blanks display if numeric is zero Back up a window on left arrow Clear the window if new data is entered Advance to next window on a full window Decimal points set to (0 1 2...n) Displays thousands separator in numeric fields
187
Field Validation
Field Validations are accomplished upon forward navigation from the field and prior to the save (outside of a locked state).
Figure 151
Description & Example Code Created: A validation message that will get called whenever there is forward navigation from this field.
Set Field_Validate_Msg Field Cust.St to Ck_State : Procedure Ck_State // add validation code here End_Procedure
Will check that the data is a sub-string of the checked string, e.g.; M|F.
Set Field_Value_Check Field Cust.Sex to M|F
Error Number/Message that will display if a Simple Validation, Range Validation, Validation Table or an incorrect Checkbox Value Validation fails Number is set by developer
Set Field_Error Field Customer.Credit_Limit to 330 ; The Credit Limit must be between @PARAM to @PARAM2
189
The Class Hierarchy chart shows the first Validation Class was built from the Array class and then each seceding class has additional functionality and features included. The main difference among the classes is how the source of the data is being displayed.
Class Hierarchy
Array
|__ValidationTable (built from static data) |__DescriptionValidationTable (built from static data) |__FileValidationTable (built from a database table) |__CodeValidationTable (built from existing database tables)
190
Visual Display of Validation Tables: All of the validation classes will use either a ComboForm or a ValidationList Class as the visual object to display the data.
This is an example of a Validation Table attached to a field and displayed with a comboform class.
Figure 152
If the validation table is attached to a field built from a dbForm class, the validation table will appear as a popup scrollable list. It will be built from the ValidationList Class.
Figure 153 Note: Creating a parent file and building selection lists (lookups) like those that we created in the last lesson will basically accomplish the same thing as validation tables.
191
Types of Validation Tables The source of the displayed data will determine which class to use for your validation table.
Source of Displayed Data CodeMast & CodeType data files Static Hard Coded Values that will not change Programmers specified database table
Class to be Used Clears Field_Value_Table property. CodeValidationTable DescriptionValidationTable (if Values and Descriptions are loaded) or ValidationTable (if only Values are loaded) One of the Validation table objects created manually.
Custom
Figure 154
Checking Validate will require entries to exactly match a value in the list
Note: (Everyone) On-line help is always available. Use it for a more complete explanation of all settings.
192
Figure 155
Note: If you have entered values into the grid for a static type validation table, selecting None will clear the values entered for the Static validation table. This will require you to re-enter the data if the none option was click by mistake.
193
Dynamic sets the Validation Tables class to CodeValidationTable. By default this class uses the predefined database files CodeMast and CodeType. The Type Value form should be filled in to indicate the code type from the CodeMast file. New Type Value Button allows you to add a CodeType record so it will be available in the Type Value combobox. But normally we create the records first as shown below.
Figure 156
The Maintain Code File dialog is used to create records for the validation table.
This dialog can be reached from the Studio Workspace pull-down and the Code Master Maintenance option. Two empty database files, CodeType and CodeMast are included in the \Data subdirectory. After creating the records in this utility they will be available when you create Dynamic Validation Tables.
Data Access Corporation
Note: a useful property is: Static_State Set Static_State to True // Will load its list only once in each session. Set Static_State to False // If application allows editing of the list, //such as a code Maintenance view
Note: Since CodeMast and CodeType files are being opened as file numbers 207 and 208 these file numbers should not be used.
195
Static Uses static data that is hard coded into the object. It sets the Validation Tables class to Description ValidationTable (if Values and Descriptions are loaded) or ValidationTable (if only Values are loaded)
Figure 158
End_Object // Empl_Pay_Type_VT:
Procedure Define_Fields Forward Send Define_Fields : Set Field_Value_Table Field Empl.Pay_Type To (Empl_Pay_Type_VT(Self)) // used in conjunction with the Validation Table above :
196
Custom for any other class that you have used for the Validation Table. Normally a FileValidationTable is used. If you select Custom, then Database Builder will not allow you to configure the Validation Table object and the object will have to be manually built.
Use this class to display/ validate from Database files or DataDictionarys. Normally it is better to use a Selection List because of performance.
Figure 159
197
// Developer creates the Code File therefore // the fields used for Code & Description must be // indicated along with the correct index to use.
Set Main_File to Chg_Code.File_Number Set Code_field to 3 Set Description_field to 4 Set Ordering to 1 Set Validate_State to True Set Allow_Blank_State to True End_Object // Charge_Table Procedure Define_Fields Forward Send Define_Fields : Set Field_Value_Table Field Empl.Pay_Type To (Charge_Table(Self)) // used in conjunction with the Validation Table above : // field 3 is the charge card code field // field 4 is the charge card description field // index that contain the segments // Chg_Code.Code & Chg_Code.Desc // requires entries to exactly match a value in the list // will allow blanks or 0 as a valid response
198
Field Masking
This powerful feature enables you to define a data-entry template, or mask, for the values that can be entered into a field. Field masks constrain entries to only those characters, digits and special characters that the masks allow, and only in those specific positions within a field that you predefine. The mask characters are not saved in the database files and are mainly for improving the appearance of the displayed data.
1. Default Masks: Most of the time the default Field_Mask_Type settings are all that is required. There are four Field_Mask_Type settings. Their defaults will be covered in a table in the next section.
Figure 160
// The following Mask_windows are normally not set since they are the default Set Field_Mask_Type field Customer.Name to Mask_Window Set Field_Mask_Type field Customer.Last_Order_Date to Mask_Date_Window Set Field_Mask_Type field Customer.Age to Mask_Numeric_Window
199
2. Custom Masks: Sometimes the default masks are not sufficient and customized masks must be created. This is done in two steps. First, set the Field_Mask_Type property to the correct type, then customize a mask with the Field_Mask property. Token characters are shown in the tables on the next few pages.
Figure 161
Example Code:
Set Field_Mask_Type Set Field_Mask
To MASK_WINDOW To "###-##-####"
The hyphens in the mask will not be saved to the database. This means that the field length will not need to be increased
200
Non-token characters (defined for the Field_Mask_Type) will be displayed literally. Token characters can be displayed literally by preceding each with a backslash (\).
Field_ Mask_ Type Defaults Mask_Window Windows default Token Char. # @ ! * Mask_Currency_Windo w & Mask_Numeric_Window "$,*;($,*)" *" , . ; # * 0 Contents of Token Each token occupies one place unless noted 0 - 9 (or blank) any alphabetic character (no numbers) any punctuation character any printable character insert local thousand separator insert local decimal indicator separates positive & negative formats 0 - 9 (or blank) any number of digits including none 0 - 9 (cannot be blank) 1 - 12 01 - 12 Jan - Dec (abbreviated) January - December 1 - 31 01 - 31 Sun - Sat (abbreviated) Sunday - Saturday 00 - 99 1700 - 2900 (diagonal is replaced with the local date separator)
Mask_Date_Window
Note: Dates will take Microsoft Windows Settings over the mask!
201
3. Masks in DEOs: If the mask should only affect one Data Entry Object (DEO) in a view, it can be altered with one of the properties shown
// Set Currency_Mask item_num to integer integer [string] // // // Set Currency_Mask 0 to 8 2 $,*;$,*- : : Set Numeric_Mask 0 to 6 0 *% string is optional second integer is number of digits to right of decimal first integer is number of digits to left of decimal
You can change the global defaults of Currency_Mask_Window and Numeric_Mask_Window. This is done by altering the Default_Currency_Mask and Default_Numeric_Mask string(s) within the DFBASE.PKG. When you wish to change the global strings for only one application, you can change the string(s) immediately after the "Use DFAllEnt" statement.
202
Appearance Tab
This tab allows us to set the default class our visual controls will be built from in the Studio. The Magic Wand button (Automatic Class Selection) on the Database Selector tool defaults dbEdit objects for all TEXT fields; and dbForm objects for all other type fields. Using the Appearance tab page, we can set the type of class that objects will default. Automatic Class Selection
Figure 162
Figure 163
We created a Static Validation type table on the Pay_Type. By our setting the Visual Control to dbComboForm, the Studio will create a dbComboForm (not a dbForm) whenever an object is built from this field. Any objects created by the Studio prior to setting this option are not affected.
Example Code:
Set Field_Class_Name Field Empl.Pay_Type To "dbComboForm"
203
The Long and Short Labels will be displayed as the visual label when we create an object from the field in the Studio. The short label will be used in all list type objects (such as dbGrids) and the long label will be used as the label in all other types of objects. This will speed the creation of all our views and will keep our labels constant throughout our application. If the labels are not set, then the Studio will use the field name as the label.
Figure 164
Example Code:
Set Field_Label_Long Set Field_Label_Short Field Empl.Soc_Sec_Number Field Empl.Soc_Sec_Number To "Social Security Number" To "SSN"
Note: The Auto_Label_State property will use the Long Label setting. See the on-line help for a full description of this property.
204
Checkbox Option
The Checkbox option will make the field into a checkbox. In the Contact sample (a sample provided with VDF) we can see that the Studio will create the visual control for the STATUS field as a checkbox. The values saved to the database will be an A for active (true- checked) or an I for inactive (false- unchecked).
Figure 165
205
Status Help
Status Help will display at the bottom of the screen whenever the user enters this field.
Figure 166
Example Code:
Set Status_Help Field Empl.Last_Name To "Please enter the employee's last name. "
206
Figure 167
Example Code:
Procedure Field_Defaults Forward Send Field_Defaults //DDB-FieldDefaultStart Set Field_Changed_Value Field Empl.St //DDB-FieldDefaultEnd End_Procedure // Field_Defaults To "FL"
Note: (Everyone) This can also be a function such as (MyFunc(Self, parm1 parm2,)). Functions will be covered in a later lesson.
207
Entry/Exit/Validation Messages
Many times processing must be done as the user enters into or out of a data entry window. The Field Entry, Exit, and Validation messages allow the programmer to send a message to accomplish extra processing.
Description
Message sent before entering an item. Returning a non-zero value will stop entry into the item.
Set Field_Entry_msg Field Empl.Hire_Date to Current_Date
Field_Exit_msg
Message sent before exiting an item. Returning a non-zero value will stop exit from the item.
Set Field_Exit_msg Field to Adjust_Ext_Price
Message sent before forward navigation from an item, it is called again just prior to the lock of a save operation. Returning a non-zero value will stop forward navigation /save.
Set Field_Validation_msg Field Empl.Hire_Date to Current_Date
// This is our newly created procedure // It adds a default date if the field is blank and not changed Procedure Current_Date Integer iField Date dDate Boolean bChanged Get Field_Changed_State iField to bChanged If ( bChanged=0 AND dDate = 0) Begin SysDate4 dDate Set Field_Default_Value iField to dDate End End_Procedure
These messages will pass the Field number and the value of the current DEO.
208
Figure 168
Step 2 Under the Other tab page list the procedure name to send when entering this field.
Figure 169 Note: You should NOT change the normal navigation during these procedures. If you return a non-zero value it will not allow you to enter/exit. Do not try to have it jump to a new location on screen this should be done by augmenting a message like Refresh or Next. Remember these messages will affect ALL views and should not contain code with features that should only apply to a single view.
209
Two Arguments are passed with Field_Entry, Field_Exit & Field_Validation messages: Field Number and Field Current Value
Example of each (the fields in this example are not the same as our Empl file):
Set Field_Entry_msg Set Field_Exit_msg Field Empl.Dependents to Default_Dep Field Empl.Birthday to Calc_Age to Check_Age
Procedure Default_Dep Integer iField Integer iDependents // Default to one if blank, on entering If (iDependents =0) Set Field_Default_Value Field Empl.Dependent to 1 End_Procedure Procedure Calc_Age Integer iField Date dBirthday Integer iAge Date dToday Sysdate4 dToday Calc ((DateGetYear(dToday)) - (DateGetYear(dBirthday))) to iAge // If you havent had your birthday this year you must decrement iAge If ((DateGetDayofYear(dToday)) < (DateGetDayofYear(dBirthday))) Decrement iAge Set Field_Changed_Value Field Empl.Age to iAge End_Procedure Function Check_Age Integer iField Integer iAge Returns Integer // Validate Age is less then 100 If (iAge > 100) Function_Return 1 Else Function_Return 0 End_Function // would remain in the age window - shift+tab would work // Updates Age when Birthday field exited
210
The passing of these arguments (Field_Number and Current_Field_Value) allows us to call the same procedure from multiple fields. This example calls the same procedure from the Customer.First_Order_Date and Customer.Last_Order_Date fields.
Class Customer_DataDictionary is a DataDictionary ... Set Field_Entry_msg Set Field_Entry_msg Procedure Default_Today Integer iFieldnum Date dDate Integer bChanged Get Field_Changed_State iFieldnum to bChanged //has field been changed? 0=not changed If ( bChanged=0 AND dDate = 0) Begin SysDate4 dDate // put system date into dDate // but will not toggle Field_Changed_State End End_Procedure //Default_Today End_Class Set Field_Default_Value iFieldnum to dDate // displays current date to screen Field Customer.First_Order_Date Field Customer.Last_Order_Date To Default_Today To Default_Today
211
Auto-Assigning Numbers
Use this feature when you wish a field in each new record to be automatically assigned the next incremented number. Steps: 1. Select the field that will be autoassigned 2. Assign the File.Field to increment in the Auto Increment form. Step #2 List file.field to increment For ease of use, have these checkboxes checked
Figure 170
3. If the incrementing file is not part of the DataDictionary structure, list it as an external file from the Structures Tab page. This will only have to be verified if the checkbox above is checked.
External Structure All files that are not part of the DataDictionary structure but will be manually updated must be listed here so they will be locked properly.
The system file must be locked during the save operation so we list it as an Externally Updated File.
Figure 172
For optimization purposes we only lock the system file on new saves and deletes!
Figure 173
Open Empl Open SysFile
Example Code:
// External (System) file structure............. Send Add_System_File Sysfile.File_Number DD_LOCK_ON_NEW_SAVE Define_Auto_Increment Sysfile.Last_Empl_Num To Empl.Code
Note: (Everyone) This DataDictionary method supports only one auto-increment field per file. Data Access Corporation 213
Lesson 5 Lab
Description: This lab creates and edits the DataDictionary (.DD) files reviewing the many items the lesson covered.
Tasks: In this lab, we will build more features into the .DD files. Modifications that are made require little typing, so these modifications have not been added to the Code_Mod.TXT file.
Figure 174
214
Figure 175
Field Soc_Sec_Number
Entry Option AutoFind CapsLock CapsLock CapsLock CapsLock CapsLock, Required AutoFind, KeyField, CapsLock
215
Figure 176
216
Validation Tables
Static Table
[ Validation Table Tab [Pay_Type field [ Static Type Fill in the Value and Description columns as shown
Figure 177
217
Creating Dynamic Tables is a two step process: 1. Create validate records in the Studio using the Code Maintenance view. 2. Create the Validation table in Database Builder
Step #1 Create records in the Studio using the Code Maintenance view.
Save & Close all files in Database Builder and return to the Studio [ Workspace [ Code-Master Maintenance Fill-in & Save the following reason code records Close the Code Maintenance View
Figure 178
218
Return to Database Builder & reopen the files the Reason Code records will not show up if the files are not reopened [ TimeCard file [ Reason_Code field [ Field Settings [ Validation Table Tab [ Dynamic Radio [ Type Value Combo and select Reasons
Figure 179
219
[ Empl file [ Pay_Rate field [ Field Settings [ Mask Tab [ Mask Type ComboBox [ Currency Complete the mask setting for the Employee & Dept files from the table
Figure 180
220
Figure 181
This will set the label. The default is the field name.
[ Soc_Sec_ Number field Social Security Number Soc Sec Num
Figure 182
221
[ Code field [ Other Tab page In Status Help area Type: New employees will be assigned the next available number. Create your own Status Help lines for a few other fields in the files
Figure 183
222
Field_Default_Value Property
[ St field Enter FL as the Default Value
Figure 184
Alternatively, we could make this a dynamic default by using the Procedure Field_Defaults under the Method tab page. The added code would look like this:
Procedure Field_Defaults Forward Send Field_Defaults //DDB-Generated-Code-Location Set Field_Default_Value Field Empl.St to Sysfile.Local_State End_Procedure // Field_Defaults
223
Auto-Assigning Numbers
We will auto-assign Empl.Code field by incrementing the Sysfile.last_empl_num field
[ Empl.Code field [ prompt button to the right of Auto Increment [ SysFile [ Last_Empl_Num [ OK
If the SysFile is not listed, open the SysFile and check the System File checkbox on the Parameters tab page. This checkbox will do .step #2 automatically This step checks that the SysFile is listed correctly.
[ Structures Tab Check that the SysFile is listed if not [ 2nd button in the External Structure Area & add it [ Lock Button [ Lock on New Save [ OK Save All Files & return to Studio
Figure 185
Figure 186
224
Figure 187
Things to Notice Try to delete an Empl record. An error message will appear! We will learn how to solve this problem in the next lesson, when we cover how Saves and Deletes propagate. Create a new Empl record and note the Save validation message. Also, check that the employee code is auto-assigning from the system file. Check the ComboForm Validation Table on the Pay_Type field Check for the Error message when Pay_Rate value is out of range Check the Default Value of the state field Status Help lines appear for the Empl.Code field
Data Access Corporation 225
Compile and Test the Application Open the Empl View and note the items in the chart
1. Where in the Studio and Database Builder will a right-mouse-click call up a popup menu?
2. What are the advantages of validation tables over creating a parent related file?
3. What are the advantages of a parent related file over a validation table.
226
Lesson 6
Data Dictionarys Part 2
This lesson covers the more advanced topics of DataDictionarys.
227
Methods Tab
The Methods Tab allows us to add manual code, such as new procedures or modification of existing procedures, to the DataDictionary Class. In the lab, we will be modifying the Update and Backout procedures to send a new message called Adjust_Running_Empl_Total that will increment or decrement the running Employee total for that department. We could simplify this by eliminating the Adjust_Running_Empl_Total procedure and just put the calculation into the Update and Backout procedures but by adding the new procedure, it demonstrates how to accomplish more complex running totals.
Figure 188
The list of Unaugmented Methods allows you to quickly add the most often used procedures and functions. Double clicking on the procedure name will create a blank procedure ready for custom code additions
228
Options Tab
The Options tab page displays various datadictionary options that apply across all fields in the file.
Figure 189
When entering new records into a database the field options from the Field Setting / Options page are enforced. When the data is not of the main file of a view (but data of the related parent) it is common that additional options are needed. These options are referred to as Foreign Field Options and are separated into three groups: Key Fields, Indexed Fields and Default Fields (which include all other fields).
When entering new records for the Empl file, you would want to be able to enter an Employees Soc_Sec_Number, which is an index field. However, in a Time Card view, (where the Empl file is the parent file and not the main file that is being saved) you might wish to find on this field but you would never wish to change it. This is why you will use the Find Required and NoPut options on the Indexed Foreign Field Options.
Error Handling This is the general error message for all validates that fail and do not have an individual field error message set (Field Setting/Validation Lookup tab page). The error is triggered when one of the following validations fail: Simple Validation, Range Validation, Validation Table, or an incorrect Checkbox Value. These Validation Error Methods should be a function coded at the class level.
Data Access Corporation 229
Structures Tab
Many tasks require the DataDictionarys to communicate among themselves. An example is the save operation that propagates up the structure so all running totals are updated. A delete operation propagates down to delete child records (and then up to update running totals). The DD structure linking is normally always the same as the file structure. Therefore, the Magic Wand buttons will check the file relationships and connect missing parent/child files accordingly. The wand will only add to the list, it will not remove files from the list. Therefore, remove all files before using the magic wand.
The Delete and Save Structure Mode is used to verify the Data Dictionary Structure. It is normally safest to leave these radios to validate once (the first time).
Figure 190
To Empl.File_Number To DD_AUTOFIND DD_NOPUT DD_FINDREQ To DD_DISPLAYONLY
Example Code:
Set Main_File
Set Foreign_Field_Options DD_KEYFIELD Set Foreign_Field_Options DD_DEFAULT // Child (Client) file structure................ Send Add_Client_File Timecard.File_Number Send Add_Client_File Wk_Sum.File_Number // Parent (Server) file structure............... Send Add_Server_File Dept.File_Number // External (System) file structure.............
230
Cascade Delete
Check this option to delete all related child records whenever a delete is performed. Unchecking this option will abort the deletion if any related child records exist.
Uncheck the Cascade Delete option on the Empl database table Save the file
Figure 191
For tax purposes, we should never delete an employee that has child (TimeCard) records.
Example Code:
Set Cascade_Delete_State to False //unchecked
If you try to delete a parent record, which has related child records, this error will be generated: 4140 (Cannot delete-related records exist)
231
Database Explorer
This useful utility can be accessed directly from the Start | Programs | Visual DataFlex menu or from the Studios Database pulldown menu. It will allow you to view and change your raw data stored in your database tables. To allow changes to the database tables you must first change a default configuration setting.
Figure 192
utility
You will find MANY uses for this utility. Here are just a FEW tasks that Database Explorer can do: View and change raw data stored in your database tables Zero the database tables of test data before deploying the application Export data to ASCII or XML format
232
Lesson 6 Lab
Description: Creating more Business Rules within the DataDictionary.
Tasks:
Methods Tab
First, we will create blank procedures: Within the DBB, open the Empl file:
[ Methods Tab Expand the Unaugmented Methods Tag / Backout / Update
Figure 193
233
If the Code_Mod.txt file is not open Open it in the editor (File | Open File).
Add the new procedure and modify the Update and Backout procedures by cutting & pasting the changes from the Code_Mod.txt file
Figure 194
// this is added to the Methods tab of the Empl DD // Adjust_Running_Empl_Total: Procedure Adjust_Running_Empl_Total Integer iOne_More Calc (Dept.Number_of_Empl + iOne_More) to Dept.Number_of_Empl End_Procedure // Adjust_Running_Empl_Total
// This is added to the Update Procedure of the Empl DD Send Adjust_Running_Empl_Total 1 // This is added to the Backout Procedure of the Empl DD Send Adjust_Running_Empl_Total -1
234
Another business rule is in the TimeCard file. Whenever a TimeCard record is created, we need to update the status of the employee to Logged In or Logged Out.
Open the Timecard file [ Methods Tab Expand the Unaugmented Methods Tag / Creating Modify the procedure as shown Save & Close file
Figure 195
// This is added to the Creating Procedure of the TimeCard DD Move TimeCard.In_or_Out to Empl.Logged
235
Structures Tab
The Required Child and Required Parent list should match our file relationship structure.
This step was accomplished in Lab 2 and can be skipped if done in that lab If there are any files listed in the Required Child/Parent file areas delete them using the delete button. [ Magic Wand in the Required Child files [ Magic Wand in the Required Parent files Repeat this step for all files Save and Close all the files
Figure 196
236
Figure 197
This is a system file so it should only have one record created! Save and Exit
237
1. When using the magic wand button in the Structures tab page of Database Builder will it remove unneeded files from the required Child/Parent list?
2. What is the difference between the Validation Error No. & Text on the Field Setting | Validation/Lookup Tab and Validation Error No. & Text on the Options tab?
3. In Database Builder under the METHODS tab if you select a method from the Unaugmented list what happens to the Unaugmented and Implemented lists?
238
Lesson 7
Connecting Parts
Music will never be heard from a multi-unit stereo system if the cables between units are connected incorrectly. This lesson talks about DataDictionarys (DDs) and DataDictionary Objects (DDOs) and the connections they have. Proper connections of the DDs and DDOs in your application are crucial to it operating correctly.
239
// Wk_Sum.DD File Class Wk_Sum_DataDictionary is a DataDictionary // TimeCard.DD File Class TimeCard_DataDictionary is a DataDictionary End Class // Empl.DD File End Class
Class Empl_DataDictionary is a DataDictionary End Class // Dept.DD File Class Dept_DataDictionary is a DataDictionary End Class
We build the business rules in these files created in Database Builder utility.
2.) DataDictionary Objects in the Views: In our View, we have DDOs that are built from the DataDictionary Class that we create in Database Builder Utility.
// Empl_View.VW ACTIVATE_VIEW Activate_Empl_View FOR Empl_View
Object Empl_View is a dbView Set Label to "Empl_View" Set Size to 210 410 Set Location to 6 7 Object Dept_View is a dbView Object Dept_DD is a Dept_DataDictionary Set Status_Help Field Dept.Code to ; "F7 & F8 will find all dept records End_Object // Dept_DD //AB-DDOStart Object Empl_DD is a Empl_DataDictionary Set DDO_Server to Dept_DD End_Object // Empl_DD Object Dept_DD is a Dept_DataDictionary End_Object // Dept_DD Set Label to "Dept View" Set Size to 170 354 Set Location to 6 6 // Dept_View.VW ACTIVATE_VIEW Activate_Dept_View FOR Dept_View
Object Container1 is a dbContainer3d Set Size to 145 335 Set Location to 5 5 Object Dept_Code is a dbForm Entry_Item Dept.Dept_Code
241
We move the business rules into our view by adding DDOs through the database Selector tool:
Figure 199
242
File Relationships: The connection between child-to-parent file relationship is only one way. DataDictionary Structure: The connecting of DD to DD is bi-directional and done with the Send Add_Client_File and Send Add_Server_File messages.
Dept.DD
Empl.DD
TimeCard.DD
Wk Sum.DD
//Sample code showing these methods: Class Empl_DataDictionary is a DataDictionary Procedure Define_Fields // Child (Client) file structure................ Send Add_Client_File Timecard.File_Number Send Add_Client_File Wk_Sum.File_Number // Parent (Server) file structure............... Send Add_Server_File Dept.File_Number
243
Figure 200
244
The connecting of DDO to DDO is done by setting the DDO_Server property. We connect DDOs when they should act in a coordinated manner. As a general rule, the child-to-parent file updating links will match the child-to-parent relationships.
Dept
Empl
TimeCard
Wk_Sum
245
DataDictionary Object Structure: Once an updating dependency is established, the DDOs "know" about each other and can communicate directly among one another.
DEFERRED_VIEW Activate_Order_Entry FOR ; Object Order_Entry is a dbView Object Dept_DD is a Dept_DataDictionary End_Object // Dept_DD Object Empl_DD is a Empl_DataDictionary Set DDO_Server to Dept_DD End_Object // Empl_DD Object TimeCard_DD is a TimeCard_DataDictionary Set DDO_Server to Empl_DD End_Object // TimeCard_DD Object Wk_Sum_DD is a Wk_Sum_DataDictionary Set DDO_Server to Empl_DD End_Object // Wk_Sum_DD
246
Manual Steps to create a DataDictionary Object Structure in the Order Sample: Step 1 Code an object for each file. Start at the top of the file structure, and work from left to right and from top to bottom. Listing the DDOs in this order will eliminate forward reference problems of referencing a DDO in a Server property before the object declaration. Add the required DDO_Server properties. Each child file will have a Server property for each of their parents Add a constraint block in the child DDO if needed! Not all child files should be constrained. Think about your application and add the constraints where they are required.
Step 2 Step 3
Connecting DDOs within the Studio is done from the Database Selector Tool and pressing the DDO Tree button.
Since the Main DDO is OrderHea, all children files will be constrained
Figure 201
247
If a direct server is not set, then the parent objects server (Indirect server) is used. A parent object is just the object in which the current object is contained.
Figure 202
248
The Server property is what links the DEOs to their DDO Server.
Object Customer_DD is a Customer_DataDictionary End_Object // Customer_DD Object Cust_Name is a dbForm Set Server to Customer_DD End_Object // Cust_Name Object Cust_Address is a dbForm Set Server to Customer_DD End_Object //Cust_Address Object Cust_City is a dbForm Set Server to Customer_DD End_Object // Cust_City
DataDictionary Objects (DDOs) are objects that act as an interface between the database file and the Data Entry Objects. They are objects built from the filename_DataDictionary class that we created using Database Builder. Therefore, they will know about all the business rules we created. Data Entry Objects, (DEOs) are objects that allow data entry, such as dbForms, dbGrids, and dbEdits.
249
Object Nesting
Nesting of Objects is the actual physical positioning of one object inside another object in the source code. The Studio tool Controls Palette has data containers that are useful in grouping data aware objects. Direct Server specifically Object Customer_DD is a Customer_DataDictionary set in this object
End_Object // Customer_DD Object Customer_Info is a dbContainer3d Set Server to Customer_DD Object Customer_Name is a dbForm End_Object // Cust_Name Object Customer_Address is a dbForm End_Object // Cust_Address Object Customer_City is a dbForm End_Object // Cust_City End_Object // Customer_Info
Notice here that by setting the server in the parent data container object we do not need to set it in the individual data aware objects
DDOs should never contain DEOs. Since these objects do not specifically set the Server property (Direct Server), they will use their parent objects server (Indirect Server)
Reasons for nesting DEOs: Navigation / Visual Design Changing the cursor navigation through the objects by adding container objects. Organizing related fields inside a container will allow the use of the F6 key (the switch accelerator key) to jump to the next container and back. Delegation of Messages (i.e.; the setting of the server in the data container indirectly sets the server of the nested dbForms)
250
Lesson 7
Figure 203
If the objects are using different DDOs, then each will work independently of the other.
251
Lesson 7 Lab
Description: Checking the DDO structure of our views so they operate correctly.
Tasks:
Open our three views and from the Database Selector tool click the DDO tree button Check to be sure that the DataDictionarys are all listed (except for SysFile) and that the main DDO is correct Main DDO of Dept View is Dept Main DDO of Empl View is Empl Main DDO of Dept/Empl is Dept Correct anything that may be incorrect. Compile a view and check that you are able to delete records.
Figure 204
252
253
254
Lesson 8 Constraints
Lesson 8
Constraints
Constraining the DataDictionarys will limit the displaying of the records to meet the criteria of the constraint.
255
Lesson 8 Constraints
Constraining Records
Constraining DataDictionary Objects will filter the records that they display. There are two basic types of Constraints: Constrain_File Property for Relational Constraints OnConstrain Procedure
Constrain_File Property
When is a relational constraint needed? We constrain the view so only related child records of the parent can be seen. This constraint is needed in some views and not desired in others.
256
Lesson 8 Constraints
Needs a Constraint
In this view, we want the table to fill only with Employees (child records) that are related to the Dept. (parent record).
Figure 205
The Studio will set this constraint for you, based on the Main DataDictionary of the View.
The figure shows how to set & view this constraint in the Studio.
Figure 206
257
Lesson 8 Constraints
Does Not need a Constraint Here we do not wish to limit the viewing of child records (Empl) to only the children of the found parent record (Dept).
If we did constrain the Employee file, after finding this record all other finds on any employee indexes would only find Tech Employee records.
Figure 207
Lesson 8 Constraints
Constraining is most commonly done on a child file to show only the related records of the parent record currently shown. This type of relational constraint can be accomplished by a property setting or by an OnConstrain procedure.
Object Empl_DD is a Empl_DataDictionary Set Constrain_File to Dept.File_Number // or replacing the above property with the following procedure will do the same thing // // // Procedure OnConstrain Constrain Empl Relates to Dept End_Procedure // Empl_DD
End_Object
259
Lesson 8 Constraints
OnConstrain Procedure
We can use constraints to restrict the database viewing in many ways. Here we limit the view to only TimeCard records with a date greater than 01/01/2000
Procedure OnConstrain Constrain TimeCard.Date GE 01/01/2000 End_Procedure
Multiple Constrain Commands: Here we limit the view to only TimeCard records with dates greater than 01/01/2000 and Empl_Code that are greater than 250. If possible, the constraint listed first should be the primary segment of an index in order to increase performance. It also should be the most limiting constraint.
Procedure OnConstrain Constrain TimeCard.Date GE 01/01/2000 Constrain TimeCard.Empl_Code GE 250 End_Procedure
Avoid Expressions: The above example can also be written like this, but because of the use of expressions it would not be optimized. For this reason avoid using the AS syntax whenever possible.
Procedure OnConstrain Constrain TimeCard as ((TimeCard.Date >= 01/01/2000) and ; (TimeCard.Date <= 06/30/2000)) End_Procedure
260
Lesson 8
Steps to Changing Constraints on the Fly! (While the program runs) 1. Create a property. A property will keep its value as long as the object persists. Properties will be covered in detail in a later lesson. 2. Create an interface that will allow the user to alter the value of the property. 3. Send the message Rebuild_Constraints to the DataDictionary every time the value of the property changes.
Property Boolean pbLimitView False ... Procedure OnConstrain If (pbLimitView(Self)) Constrain Customer.State EQ "FL" End_Procedure // An interface (such as a button that would pop up a form) would be needed to // change the value of the property and Rebuild_Constraints would have to be // sent whenever the property was altered. If the DEO was a dbGrid then // Beginning_of_Data may be required.
A field in a System File could also be used, but since this field could change it is not a very good method, unless you have a method of sending Rebuild_Constraints whenever the field is changed.
... Procedure OnConstrain Constrain Customer.State EQ SysFile.Local_State End_Procedure
261
Lesson 8 Lab
Description: Modifying the Employee Selection List to constrain the viewing of the records to only active employees. Tasks: Constrain the selection list so only active Employees (employees that have their Termination_Date field blank) will be shown. This can be accomplished in the Studio by opening the Empl.SL file and modifying the DDO.
262
Figure 209
File | Open Component [ Views from the comboform [ Employee View [ OK button Compile & Test Enter a Termination Date for an Employee & Save test that it does not show in the Selection List
263
Empl DD
Change a State Field to something other than the local state & save You should no longer be able to find the record using the F7&F8 keys
Figure 210
Use Database Explorer to check the Empl.St field to ensure that the constraints are only showing the correct data.
//--------------------------------------------------------------------------------------// Only show Employees that match the default state in the SysFile //------------------------------------------------------------------------------------// Add to the Empl_DD in the Empl_View Procedure OnConstrain Constrain Empl.St EQ SysFile.Local_State End_Procedure
Thus if this application were deployed in Florida, the value of the Local_State field would be FL, however in California it would be CA.
264
2. If you look in the properties of the selection list, the Ordering property (which index to use) is set to zero. Why is that?
3. After the constraint in the Employee View is added, can you save an employee that has a termination date greater than zero?
4. How could you make the Selection List use the same DataDictionary constraints as the invoking view? (without copying or moving the OnConstrain code from one to the other)
265
266
Lesson 9
All about Messages
Love may make the world go round but it is Messages that make Object Oriented Programs go round. The cascade of messages being sent is what makes everything happen in an OOP program. Developers must be able to understand and send messages in order to make their programs operate.
Properties (creating) Properties (Set Get Commands) Object Properties Itme Properties Procedures Functions Functions as Expressions Categories of Messages Delegation & Container Objects On Procedures (Events) Using OnClick / OnActivate App / OnMaxText Events Creating Buttons Creating Checkboxes & Radios Lab 9 Checking the Servers Properties Highlighting a Grid Row
OBJECT ORIENTED EXAMPLE: Matching message name and called Sound_Alarm Send Sound_Alarm // Jumps to a procedureProcedure name
268
Event
Message Sent
Pressing F2 key
269
Self is the object where the processing is taking place at that instant. There is a property Self that returns the Object ID of the current object (a synonym for Self is Current_Object).
If the users cursor were sitting in the Customer_State dbForm, both Current and Focus Objects would be this Customer_State dbForm. If the user presses the Save Key, the Focus Object remains the same and the Current Object changes according to which object is processing the many messages that cascade from the Request_Save message. You can reference Self in order to get the Object_ID of the current object.
Move Self to hoCurrentObj
270
Sending a Message
Defaulting to the Current_Object Sending the message my_routine without referencing an object will cause the message to be sent to the current object (the object currently in control).
Send My_Routine
Directing a message to a specific object In order to send a message to a specific object, we need the objects ID. Here we wish to send the My_Routine message to the oEmplView object. It will find an object named oEmplView, return the object ID, and then send the My_Routine message to that object ID.
Send My_Routine of oEmplView
You may see old code that uses the syntax Send MessageName to ObjectID instead of Send MessageName of ObjectID. For consistency, the of syntax works better since it is the same for properties and procedures and functions. Set MyProperty of oObjectName to XYZ Send MyMessage of oObjectName Get MyFunction of oObjectName to iVal
Note: Code Editor Hint: After you type Send MessageName of the editor will popup a list of object names of all objects in the current component.
271
Access Methods
Access methods are used to direct a message to a particular object. Access methods are functions, which return the object ID.
Types of Access Method: Object Referencing Current_Object / Self Access Method Full Access Method
Object Referencing This is the simplest and recommended method. You simply list the object name and it will determine the object ID and send the message to the correct object.
Send Change_Label of oCustomer_Phone
Self or Current_Object Access Method: This is an older method that required you to add the current_object or Self keywords.
Send Change_Label of (oCustomer_Phone(Self)) // Or Send Change_Label of (oCustomer_Phone(current_object))
Full Access Method: This method involves listing the full nesting structure of the objects. Using this method is lengthy and to be avoided if possible.
Send Change_Label of (oCustomer_Phone(oCustomer_View(oClient_Area(oMain(Desktop)))))
This command is read: Send Change_Label to oCustomer_Phone child of oCustomer_View child of oClient_Area child of oMain child of the Desktop
Note: If you are maintaining old code you may run into the Name_Object access method. This is an obsolete command and should not be used.
272
When a message is sent to an object, it does not stop there if the object does not have a corresponding method (procedure or function). It loops through a three-step cycle trying to find the method. The message cycles through the three steps repeatedly, trying to find a method with the same name as the message being sent. When it finds the method, the method is executed. These three steps are:
2. Forward the message (forward the message up the inheritance path, through classes)
3. Delegate the message (pass the message through to the parent object). Delegation does not happen automatically in other OOP languages. DataFlexs default is to automatically delegate.
The next page will demonstrate what will happen if we send a message that does not exist. We will get an error at the desktop but the next page shows all the steps.
273
Invalid message MSG_Print_Label Status <<98>> on line #25119 Step D1: Check Current_Object Step D2: Forward dbView Up Class Hierarchy
Step C1: Check Current_Object Step C2: Forwarding dbTabDialog Up Class Hierarchy
Object oComments_TP is a dbTab page Set Label to "Comments" Object oCustomer_Comments is a dbEdit Entry_Item Customer.Comments
Step A1: Check Current Object Step A2: Forwarding dbEdit Up Class Hierarchy
On_Key Key_Alt+Key_P send Print_Label Step A3: Delegate to Parent Object End_Object End_Object End_Object CD_End_Object // oCustomer_Comments // oComments_TP
// oCustomer_TD // oCustomer_View
274
Steps: 1. The oCustomer_DD is first evaluated to find the Object_ID. These are the steps to find the object ID of oCustomer_DD. oCustomer_Comments do you have a child object called oCustomer_DD? No, then forward & delegate oComments_TP, do you have a child object called oCustomer_DD? No, then forward & delegate oCustomer_TD, do you have a child object called oCustomer_DD? No, then forward & delegate oCustomer_View, do you have a child object called oCustomer_DD? Yes, then return the Object ID. This will be something like 97.
Optimizing your code: If many messages are to be sent to the same Object it is more efficient to place the object ID into a local variable and send the messages to that variable.
Procedure DoIt Integer hoObjID // Object ID hanble Move oCustomer_DD to hoObjID Send Clear of hoObjID Send Find of hoObjID First_Record End_Procedure
275
Object oParent Messages should NOT flow directly in these paths Object oChild Object oGrandchild
Object oSibling
276
In our example, the grandchild is an edit object displaying a large text field. If the parent object wanted the grandchild to jump to the top of the text field, the Beginning_of_Data message would be sent to the grandchild.
To correctly send a message without breaking encapsulation we relay the message down to the inner object.
Object oParent ... Send Update_Your_Child of oChild ... Object oChild ... Procedure Update_Your_Child Send Beginning_of_Data of oGrandchild End_Procedure Object oGrandchild is an Edit .... (Beginning_of_Data is received and the Cursor is sent to the top of the Data in this object) End_Object End_Object Object oSibling End_Object End_Object
277
Neighborhoods
As you can see from the above topics sending a message can sometimes become difficult. Neighborhoods are used in a limited (almost exclusively by visual objects) but very useful way. Their main purpose is to hide visual containers. This will make sending messages MUCH easier. Neighborhoods will find the objects that you previously could not find by flatting out the visual container objects.
Everything we have covered so far in this lesson still applies. The only difference is the FIRST neighborhood found if it were a public neighborhood, it would check its list of neighborhood objects.
Each object has a peNeighborhood property that is set to one of three settings. This property is available through the Studios Object Properties dialog. nhPublic: This will flag the object (views, tab-views, modal dialogs) as a public neighborhood, and will maintain a list of neighborhood objects. nhPrivate: This will flag the object (controls, arrays, reports, etc.) as a private neighborhood and will not maintain a neighborhood list. This is the default for most objects and is the standard black box theory of OOP. This theory states that objects are encapsulated by their parents black box (will not be accessible to outer objects). Private neighborhood objects will register themselves in their parents neighborhood but will STOP their child objects from registering themselves in a neighborhood (which will make the children hidden). nhNo: This setting is used for visual containers. They will register themselves in their parents neighborhood and allow their child objects to also register themselves in the neighborhood.
278
How objects become part of a neighborhood list: When child objects are created, they will find the first parent object that is a neighborhood (public or private, but only the first neighborhood). If it is a public neighborhood, it will register itSelf in the neighborhood list.
Note: Neighborhoods do not support duplicate object names (only one duplicate name will appear in the neighborhood list).
Public Neighborhood Object oView is a dbView Object oContainer1 is a dbContainer Neighborhood set to nhNo Object oForm1 is a dbForm Member List: oContainer1 oForm1 oContainer2
Neighborhood set to nhPrivate Notice its children are not listed in the public neighborhood
279
Broadcast Command
The broadcast command allows you to quickly send messages to a group of nested objects.
Broadcast Send Do_It //Will send the message to all immediate child objects. Broadcast turns the normal delegation off. Broadcast Recursive Send Do_It //Will send a message to all descendents of an object. //The message will be sent to a child, then to all of that child's children before proceeding to the next child Broadcast Recursive Send Do_It of Desktop //Will send the message to all objects in the program. Broadcast Recursive_Up Send Do_It //Will send the message to the most inner child object then upward to itSelf (excluding itSelf). //This mode is well suited for deactivating child objects or left-right tree navigation, where every //node on the tree is an object. Broadcast No_Stop Get IsSomeoneCelebrating to iAnswer //The No_Stop option allows a Broadcast Get command to continue broadcasting even after an object //returns a non-zero value for a Get message. When the broadcast finishes, the return value will be that of //the last object to process the message. Normally used when you know several child objects do have a //common method which you want to execute but when youre not interested in the return value.
A The command Broadcast Recursive Send Do_it sent from object A would be sent to all objects. Sent from Y would only be sent to object Z. B C D E F
Y Z
280
Delegate Send
Delegate Send is used to send the message directly to the parent object. Using it will optimize performance and will make your intentions clear.
// Both lines accomplish the same thing: Send DoIt of MyParent Delegate Send DoIt // here the Parent ID is evaluated // here the message is directly sent to the parent
281
[ Start [ Programs [ Visual DataFlex 9.1 [ Visual DataFlex Help [ Index Tab type bro [ Display Button Read the help for the two broadcast pages Look up the Delegate command
Figure 211
You can also double click on the Broadcast Command instead of the Display button.
282
Augmenting a Message Augmenting adds additional functionality to the normal operation of a pre-existing procedure. Forward Sending the message accomplishes this. Augment whenever you wish the normal procedure behavior, but need something extra to happen.
Augmenting a Procedure:
Procedure Request_Save Forward Send Request_Save Send Bell End_Procedure // do normal save behavior // then ring computer bell
If you Send instead of Forward Send the message you will get a recursive or Stack fault error.
Augmenting a Function:
Function Validate_Save Returns Integer Integer iRetVal If (Invt.Qty < 0) Begin Error DFErr_Operator "Insufficient Inventory on hand" // error message will occur after the unlock Function_Return 1 End Forward Get Validate_Save to iRetVal Function_Return iRetVal End_Function
283
Canceling a Message Canceling is done to stop an object from performing a procedure. Since your procedure is found before the predefined procedure (in the class or within a parent object), it will look no further and never find the other procedure.
Procedure Request_Clear End_Procedure
Overriding a Message Overriding a procedure is changing the normal behavior We do not forward send the original message so the normal behavior is not done. We position the procedure so it is found before the pre-existing procedure is found (normally in the current object).
Procedure Request_Delete Send Bell Send Info_Box NO DELETIONS ALLOWED! End_Procedure
Adding (creating) a Message The above methods alter pre-existing procedures. Adding a message is creating a completely new procedure. Notice when we create a new procedure we also must create a way of triggering the message. In this case, we use the On_Key command.
.... On_Key Key_Alt+Key_C Send Check_Range .... Procedure Check_Range Date dStart dEnd Get Value of oStart_Date to dStart Get Value of oEnd_Date to dEnd If (dStart > dEnd) Error DFErr_Operator The ending date must be greater than the starting date End_Procedure
284
Figure 212
Remember if the message is not found in the current object it will forward up the class hierarchy path. In this case, it should find it in one of these defining classes.
285
Figure 213
Notice the dbSpinForm is a subclass of the dbForm class. The dbForm is a defining class for the Request_Save message. When the message is forwarded up the class hierarchy path, it will find the Request_Save message in the dbForm class.
286
Local Variables
Local variables are declared in procedures or functions and only exist within the procedure or function. Variables declared outside procedures or functions are global variables.
Local Variables: Used only in Procedures or Functions Most common types are: String; Number; Date; Integer, or Real. Others are: Boolean, Time, TimeSpan, DateTime, Handle, plus advanced data types. Are Dynamic: They will grow as needed no length is indicated. Destroyed & memory released when the Procedure/Function is terminated Since they are destroyed their names can be duplicated in other procedures or functions
Note: In prior versions, local variables were always preceded with the word Local. This is no longer needed or suggested.
Note: Try never to use Global variables! They consume memory, cause undesired dependencies, and cause naming conflicts, since Global variable names cannot be used as a Local variable name!
287
On_Key Commands
These are used to send a message from a key combination or from one of the predefined accelerator key functions. Adding an accelerator key can act as a shortcut to options from the menu bar or button.
On_Key key_name send message {of object} {private} Stops child objects from inheriting Name of the Message
Accelerator key function name or a physical key combination Accelerator Key Functions: (cannot change the hot key associated with them)
On_Key KCancel Send Exit_Application On_Key KUpArrow Send Previous
Note: Child objects will inherit accelerator keys (just like messages) through normal delegation unless the Private option is used.
288
Properties (creating)
Syntax
Property type property_name initial_value
Often we need to store a value from one object and have access to the value from another object. Procedural programmers have a tendency to want to create a global variable but creating a new property is the correct way to code this. The solution is to: 1. Create a property in an outer parent object 2. Use the Set command to store the data 3. Use the Get command to retrieve the stored data Sample of creating a property:
Object oMy_View is a dbView Property integer piClick_Counter 0 // new property created and available to all objects in the dbView Object oMy_Button is a Button Procedure OnClick Integer iClicks Get piClick_Counter to iClicks Increment iClicks Set piClick_Counter to iClicks Set Label to iClicks End_Procedure End_Object // oMy_Button End_Object // oMy_View // Set the property value // Get the current property value
Note: Instead of procedures or functions that pass many arguments it may be better to create a new class that has new properties. With the Set and Get commands, these properties can be easily stored and altered, eliminating the need of argument passing.
289
The Studio sets properties for you such as Location, and Application_Name.
If we leave off the {of object }, it will default to the current object.
290
Item Properties These are properties at the item level. Items are zero-based, so the second item is referenced as item 1. Syntax:
Set property_name {of object} {item_number} to value {value 2 ...} Get property_name {of object} {item_number} to return_value
Object DtlGrid is a dbGrid Set location to 5 10 Begin_Row Entry_Item Invt.Item_id Entry_Item Invt.Description Entry_Item Invt.Unit_price Entry_Item Orderdtl.Price Entry_Item Orderdtl.Qty_ordered Entry_Item Orderdtl.Extended_price End_Row Set Form_Width item 0 to 55 // this column will be shadowed
The word item is no longer required and can be left off on all these command lines.
Set Header_Label item 2 to "Unit Price" Set Form_Width Set Column_Shadow_State item 2 to true End_Object item 3 to 43
291
Procedures
Procedures and Functions are very similar. The main difference is that a Function will always return a value. A procedure can return a value but this is reserved for legacy procedures. Newly created procedures should not return values.
Syntax:
Procedure procedure_name {type1 arg1 ... ... typeN argN} variable_type name ... {forward send procedure_name arg1 ... argN} // statements to perform when this procedure is executed End_Procedure
Note: There is also a procedure {set} option, which is an advanced concept. A full example of this can be found in Appendix B.
Example: When the message Authorize is sent it also passes a string argument. This argument is placed into a local variable called sUser_Rights.
Object oMyOKButton is a Button Procedure OnClick Send Authorize SUPERVISOR End_Procedure End_Object Procedure Authorize String sUser_Rights If (sUser_Rights = "SUPERVISOR") Send Activate of oMain_View End_Procedure ...
292
Functions
Functions always return a value. Therefore, instead of using the Send command we use the Get command. This is similar to retrieving the setting of a property. Syntax:
Function function_name {type1 arg1 ... ... typeN argN} returns return_type variable_type name ... {forward get function_name arg1 ... argN to value} : // statements to perform when this function is called Function_Return value End_Function
Get function_name {of object_name } arg1 ... argN to value // functions can also be written as an expression Move (function_name (Self, arg1)) to value
Sample:
Function Wage_Increase Number nWage Returns Number Number nAfter_Raise Calc ( nWage * 1.10 ) to nAfter_Raise Function_Return nAfter_Raise End_Function
Here we pass the value of Empl.Wage to the local variable called nWage. The function returns the value nAfter_Raise into the variable nWage_Incr.
Note: (prior DataFlex Users) Many of your Macro commands can be easily converted into Functions. In fact, many DataFlex commands have been replaced with functions, e.g., Append and Length.
293
Functions as Expressions
A Function can be used as an expression, while procedures cannot. This example uses an expression for an Entry_Item. (the database in this example is not the one in our labs)
Object oCustomer_Grid is a dbGrid //AB-StoreTopStart Function DaysSinceOrder Returns Integer DateTime dHireDate dToday TimeSpan tsDiff Integer iDays Move Customer.Last_Order_Date to dHireDate Move (CurrentDateTime ()) To dToday Move (dToday - dHireDate) To tsDiff Move (SpanTotalDays (tsDiff)) To iDays Function_Return iDays End_Function // DaysSinceOrder //AB-StoreTopEnd Set Main_File to Customer.File_Number Set Size to 105 239 Set Location to 12 24 Set Wrap_State to TRUE Begin_Row Entry_Item Customer.Last_Order_number Entry_Item Customer.Last_Order_date Entry_Item (CurrentDateTime()) Entry_Item (DaysSinceOrder (Self)) End_Row
The Self keyword is left off on Global Functions The Self keyword on other functions is used as the location. Only use the Self keyword as a parameter on Global functions.
If the function has arguments, they are passed just before the closing parentheses. Here Empl.wage is passed as an argument. Ex: Move (Wage_Increase(Self, Empl.wage)) to nWage_Incr
294
Categories of Messages
Properties, procedures, and functions fall under three categories.
Public messages are the most commonly used messages and are intended to be sent or altered in typical programs.
Protected messages are available for special uses, but not likely to be sent or altered in typical programs.
Private messages are used by the class internally to accomplish a goal. They should not be sent or intercepted! Private messages could be removed when a class is modified.
295
The example on the next page will show how the Parent Server is used if the nested objects do not explicitly set the server.
Figure 214
296
Visual DataFlex Code: Here the container is setting the server. The nested objects will use the same server, since they are not setting the server for themselves.
Object oContainer1 is a dbContainer Set Server to oCustomer_DD
Object oID_Form is a dbForm Entry_Item to Customer.ID End_Object // oID_Form Object oName_Form is a dbForm Entry_Item to Customer.Name End_Object // oName_Form Object oPhone_Form is a dbForm Entry_Item to Customer.Phone End_Object // oPhone_Form Procedure Request_Delete Forward Send Request_Delete Send Bell End_Procedure End_Object // oContainer1
We would not wish to repeat the Request_Delete message for all three dbForms. Therefore, we send the Attach_Server in the container (not in the dbForms) and request_xx messages sent by child objects are delegated to the parent container/object with the Attach_Server set.
297
On Procedures (Events)
Programmers often desire to add functionality to certain events. ON procedures are triggered (sent) during certain events and allow the programmer easy access to add additional functionality at the time these events occur. All Visual DataFlex event names begin with the On prefix (some older ones are missing the On prefix). It would be beneficial to look in the online help files and see what is available. Do not try to learn all the On procedures. Simply browse the list to see what is available. Some events may behave differently depending on the Defining Class.
Within online Help [ Index tab Type OnAct R this will bring you to the first On-event procedure. Browse the list to see what is available
Figure 215
298
Using OnClick Event Add this procedure inside a button to exit the application.
Object oExit_Button is a Button : Procedure OnClick Send Close_Panel End_Procedure End_Object
Using OnActivateApp Event This procedure is added to the Views main Panel object. The event will fire when the application is first activated and every time you switch to the application. This example will play a wave file upon activating our application.
Use Wave : Object oMain is a Panel Set Label To "New Program1" //AB-StoreStart Procedure OnActivateApp Playwave "c:\windows\msremind.wav" SND_ASYNC End_Procedure //AB-StoreEnd
Using OnMaxText Event Add this procedure to an Edit Object to notify that the size limit has been reached.
Object oComments is an Edit : Procedure OnMaxText Send Bell End_Procedure End_Object
299
Creating Buttons
Buttons are another method of triggering a message. Through the OnClick event it gives the user visual clues to available options.
Object oMy_Button is a Button Set Label to Cancel Set Size to 14 50 Set location to 115 36 Procedure OnClick Send Request_Cancel End_Procedure End_Object
300
Object oRadio2 is a Radio Set Label to "Printer" Set Size to 10 37 Set Location to 24 5 End_Object // oRadio2
Procedure Notify_Select_State Integer iToItem integer iFromItem Forward Send Notify_Select_State iToItem iFromItem If (iToItem = 0) Set Output_Device_Mode to Print_To_Window Else Set Output_Device_mode to Print_To_Printer End_Procedure End_Object // oRadioGroup1
301
302
Lesson 9 Lab
Description A new view will be created to log employees in, generating a timecard record. We will also be creating a Property called psInOut that will be used to set the label of four objects. Tasks The TimeCard Log-In view will contain a number of manual code additions. We will use this same view again as the Log-Out view in another lesson. This is why we will make many of the labels within the view dynamic. We will do this by creating a property called In_Out. Then procedure Activating will correctly set the label property from the In_Out property. By using this property to dynamically set these labels, we will later be able to use this same code for the logging out of employees. By simply setting the property to Out all the labels will also change. Creating new TC_In View:
[ New View button From the Database Selector tool, select the DDO tree button Check to be sure that the DataDictionarys are all listed and that the main DDO is correctly set to TimeCard_DD
Figure 216
303
File.Field to Display
dbGrid Empl.Code oEmpl_Grid Grid Options: Empl.Last_Name Main File=Empl Empl.First_Name Index =#2 dbGroup Process Button Log dbForm * Empl.First_Name First Name: TextBox At dbForm * TimeCard.Hours Hours: dbForm * TimeCard.Minutes Minutes: dbForm * TimeCard.Reason_Code Reason Code: dbEdit TimeCard.Memo Memo: * Set Label_Column_offset to 0 and Label_Justification to JMode_Top
The table on this page lists the fields and other items to modify. Use the Database Selector and the Controls Palette tools to make all the objects. Use the Object Properties dialog to name the objects and set their labels (some labels are set to jMode_Top & 0 offset). Use the Object-Order Definition Tool to correct navigation
Figure 218
It is important that the view is correct up to this point before adding manual code.
Classroom Environments: Verify your classmates work and have them verify yours. Make sure that all objects are created and are the correct type Self Study: Verify your work with the chart and screen shot (on the prior pages) Dont forget to save the view as TC_In
306
Here we retrieve the value of the InOut property to use in our labels Green Line
Figure 220
307
308
Empl_DD:
Add the manual code from the Code_Mod.TXT file to the Empl_DD object
Figure 221
//---------------------------------------------------------// Add to the Empl_DD in the TC_In view // Only display In or Out Employees depending on first // character of the psInOut property //---------------------------------------------------------Procedure OnConstrain String sVal Get psInOut to sVal Move (Uppercase(sVal)) to sVal Move (Left(sVal,1)) to sVal Constrain Empl.logged NE sVal End_Procedure
309
TimeCard_DD:
Add the manual code from the Code_Mod.TXT file to the TimeCard_DD object
Figure 222
//---------------------------------------------------------// Add to the Timecard_DD in the TC_In view // Remember the DD also has a procedure Creating that moves // the TimeCard.In_or_Out to the Empl.Logged field. This is // one of the times that it is very important that we do not // Forward Send first. //---------------------------------------------------------Procedure Creating // Since the TimeCard.In_or_Out is only one character long // the psInOut property value will be truncated Move (Uppercase(psInOut(Self))) to TimeCard.In_or_Out Forward Send Creating End_Procedure
310
Textbox Object:
Add the manual code from the Code_Mod.TXT file to the oTextbox1 object
Figure 223
//---------------------------------------------------------// Add to the oTextBox1 in the TC_In view // Dynamically set the Label property (opposite to the // value of the psInOut property //---------------------------------------------------------Procedure Activating String sIO Forward Send Activating Get psInOut to sIO Move (uppercase(sIO)) to sIO If (sIO = "IN") move "Out" to sIO // this will toggle the status from In to Out Else move "In" to sIO // this will toggle the status from Out to In Set Label to ("The Following Employees are logged" * sIO * ":") End_Procedure
311
Empl_Grid Object:
Add the manual code from the Code_Mod.TXT file to the appropriate object
Figure 224
//---------------------------------------------------------// Add to the oEmpl_Grid // Do not allow any changes in the grid //---------------------------------------------------------Set Allow_Bottom_Add_State to False Function Row_Save Returns integer Error DFErr_Operator "No Saves allowed to this grid!" Send Refresh Mode_Find_or_Clear_Set Function_Return 1 End_Function Procedure Request_Delete Error DFErr_Operator "No Deletes allowed to this grid!" End_Procedure
312
Process Object:
Add the manual code from the Code_Mod.TXT file to the dbGroup appropriate object
Figure 225
//---------------------------------------------------------// Add to oDbGroup1 in the TC_In view // Dynamically set the Label from the psInOut property //---------------------------------------------------------Procedure Activating String sIO Forward Send Activating Get psInOut to sIO Set Label to ("Process" * sIO * ":") End_Procedure
313
Button Object:
Add the manual code from the Code_Mod.TXT file to the Button object Paste over the existing OnClick procedure
Figure 226
//---------------------------------------------------------// Add to oButton1 // Dynamically set the Label from the psInOut property //---------------------------------------------------------Procedure Activating String sIO Forward Send Activating Get psInOut to sIO Set Label to ("Log" * sIO * ":") End_Procedure //---------------------------------------------------------// Process the selected employee saving & refreshing list //---------------------------------------------------------Procedure OnClick Delegate Send Request_Save // delegate will start the message in the parent object Send Beginning_of_Data of oEmpl_Grid // move to top of grid & remove logged employee from list End_Procedure
314
Figure 227
315
You should have already saved this view but to change the description or defer the object you can call up the component property dialog.
Component | Properties Verify the data in the dialog [ OK
Figure 228
316
[ Test compile and run component in the debugger button Check that: It compiles without errors 4 labels displayed correctly Grid has row highlighted Lower name object matches grid Grid disallows saves & deletes
Warning:
The view is not complete yet, so do not add any records!
Figure 229
Note: (everyone) To fully understand code requires time to study it. As time permits, follow through the manual code segments at your own pace.
317
2. If you cancel the Request_Clear procedure in a container object that contains many dbForm objects will it affect the Request_Save?
3. What would happened if Forward Send Creating was listed before the Move command in TimeCard DD objects Creating procedure we just added in the lab? Here is the code:
Procedure Creating // Since the TimeCard.In_or_Out is only one character long // the psInOut property value will be truncated Move (Uppercase(psInOut(Self))) to TimeCard.In_or_Out Forward send Creating End_Procedure
318
6. Create a new view with a grid displaying the Empl.Code; Empl.Last_Name and Empl.Term_Date fields. Use the RadioGroup Class to set up a dynamic constraint to show: All Employees Terminated Employees Active Employees
319
320
Lesson 10
Items & Predefined Classes
This lesson covers topics such as images and special On events that trigger messages to be sent whenever these events occur.
321
Items - Zero-Based
Most Windows classes only have one item so the item will default to item 0. For Example, in the case of a dbEdit class, you may have a need to reference each item (line) separately. Items are zero based, meaning that the first item is item 0. The property current_item is the item that the user is currently interacting with.
Object Copyright is an Edit Set Size to 100 200 Set Location to 10 10 Procedure Activating Forward Send Activating
Set Read_Only_State to True //This will stop the user from making changes to the text
Set Value 0 to "Copyright 2004 Data Access Corporation" Set Value 1 to " Set Value 2 to " Set Value 3 to " End_Procedure End_Object Data Access Corporation" 14000 S.W. 119 Avenue" Miami, Florida 33186"
Other multi-item classes are grid, list, edit, menu, dbList, dbGrid, array, and set.
322
These are item references or in the case of an Edit object, the line number
On_Key Key_Alt+Key_U Send Add_Phone Procedure Add_Phone String sCurrentVal Integer iLineCount Get Value to sCurrentVal //move the value from this dbForm into sCurrentVal variable Get LineCount of oCopyright_Object to iLineCount // find the max line count of the edit object Set Value of oCopyright_Object iLineCount to sCurrentVal End_Procedure End_Object
323
// Adding parentheses around it can also return a property value If (Column_Shadow_State(Self,4)) send Extra_Processing
Column properties may be set dynamically, although such usage would be unusual. If the property is changed when the object is active, you will not see a change in the objects appearance until you redisplay the object. The following sample would toggle a columns checkbox state and update the dbGrid as required.
Procedure Toggle_CheckBox Boolean bState Get Column_Checkbox_State 4 to bState Set Column_Checkbox_State 4 to (not(bState)) // If the object is active, we must redisplay it to see changes If (Active_State(Self)) Send Display End_Procedure
Note: Column_xxx states must be set after the Entry_Items, in order for it to take effect. (e.g. in the bottom code section below the comment line in the editor).
324
Lesson 10 Lab
Description: Practice using the dfTimer class, by adding all the parts to make this timer a functional part of our view. This lesson also duplicates the view and shows how to register an external component so the Studio will recognize it. It then adds the new views to the overall application. Tasks:
Creating Timers
(This is an outline; the detail instructions will follow) Add a timer event that will default the time into the TimeCard record. We use the Field_Default_Value so we do not trigger the Data Loss message when we close the view.
We will be using the dfTimer class from the Studios Controls Palette Tool (NonVisible tab page).
The properties of the dfTimer object will set the frequency that the timer will fire and list which object should be sent what message.
The Timecard DataDictionary Object will contain the Update_Time message that will default the current time into the TimeCard record.
The Log In/Out button will send the Request_Save message. It will also send Beginning_of_Data so the selected record in the grid will be removed and our cursor will be returned to the top of the list.
325
Figure 230
326
[ TimeCard_DD Add the new code segment below the code already there.
Figure 231
//---------------------------------------------------------// Add to the TimeCard_DD object // This procedure triggers the timer. // It sets the date & time values in the TimeCard record. //---------------------------------------------------------Procedure Update_Time Integer iHr iMin Date dToday SysDate4 dToday iHr iMin Set Field_Default_Value Field TimeCard.Date to dToday Set Field_Default_Value Field TimeCard.Hours to iHr Set Field_Default_Value Field TimeCard.Minutes to iMin End_Procedure
327
[ Test compile and run component in the debugger button Check that the timer is updating time Log someone in: Select a Reason code from the comboform and then press the Log In Button Were they removed from the list? Exit back to the Studio
Figure 232
Warning! The Reason code is a Validated field. An error will be generated if you leave it blank!
We will need two views one for processing the employees in and one to process them out. Therefore, we will save this view under two names.
File | Save As Enter the data as shown [ Save Button Close this view and
Figure 233
328
329
The closing and reopening of the views will refresh the code explorer.
The psInOut property that we created affects the labels and the constraining of the view. Therefore, the only change that we will have to make to our new view is changing its default property value from In to Out. Default setting Within TC_Out view:
[ oTC_Out Change the default property setting from IN to OUT Compile the View and make sure the In & Out labels are correct
Figure 234
Warning! You might have to close the component view and reopen the view in order for the tree view to show the object name change from oTC_In to oTC_Out.
330
Figure 235
331
2. What information can you get by clicking on "Help/About..." of a running VDF application?
Note: (everyone) To fully understand the manual code requires time to just study it. If time permits, follow through the manual code segments at your own pace.
332
333
Lesson 11 Troubleshooting
Lesson 11
Troubleshooting
This lesson covers Troubleshooting techniques.
335
Lesson 11 Troubleshooting
Studio Databases
The Studio uses two databases, ddData and abData files. The Studios Workspace pulldown menu has the Maintain and Reindex options. These options allow you to update or reindex the databases. ddData file contains a record for each DataDictionary created. abData contains a record for all the subcomponents of the Studio. Knowing about these files and how to reindex them can sometimes solve your problems.
Workspace | Reindex Studio databases (it will quickly reindex the files) Workspace | Maintain Studio databases
Figure 236
Lesson 11 Troubleshooting
Troubleshooting Hints
Here is a list of troubleshooting hints that solve many program problems.
1. Compiling each View separately 2. Checking File Relationships Matching length/type of related fields Matching DataDictionary Required Parent/Child structure
3. Checking for unique index on the parent related field: 4. Rebuilding the DDO Tree within the View 5. Checking the Data 6. Debugging Compiling Errors & using a .PRN file 7. Creating a Small Test Program 8. Debugging Runtime errors
337
Lesson 11 Troubleshooting
1. Compile Each View Separately Each view should be tested and compiled separately before it is added to the complete program. The ability to conduct stand-alone tests is one of the benefits of OOP. This will make tracking down problems less painful and time consuming. If multiple views are not compiling, it may be a DataDictionary error. An error in the DataDictionary will affect all views that use the common DataDictionary. To compile a single view, open the view and then click the Test compile and run component in the debugger button.
Figure 238
338
Lesson 11 Troubleshooting
2. Checking File Relationships Valid file relationships are critical to the correct operation in Visual DataFlex. Checking your relationships has been made easier in Database Builder.
Figure 239
Figure 240
339
Lesson 11 Troubleshooting
From this screen, we can print the report out. However, just reading it on screen will normally point us to any incorrect relationship.
Figure 241
The following tests are made and all mismatches reported: The length & type of each relating child field to the related parent field The parent related field is uniquely indexed The Required Child and Parent File Structure is correct
340
Lesson 11 Troubleshooting
Another way to check that the required Child and Parent DataDictionary structure is correct is to remove the references and then use the magic wand to re-add them.
Figure 242
Use the delete buttons to remove all files and then use the top (magic wand ) buttons to add back only the files that have a relationship created.
341
Lesson 11 Troubleshooting
The employee file relates to the Dept file on the Dept_Code field here we see that the Main index for this field is index 1
Figure 243
Figure 244
#2. Check that the Dept_Code field is the only field listed
342
Lesson 11 Troubleshooting
This dialog is in the Studio. Open the Empl View, then press the DDO Tree button from the Database Selector tool.
Figure 245
If the Studio encounters file relationships in your DDO Tree Structure that are not represented in the DD classes, a warning message will appear.
Main_DDO Changing the Main_DDO will affect how the Constrain File commands will be added. All Child DDOs to Main DDO will have a Constrain_File property. Notice how both Timecard and Wk_Sum are constrained to Empl, which is the Main_DDO.
343
Lesson 11 Troubleshooting
Steps to Rebuild a DDO structure: Rebuilding the DDO tree can solve many oddball behaviors that are caused by an incorrect DDO structure.
Use the Studio Editor to check for any manual code additions in the DataDictionarys. If there are any edits, cut and paste them somewhere safe. Otherwise, we will lose these additions when we complete the next step. Use the Remove button to remove all DDOs. Use the Add DDO button to add in the Main_DDO file. This will add the main DD and all ancestors (parent, grandparent, etc.) DDOs to the structure. If you disallow saves in your view, the ancestor DD files will not be necessary, unless the files are needed elsewhere in the view. Next, use the Add DDO button and add all descendent (child, grandchild, etc.) DDOs. If deletes are disallowed, these descendent DDOs will not be needed unless the files are required elsewhere in the view.
Figure 246
344
Lesson 11 Troubleshooting
5. Checking the Data During development of an application, as file structures and relationships change, invalid data can be added to the database. This bad data can be responsible for the application not operating correctly. Use Database Explorer to check for these problems: Check that System Files only has one record. Check that validated fields have valid data. Even if a field is not visible on screen, when the record is saved, all fields will be validated. If a validation on a field is added, the existing data must be validated against the new business rule.
Use Database Builder to check for these problems: Check Max Records against Records Used. Max Records should be set to about 20% above the estimated maximum size of the database. This estimate should be sufficiently large enough to accommodate the expected file, but be aware that making it too large will slow down index performance. Check for orphan records (from the Report pull-down)
Lesson 11 Troubleshooting
6. Debugging Compiler Errors & using a .PRN file The new editor in the Studio makes using the PRN files almost obsolete, but it is still worthwhile to know about this file.
Always compile each view separately. Compiling smaller sections makes it easier to locate the problem.
Even when compiling a single view, an error can still come from included files (i.e.; .DD; .SL; .PKG files).
Figure 248
346
Lesson 11 Troubleshooting
Often the errors will direct you to the last addition that you made to the program, so finding the cause of the error is not that hard. Other times you have no idea which section of code contains the error. When this is the case, you may need to look at a .PRN file.
Tools | Configure Environment [ General Tab page Click in the Compiler Switches and press F1 for help
Switches
From the help screen, scroll down until you find the words Figure 249 Compiler Switches printed in green. Clicking on this link will jump you to the full explanation of the switches. The F option will generate the .PRN file.
347
Lesson 11 Troubleshooting
This .PRN file can then be loaded into any editor. If we were compiling the entire Order application example, then the .PRN would be called Order.PRN. If you are compiling a single view, the .PRN file will be named IDETestRun_X.PRN in the \AppSrc directory. After loading the PRN file, you search for the word ERROR:. Your code will be listed here along with the error messages. The error normally will be located within the two lines of code above where the error message is printed.
We cannot Figure 250 correct the error in the .PRN file, but we can see that the code is located in the button object, so we return to the Studio and double click on the button to open the editor.
Note (Everyone): With the Studio Editor it is very seldom that looking at a .PRN file is needed. The Studio will open the correct file that contains the error just by double clicking on the error.
348
Lesson 11 Troubleshooting
7. Create a Small Test Program Whenever you use a new class or try to accomplish something for the first time, create a small test program. Creating a test program will allow you to experiment with the new properties, procedures and functions. This will give you a better understanding of the code and how to use it before including it into a large program.
To do this, look up the new feature in online help. Often there will be sample code that you can cut and paste to test.
Notice the sample code that is provided can be cut and pasted directly into the Studio.
Figure 251
349
Lesson 11 Troubleshooting
Some of the Debugger features: tracking down runtime errors setting watches message tracing
Open the CorporationX Application ] Compile and debug-run program button View | Empl View Resize the dialogs as shown
Figure 252
This will compile your application with all the debugging packages added and load & run both the debugger and your application.
350
Lesson 11 Troubleshooting
Figure 253
When starting to learn the debugger, you normally want to have all the components open.
The next step is normally setting breakpoints, which we will do in the lab.
351
Lesson 11 Lab
Description: Using the debugger. We will continue using the above example in the lab. If you have closed everything, simply refer back a few pages and set up the debugger again.
Tasks:
Debugger Breakpoints
First step is to set breakpoints. All files (views, components, .SL and packages) that make up the view will be available from the debugger comboform.
Select the Empl.dd from the comboform Scroll down until you find the Update & Backout properties [ the dots at the left (of the Forward Send statements) to create breakpoints where indicated
You cannot break on the actual Procedure line, so we break on the first line of code in the procedure. Will turn to red showing a breakpoint
Figure 254
352
Debugger Watches
Start Program Execution Button
Within the debugger, highlight Dept.Number_of_Empl and then right click on it
Step into
Select Evaluate from the floating menu [ Watch button [ Close Within the running program,
find an existing record and change the Dept code F2 to save [ OK & then continue to press the Step into button and watch the Dept.Number_of_Empl field change as it steps through the Backout and Update procedures. List the values in the chart.
Value of Dept.Number_of_Empl Before the Backout After the Backout Before the Update After the Update Your results should show Backout subtracting one from the old department count and Update adding one to the new department count.
353
3. If your users launch 3-4 copies of this program at the same time, how much memory will it use up?
354
Lesson 12
Waves and Bitmaps
This is a fun lesson that covers sounds and bitmaps and a few other GUI features of Visual DataFlex. We will add a wave file and bitmap file, adding sound and color to our application.
355
Objects of the dbBitmap class display the bitmap file named in a database field. Upon receiving the Entry_Display message from the data dictionary, the bitmap is displayed. These bitmap files store such data as personnel ID photos or inventory pictures.
Steps for Creating a dbBitmap Object All bitmaps must be created and assembled together in the bitmap directory. Create a dbBitmap from the database selector tool dragging the ASCII field into the view.
356
You may design your own bitmaps, or use any Object Print_Button is a Button *.BMP-format files legally Set Size to 10 10 available to you from any Set location to 20 20 source (*.BMP, or *.RLE Set BitMap to printer.bmp for the compressed bitmap Procedure OnClick format). Typically, you Send Print Report would design a bitmap to End_Procedure fit on, and completely cover, a control. If you End_Object want a panel or dialog to contain a bitmap, however, the chances are that you want its size and aspect ratio retained. Therefore, Visual DataFlex resizes bitmaps to fit controls, but does not resize bitmaps displayed on panels and dialogs. If you want the exact appearance of a bitmap you are putting on a control to be retained, make sure the ratio between the vertical and horizontal dimensions are the same for the bitmap as for the control.
Many VDF properties can be set to a .bmp file. Always check the help documentation for graphical file requirements. Some properties require a 24x24-pixel file.
357
Some common properties and functions are: Properties / Functions bitmap string filename bitmap_style integer BITMAP_ACTUAL| BITMAP_STRETCH| BITMAP_CENTER| BITMAP_TILE bitmap_height returns integer function bitmap_width returns integer function Description This property identifies the file containing the bitmap image for this object. This property specifies the position, size, or shape in which the bitmap image for this object is to be displayed. BITMAP_STRETCH fills the object with the image. This function returns the height of the image contained in the file named by bitmap. This function returns the width of the image contained in the file named by bitmap
Note: Bitmaps can also be used as Icons. They can also be captured to and from the Windows clipboard a complete explanation of this is in the Language Guide
358
Syntax:
Description Play synchronous. Plays from beginning to end. Will not interrupt (default setting) Play asynchronous. Interrupt playing by pressing a key. Does not play system default sound in the case that the specified file is not found. This must be Or'ed with either SND_SYNC or SND_ASYNC. Play in a loop Play non-stop
SND_LOOP SND_NOSTOP
359
Figure 256
The sound recorder buttons work very much like the buttons on a real recorder.
File | New [ Record Button and record a message File | Save As Give this file a name and save it under our\Bitmaps directory
Figure 257
360
Embedded Bitmaps
DataFlex can include bitmap files and icons into the Exe as native resources as it compiles your source code. This will increase speed of loading bitmaps and eliminate the need of copying these as separate files during deployment.
The Compiler uses the Programname.cfg file to determine what items to embed. This file can be directly edited but it also can be modified via the Studio from the Program | Properties Dialog.
Programs | Properties [ Bitmaps tab page [ Scan for images [ Yes Button [ Yes Button [ OK Button Close the Dialog
Figure 258
361
Figure 259
362
Lesson 12 Lab
Description: This lab uses one of the event procedures to add a picture as a background.
Tasks:
Open the application in the Studio [ Client_Area Cut & past the code modification from the Code_Mod.txt file Compile & Test
Figure 260
The CorpLogo.BMP file is located in the workspace \Bitmap directory, which was copied earlier from the training CD.
363
2. How can you create an icon on the desktop to automatically run this application?
3. After completing this lab, will you have to move the CorpLogo.BMP when deploying your application? What would you suggest be done?
364
Lesson 13
DDs Local Buffers & Procedures
This lesson covers some of the most commonly used DataDictionary procedures and how the DataDictionarys Local Buffers operate.
365
Without Data Dictionarys: there are three work areas Screen Buffer Area /DEO items
Set Changed_Value 0 to sVal
Hard Disk
Save Customer
With Data Dictionarys: The Screen buffer and DD Local Buffer areas are always synchronized. Change one and the other one automatically updates.
Record Buffer Area These are always synchronized. DD Local Buffer Area
Set Field_Changed_Value ; field Customer.St to sVal // in a locked state to file.field Move sVal to Customer.St
Hard Disk
Save Customer
366
Setting data entry object values vs. setting DataDictionary buffers: Within the DEO
Set Value to FL
Within the DD
Set Field_Current_Value; field Customer.State to FL This only sets the value. Without the Field_Changed_State set to true, the data will not be moved into the database during the save! Flags the field as changed, so it will saved to the database during a save operation. A short-cut. It is a combination of the two properties above
The Set establishes the property value. To retrieve property values use the Get command.
Note: Many field properties are also available in the format file_field. These will set/get the value from a parent file:
367
Optimizing Field_Exit_Msg
The prior page covered the differences between Field_Current_Value and Field_Changed_State. Field_Current_Value changes only the value on screen. If a save occurred, the data would not be moved to the database. This may lead one to believe that using Field_Changed_Value all the time would be correct, but this is not always the case. The following two examples will both result in updating the extended_price. However, in grids, the Field_Current_Value is more efficient. The following pages will show you why.
Procedure Adjust_Display_Total Integer iQty Number nAmnt Get Field_Current_Value Field Orderdtl.Qty_Ordered Get Field_Current_Value Field Orderdtl.Price to iQty to nAmnt
Set Field_Current_Value Field Orderdtl.Extended_Price to (nAmnt * iQty) // Note we set Current_Value, but not Changed_State! // Since Changed_State is not true, a save will not move the new value to the database // To update the field value we recalc it in procedure Update of the DataDictionary End_Procedure
Procedure Adjust_Display_Total Integer iQty Number nAmnt Get Field_Current_Value Field Orderdtl.Qty_Ordered Get Field_Current_Value Field Orderdtl.Price to iQty to nAmnt
Set Field_Changed_Value Field Orderdtl.Extended_Price to (nAmnt * iQty) // note Field_Changed_State will set the Current_Value and the Changed_State End_Procedure
368
Negative side effects of using Field_Changed_Value in Grids: When using a dbForm there is no big benefit of one procedure over the other. The big difference is when we are using a dbGrid. Accessing a blank row will create a record with only the Orderdtl.Extended_Price field filled in. Because the Field_Changed_Value sets Field_Changed_State to true, a save will take place EVERY time you navigate up or down the Quantity column, even though no user input took place. Using this property forcing saves, a LOT of unnecessary I/O traffic can be generated if the user scrolls in the Qty column.
Change the Studios workspace to Order Entry Sample Application Open OrderDtl in Database Builder and click on the methods tab page Scroll down to the Adjust_Display_Total procedure and change Field_Current_Value to Field_Changed_Value
Figure 261
// This updates the extended price field, which will update any // display balances. This is only done for display purposes. The actual // amount is updated to the field during the save. Procedure Adjust_Display_Total Integer iQty Number nAmnt Get Field_Current_Value Field Orderdtl.Qty_Ordered Get Field_Current_Value Field Orderdtl.Price // note we set value, but not changed state! End_Procedure to iQty to nAmnt
369
Save and return to the Studio File | Open | View | Order Entry Double click on the dbGrid and add the Row_Save function from Code_Mod.txt file Save and Compile the view
Figure 262
// Add to the top of the OrderDtl_Grid Function Row_Save Returns integer Integer iRetVal Send Info_Box "Save Operation being Called" Forward Get Row_Save to iRetVal Function_Return iRetVal End_Function
370
Click F8 (to find the first record) Click on the first row of the Qty Column Move down the Qty Column without changing any values Note that a save is being triggered because of the Field_Changed_Value property. Continue down the Qty Column until you come to the first blank row
Figure 263
When you try to leave this blank row, a save is again attempted; but this time it will generate a Status 90 error because other columns are required fields in the DataDictionary. Click OK in the error dialog & Close the running application. Open Database Builder and return Field_Changed_Value to Field_Current_Value. Leave the other changes in place, recompile and run the application. Move down the Qty Column, without changing any values. Note that no saves are being triggered. This is because the change to the Field_Current_Value property alone did not cause the line to save. The Field_Changed_State remains false and therefore no save is triggered. This time the blank line problem we experienced earlier does not happen.
371
We now see the benefits of using Field_Current_Value in dbGrids. However, since Field_Current_Value only sets the value, if we make a change to the Qty, how is the Qty field and the Extended price being saved to the database?
Open OrderDtl in Database Builder and click on the methods tab page Scroll down to the Update Procedure Note that Update will recalculate the Extended_Price field every time a save occurs
Figure 264
372
Procedure Creating
Procedure Update
Procedure Deleting
Note: When you are outside of a locked state, reference item windows or the DD local buffers. Inside a locked state, reference file.fields (record buffers). Never add code in a locked state that would wait for user intervention.
373
Procedure Creating
This procedure is only called when saving a New Record. Here we are adding the users ID to the newly created record so we can track who created the record.
Procedure Creating Forward Send Creating Move (UserID(Self)) to Empl.Created_By End_Procedure // Creating
The Creating procedure (and other procedures covered here) is an empty hook (empty procedure) within the basic class package. When the procedure is an empty hook in the Class, it is not required to Forward Send. Although it is a good practice to always Forward Send, since we may someday add new subclass layers that would then require the Forward Send.
Note: (DataFlex 3.1 Object Oriented Programmers) The Destroying procedure is obsolete, given the new transaction processing feature.
374
Procedure Update Forward Send Update Add TimeCard.Pay to Empl.YTD_Pay End_Procedure Procedure Backout Forward Send Backout Subtract Timecard.Pay from Empl.YTD_Pay End_Procedure
To fully understand how these two procedures work so harmoniously together during an edit save, we must remember that both are called during the same locked state and that Entry_Update (which moves the data from the image to the record buffer) is called between these two procedures.
STEPS: ReRead Backout Locks files and refreshes the record buffer Subtracts the original timecard amount from the running total (this is like deleting out the original record) Entry_Update Update Save Moves new data values from the screen to the record buffer Adds new timecard amount to the running total Moves data from record buffer to disk
375
// Will give an error if the inventory is not sufficient to cover the order. // This function would normally go inside the Order detail DataDictionary Function Validate_Save Returns Integer Integer iRetVal If (Invt.Qty < 0) Begin Error DFErr_Operator "Insufficient Inventory on hand" // error message will occur after the unlock Function_Return 1 End Forward Get Validate_Save to iRetVal Function_Return iRetVal End_Function
// before deleting Customer record, check if needed for end of year taxes via an active field Function Validate_Delete Returns Integer Integer iRetVal Forward Get Validate_Delete to iRetVal If (iRetVal <> 0) Function_Return iRetVal // the delete has failed, no need to continue If (Customer.Status = "Y") Begin Error DFErr_Operator "Cannot delete an Active Customer" // error will not show until unlock occurs Move 1 to iRetVal End Function_Return iRetVal End_Function // to stop the delete
Validate_Delete is called from a locked state. The error message will not appear until the operation is completed and the file is unlocked.
376
In both of these examples, the extra Hist file is not part of the DataDictionary structure. To have the file locked and reread with the other files, we would add it to the External Structure in the DataDictionary.
// Purpose: To collect a record of all save operations made to the main file into a history file. Procedure Save_Main_File // clear, move the fields into the history file & save Clear Hist Move Employ.ID to Hist.ID Move Employ.Name to Hist.Name ... SaveRecord Hist Forward Send Save_Main_File End_Procedure // Save_Main_File
// Purpose: Before deleting an employee record, save the data to a history file Procedure Delete_Main_File // clear, move the fields into the history file & save Clear Hist Move Employ.ID to Hist.ID Move Employ.Name to Hist.Name ... SaveRecord Hist Forward Send Delete_Main_File End_Procedure // Delete_Main__File
377
Lesson 13 Lab
Description: This lab will not list all keystrokes. It lists general instructions. It is a good review of many of the topics covered so far in the manual. It uses the procedures that we have learned in this lesson. It also adds an additional Company file. When an additional file is added to the File/DataDictionary structure, many steps need to be taken to make sure all existing files are updated correctly. Tasks: Open the Empl file in Database Builder and review how we maintained the running totals for the Number of Employees in the Dept file.
Figure 265
378
Using Database Builder, create a new Company file (file number = 1). Then create the needed index so this can be used as a parent file. (For help, review the rules of file relationships located in Appendix C). Company; Filenumber = 1 Fields Company_Code Type ASCII Length 4 Field Settings AutoFind CapsLock Name Total_Budget ASCII Numeric 25 8.2 Key Field AutoFind Currency Mask
Open the Dept file: Add a field in the Dept file called Company_Code (this field must be called Company_Code for a future Lab to work!). Relate the Dept.Company_Code field to the Company.Company_Code field (both fields must be the same size and type to relate them!). Create a new Index #3 with the new Company Code field and the Dept Code fields as the index segments. Both uppercase checkboxes should be checked. (Did you remember to verify the structures tab on both Company & Dept DataDictionarys?)
379
Select File | New Component and use the Invoice Style template that was created in a prior lesson. Create a small view called CoDept that will show the Company data at the top and all the related Dept records in a dbGrid below. You may wish to review the prior Lab where we used the Invoice_Style template to create the DeptEmpl view. The steps below will walk you through all the steps. Update the two default properties within the template. Company Company.Company_Code Set the Main_DDO to Company in this new view. Delete the Parent Related Object Attach the Company.Code and Company.Total_Budget fields to the first and last dbForms Add labels to these objects Add the Company.Name field Adjust the Object-Order to correct navigation among these three objects. Add Dept fields to the dbGrid. Hint: comment (text) fields cannot be placed in dbGrids. Align objects Compile and Test the view. Create a company record with the company code of DAW. Before you create this record, first press Ctrl+F5 to clear the grid. The department records already created will be showing up in the grid as orphan records. This is because their Company_Code field is blank in all these records. Do not correct this now. We will correct this in a batch process in another lesson.
380
The Dept DataDictionary file will need Update and Backout procedures to collect the running total in the Company.Total_Budget field. Review the Update and Backout procedures just covered in this lesson and the one just reviewed at the start of this lab as a model. The OrderDtl.DD in the Order sample is an excellent example to study. If you need more help, see the completed DataDictionarys in the Finished Example workspace.
What did we learn about which DataDictionarys are required in a view? (Both parent and child DataDictionarys are needed to save and delete records in the main DDO). What will happen when we go to save a record in the other views? (They will not be able to save, unless all parent DataDictionarys are present. This is because Save operations propagate up so all parent DataDictionarys are required in all views.). Make the needed changes in all views to add the Company DataDictionary using the DDO button on the Database Selector tool. Close the Database Selector tool every time you switch between views.
Update Dept/Empl View by adding the Company.Company_Code field to the view. This object should be the related parent object that was created in the Invoice_Style template but we already deleted it in the prior lab. The code is listed below and in Code_Mod.txt under lesson 13. Cut and paste it into this object. This code will shadow the parent object when you find an existing record.
Save, Compile & Test you may need to review the Troubleshooting lesson.
//------------------------------------------------------------------// Add to Parent (dbForm) object - below the green line // If Header record exists, disallow entry in Related Parent window. //------------------------------------------------------------------Procedure Refresh Integer iMode
381
382
2. Can you write a business rule so that a company must have a "NAME" (must not be blank?)
3. Can you write a business rule so that a company record can never be deleted?
4. In the Dept Backout and Update, we do not explicitly say "Save Company". When you delete or save a Dept record, is the Company total budget updated and saved? Why?
383
384
Lesson 14
Classes Within the Studio
This lesson covers the creating of new classes. These classes are then made accessible via the Studio.
385
Lets look at the DataDictionary class. The DataDictionay Class is the most common subclassed. This was done within Database Builder when we created each file. The DD file contains this subclass. This allows us to have one centralized file that holds all the rules for an individual database. If all our views use this new subclass, then we will have consistent behavior throughout our application. A new business rule added to the class will affect all views!
The DataDictionary class is not the only class that we can subclass. If we continually have to modify an object it is a good indication that we should subclass.
386
Here we create a new subclass. In addition to the behaviors already present in the AppClientArea Class, it sets the corporate logo as a background and creates a new property called pRestrict_Rights. Objects built from this new class will have the corporate logo displayed and can SET or GET the value of the pRestrict_Rights property.
// Stored in cCorp_AppClientArea.pkg file in the \PKG (global) or AppSrc (local) directory: Class cCorp_AppClientArea is a AppClientArea Procedure Construct_Object Forward Send Construct_Object Set Bitmap to CorpLogo.bmp Property Integer pRestrict_Rights 0 End_Procedure End_Class
Note: The DataDictionary class uses a special constructor procedure called Define_Fields. Other subclasses use the Construct_Object syntax.
387
Figure 266
388
. . .
As a development strategy, you will create a Global layer of subclasses, descended directly from the supplied classes. Then, for each Workspace that you create, you will subclass the Global layer to create a Workspace layer. This diagram outlines the hierarchy of classes that will then exist: Take the Button class as an example and using the supplied defaults, this is how the hierarchy would look:
Button (Visual DataFlex Supplied base class) +-cMyButton (Global subclass here the size could be globally changed) +-cWsButton (Workspace subclass the color could be changed for each customer)
In your applications, you would not create objects from the Button or cMyButton classes: you would use only the cWsButton. You would never make changes to the Button class (as Data Access would do that), but you would make changes to the global cMyButton class that you wanted all your Workspaces to include. These changes would include setting defaults different from those supplied that are appropriate for your work (changing colors, fonts, etc.), and they could even include bug fixes to those supplied classes, or new features. You would change the Workspace cWsButton to include changes specific to a Workspace. As these classes are derived from the Global subclasses, they will automatically have all the changes of the Global subclasses.
Data Access Corporation 389
When creating a subclass layer, you merely need to provide a few details and the Studio will automatically create all files that are needed to support the subclass layer. In a working development area, it is highly suggested that you create both Global and workspace layers. Creating Global Layer:
Tools | Create Global subclass layer
Warning! If you do not wish to create a global area (because you already have one created or for other reasons) then press Cancel button and do not complete the step below. On the next page, make sure you check the Original DAW installed classes.
Figure 267
Figure 269
[ Preview [ OK [ OK
Note that it will replace all cMy prefix with cWs check this radio ONLY if you did NOT create a global layer
Figure 270
391
The Studio will support templates at global and local levels: 1 Sub-component templates (a group of objects that can be saved & reloaded) 2 DFS DF Sub Components
Component templates (Lesson 4 created a View640x480 and Invoice_Style View templates) TPV TPR TPL TPD Template View files Template Report files Template List files Template Dialog files
Sub-component templates: A sub-component is any group of objects that can be saved to a file and reused in a component. What we are really doing is sort of a cut and paste into the component code.
Component templates: Any component (View, Report, Lookup list, Dialogs) can be saved as a template.
392
DFS files
A .DFS file is a DF Sub-component template. DFS files can be saved as Global or Local workspace files, stored in the \Visual DataFlex 9.1\Usr\Global\IdeSrc or local workspace \IdeSrc directory.
Create a view & drag a RadioGroup from the Base Containers tab Change the Group label to Send Report to: Change the Radios labels to Screen; Printer & File Cut & paste the manual code from the Code_Mod.txt file to the Radio Group within the Notify_Select_State procedure
We now have a component template that could be used for Crystal report views.
//----------------------------------------------------------------------// Add to the Notify_Select_State procedure of the Radio_Group //----------------------------------------------------------------------Case Begin Case (iToItem =0) Set Output_Device_Mode To PRINT_TO_WINDOW Case Break Case (iToItem =1) Set Output_Device_Mode To PRINT_TO_PRINTER Case Break Case (iToItem =2) Set Output_Device_Mode To PRINT_TO_FILE Case Break Case End
393
Saving a DFS:
[ RadioGroup Component | Save object Sub-Component | Local Enter Crystal_Print_Radio [ Save Close the VIEW without saving
Figure 272
394
Inserting a DFS
Figure 273
395
DFO Files
A .DFO file is also known as an object preference file. This file can be used to set properties, add custom source code, or to create additional child objects. When a new object is created by the Studio, the object's preference file is processed and added to the object. DFO files can be saved as Global or local workspace files, stored in the \Visual DataFlex 9.1\Usr\Global\IdeSrc or local workspace \IdeSrc directory.
Close all other components [ New Standard View button Drag a cWSDbForm from Data tab Change the object name to oName1 and the Label Name1
Figure 274
396
File | New File Cut the following code from Code_Mod.txt and paste it into this new file. Save the file as cWsDbForm.dfo in the workspace \IdeSrc directory
Figure 275
//AB/ OBJECTDEF Object Set Form_Border to Border_None //AB-StoreStart //Procedure //End_Procedure //AB-StoreEnd End_Object
Anything between the //ABStoreStart&End markers will be added to the object and accessible in the Code Explorer.
397
Drag another cWsDbForm into the view Change the object name to oName2 and the Label Name2 / Name2 to bring up the Code Explorer (the comments from the DFO should show) Save as TestNewDFO then close the view
Figure 276
398
Step #2 Create .DFC file The .DFC file informs the Studio how to handle your new class. Include the line Set ClassPackage To "Classname.pkg" OR add Use ClassName.pkg line to your DFAllEnt.pkg and pre-compile it. Creating .DFC file will be demonstrated in the lab.
The Studio can now display simple comments for each property in the Property Window. This is accomplished by changing the property declarations in a class's DFC file. The general syntax is to add the comment at the end of the property declaration after a "//". For example: Property Complex Size 150 300 // Object Size (Complex: height, width) Several special comment markers are allowed. Marker // Description This means delete any comment that might exist from the super class. Comment will be blank. Note required space between // and -. Only the single - is allowed // + xxxxxxx Append text following the + to any existing superclass comment. Old and new comment will be separated by a space. Note required space between // and + No comment or Use super class comment. Normally, just leave the comment // // xxxxxxxx Replace existing comment
399
Step #3 Updating the Studios Controls Palette Tool (required only if class should be visible on the Controls Palette tool) Copy the required 24X24 bitmap (to be used on the button in the Controls Palette) to the \IdeSrc area. Add your new subclass information to Maintain Class-List (located on the Tools pull-down of the Studio).
Note: Naming Convention - Use the same name for the class, the package file, the description file(dfc) and the bitmap file. The Maintain Class-List dialog is optimized for this notation. Ex: BigButton 1. Class BigButton is a Button . . . Save the DataFlex class in a file called BigButton.pkg 2. 3. Create the Studio class file as BigButton.dfc Create a bitmap to be displayed on the Controls Palette, called BigButton.bmp
400
401
Lesson 14 Lab
Description: This lab creates a new class and adds it to the Controls Palette for use within the Studio.
Tasks:
Figure 277
// Add to the new file called cWSPrint_Button.PKG // cWsPrint_Button class is a print button // that has a printer bitmap displayed on it. Class cWsPrint_Button is a Button Procedure Construct_Object Forward Send Construct_Object Set Bitmap to "cWsPrint_Button.bmp" Set Size To 28 30 End_Procedure End_Class
402
Step #2a Create .DFC file The .DFC file tells the Studio how to use the new class
FFile | New File
Cut the following code from Code_Mod.txt and paste it into the Code Editor Save it as cWsPrint_Button.DFC in the workspace \IdeSrc directory
//AB/ CLASSDEF // Add to the new file called cWSPrint_Button.DFC Class cWsPrint_Button is a Button Set ClassPackage to cWsPrint_Button.pkg Inherit Property No_Visible No_Generate String Bitmap cWsPrint_Button.bmp Property Complex Size 28 30 End_Class
Step #2b Create .DFO file (this is not require) The .DFO file tells the Studio how to use the new class
FFile | New File
//AB/ OBJECTDEF Object //AB-StoreStart Procedure OnClick End_Procedure // OnClick //AB-StoreEnd End_Object
Cut the following code from Code_Mod.txt and paste it into the Code Editor Save it as cWsPrint_Button.DFO in the workspace \IdeSrc directory
403
The class .PKG file would have to be added and pre-compiled in your DFAllEnt.PKG, if the Set ClassPackage line is removed from the .DFC.
The DFC options are fully described in the on-line help. Quickly look over this section
Open the WinHelp File [ Studio [ Advanced Topics [ Using Your Own Subclasses [ Anatomy of Studio Subclasses [ Introduction Look up Inherit and the other lines that were used in our .DFC
**
Figure 278
404
Close programs and components in the Studio [ Tools [ Configure Class-List [ Workspace tab [ Add button Enter the data for the new class [ Add button [ OK From Windows explorer copy the cWsPrint_Button.bmp from the training CD to the workspace \Bitmaps directory
Figure 279
The order of our tab pages and controls are in the same order shown in this list. The Global list is created first and then the workspace ones. Therefore, our new tab page should be created last.
405
Create a new view using your new control Save view as Testbutton Compile and test your new control remember the OnClick will not work since it is empty.
Figure 280
Notice that the bitmap property is no longer displayed in the Object Properties dialog and the button size is larger
406
2. A few classes listed in the Configure Class-List have the Image and Page columns empty. Why?
3. In many lessons, we have discussed ways that make developing faster and easier. Can you name the files extensions that are created to speed development?
4. In an earlier lesson, an Invoice_Style template was created in the Global area. What would have to be done to remove this global template?
407
408
Lesson 15
Batch Processing
This lesson covers Business Process Objects (BPOs). They are used whenever batch processing of records is required.
409
410
Send Info_Box (If(bDone,"Process Completed", "Process was canceled") + ; "\n\n Logged " * sChgCount * "Dept Records Changed!") // the "\n\n" will start a new line End_Procedure //AB-StoreEnd End_Object // oUpdateRecords_BP
411
Object Empl_DD is a Empl_DataDictionary Set DDO_Server to Dept_DD Procedure Update Forward Send Update Move "O" to Empl.logged End_Procedure End_Object // Empl_DD
// Create the process. Procedure OnProcess Handle hoDD Boolean bExit Move Empl_DD to hoDD // object id of empl dd Repeat // scan all records.
412
Send Find to hoDD GT Index.4 // Will not have to seed the Index // Empl.logged field should only contain "I" or "O" If (Empl.logged = "O") Break // Jump out of index Send Update_Status ("Updating data" * Empl.Last_name) Send Request_Save to hoDD Set piChanged_Count to (piChanged_Count(Self)+1) // count items Get Cancel_Check to bExit // check for cancel of status panel Until (bExit) If bExit ; Send Log_Status Else Begin Set pbProcess_Completed_State to True End End_Procedure // This message runs the process. // We augment this to print a status dialog when finished Procedure DoProcess Boolean bDone String sChgCount Set piChanged_Count to 0 Set pbProcess_Completed_State to False Forward Send DoProcess Get piChanged_Count to sChgCount // use counter to report records changed Get pbProcess_Completed_State to bDone Send Info_Box (If(bDone,"Process Completed","Process was canceled") + ; "\n\n Logged " * sChgCount * "Employees Out!") // the "\n\n" will start a new line End_Procedure //AB-StoreEnd End_Object // oEveryoneGone_BP "Process was Canceled"
413
Lesson 15 Lab
Description: The two BPOs covered in the lesson will be used in this lab. Both will be attached to buttons that will start the processes. When we created the new Company file and added the new Company_Code field in the Dept file, this created a problem that this field was blank. This lab will correct the problem by inserting a company code into all blank Dept.Company_Code fields. Tasks:
Figure 281
414
Set the BP object name oUpdateRecords_BP Set the Process_Caption to Update_Records Cut and paste the code from Code_Mod.txt to the BP Replacing all existing code and comments (EXCEPT for green line) Save as UpdateCo Compile & Test Verify all records are updated with Database Explorer
Figure 282
//---------------------------------------------------------// Add to the oUpdateRecords_BP Open Dept // use these to keep track of process Property Integer piChanged_Count 0 Property Boolean pbProcess_Completed_State False Set Allow_Cancel_State to True // We will not use a DDO structure. // This is because we are updating orphan records. // The datadictionary would try to do an Attach during the save. // Create the process. Procedure OnProcess Boolean bExit Repeat // scan records. Clear Dept Find GT Dept.Company_Code // Will not have to seed the Index since we are
415
If (Dept.Company_Code <> "") Break // Jump out of index - all blanks have been updated Send Update_Status ("Updating data" * String(Dept.RecNum)) ReRead Dept Move "DAW" to Dept.Company_Code SaveRecord Dept Unlock Set piChanged_Count to (piChanged_Count(Self)+1) // count items changed Get Cancel_Check to bExit // check for cancel of status panel Until (bExit) // if the process was canceled roll back If bExit ; Send Log_Status Else Begin Set pbProcess_Completed_State to True End End_Procedure // This message runs the process. // We augment this to print a status dialog when finished Procedure DoProcess Boolean bDone String sChgCount Set piChanged_Count to 0 Set pbProcess_Completed_State to False Forward Send DoProcess Get piChanged_Count to sChgCount Get pbProcess_Completed_State to bDone Send Info_Box (If(bDone,"Process Completed", "Process was canceled") + ; "\n\n Logged " * sChgCount * "Dept Records Changed!") // the "\n\n" will start a new line End_Procedure "Process was Canceled"
416
Open TC_Out view Add a Button and BP object Set the button Label to Everyone Gone and the object name to oGoneButton Cut and Paste code to the button
Figure 283
// add this code to the Everyone Gone button Send DoProcess of oEveryoneGone_BP Send Beginning_of_Data of oEmpl_Grid
417
Label the BP object oEveryoneGone_BP Set these properties: Process_Caption to Update_Records Cut and Paste code to the BP replacing code already there (EXCEPT for green line) Compile & Test view
Figure 284
If you do not have any employees that are logged in, you may have to compile the entire program and log in some employees first.
// Add to oEveryoneGone_BP // use these to keep track of process Property Integer piChanged_Count 0 Property Boolean pbProcess_Completed_State False Set Allow_Cancel_State to True // we need a complete DDO structure // If deleting records all child DDOs - Deletes propagate down // If saving records all Parent DDO End_Object // Company_DD - Saves propagate up Object Company_DD is a Company_DataDictionary
418
Object Empl_DD is a Empl_DataDictionary Set DDO_Server to Dept_DD Procedure Update Forward Send Update Move "O" to Empl.logged End_Procedure End_Object // Empl_DD
// Create the process. Procedure OnProcess Handle hoDD Boolean bExit Move Empl_DD to hoDD // object id of empl dd Repeat // scan all records. Send Clear to hoDD Send Find to hoDD GT Index.4 // Will not have to seed the Index // Empl.logged field should only contain "I" or "O" If (Empl.logged = "O") Break // Jump out of index Send Update_Status ("Updating data" * Empl.Last_name) Send Request_Save to hoDD Set piChanged_Count to (piChanged_Count(Self)+1) // count items Get Cancel_Check to bExit // check for cancel of status panel Until (bExit) If bExit ; Send Log_Status Else Begin Set pbProcess_Completed_State to True End End_Procedure // This message runs the process. // We augment this to print a status dialog when finished Procedure DoProcess Boolean bDone String sChgCount Set piChanged_Count to 0 Set pbProcess_Completed_State to False Forward Send DoProcess Get piChanged_Count to sChgCount // use counter to report records changed Get pbProcess_Completed_State to bDone "Process was Canceled"
419
Send Info_Box (If(bDone,"Process Completed","Process was canceled") + ; "\n\n Logged " * sChgCount * "Employees Out!") // the "\n\n" will start a new line End_Procedure
420
1. Will the Business Process still work if you remove the DoProcess Procedure?
2. Can you still use procedural code instead of BPO to process records?
421
422
Lesson 16 Reporting
Lesson 16
Reporting
This lesson covers the creating of reports via the report wizards and adding report views to your VDF application. Crystal is a powerful report writer that allows you to quickly create .RPT files that can be called from a VDF program. You will need Crystal Reports installed to complete some of the features covered in this lesson.
423
Lesson 16 Reporting
WinReport (WinPrint) WinReport is a subclass of the BasicReport so there are many similarities to their structure. WinPrint is capable of font changes and record selection. The WinPrint Report Wizard will use this class when generating code.
CrystalReport Class CrystalReport is a class that will use a .RPT file that was created using the Crystal Report Writer software. This report writer will generate great looking reports in minimal time. Crystal is full of features such as adding bitmaps, changing fonts and color, record selection and sort order. The Crystal Report Wizard will use this class when generating code. The Crystal product can be purchased separately. Combined with the DataFlex Connectivity Kit for Crystal Reports, it can access DataFlex databases. After installation, you will be able to produce the .RPT files that the CrystalReport Class will run. Your customers will not be required to purchase the Crystal product. The .RPT files will be launched from your VDF application.
424
Lesson 16 Lab
Description: Creating a WinPrint and Crystal report using the report wizards.
Tasks:
Figure 285
425
Dept_Budget [ Next
Figure 286
[ Next
Figure 287
426
[ DEPT [ Next
Figure 288
[ Next
Figure 289
427
Figure 290
428
[ Dept.Company_Code [ Next
Figure 291
[ Index 3 [ Next
Figure 292
429
[ Finish Button
Figure 293
Figure 294
Leaving the selection criteria blank will print all records. You may wish to add more records so your report has more to print.
Figure 295
Open the report component and look over the generated code. If you look at the above Screen shot of the report You may notice a small problem with the header of Company_Code. It is missing the last e To correct this lookup the command DFWritePos and enlarge the MaxLength to 2.50
Figure 296
431
Figure 297
[ Next button
Figure 298
432
[ browse () button From the workspace \data directory select the Department.RPT file [ Open [ Next button
Figure 299
Figure 300
433
[ Next button
Figure 301
A user selection is not always needed. This screen can be left blank.
Figure 302
434
[ Next button
Figure 303
Indexed fields have a red mark on the icon. This report is grouped by Dept. Therefore, it is limited to what fields can be used to sort. The best way to determine this is to see if Crystal would allow the field as the Sort order. This is true on many of the options of the wizard.
Figure 304
435
[ Finish button
Figure 305
Note: Crystal does not have to be installed on the end users machine in order to run the Crystal reports (just needed .dll files). It is necessary to have Crystal installed in order to create the reports.
436
Figure 306
437
Open the DeptEmpl.vw Add the Print button from the Custom tab page Set the object name to oPrintButton
Figure 307
438
Figure 308
//------------------------------------------------------------------// Add to the top of the DeptEmpl object // This package will be needed to run the Crystal report //------------------------------------------------------------------Use CrystalReport.pkg
// Add to the bottom of the DeptEmpl object // Create Crystal report to print the current header record. // Object's access method is: Send Print_It iHeaNumber Object Single_Record_Report is a CrystalReport Property Integer piHeaderNumber 0 Property String psHeaderNumber // need two properties (ASCII & integer) Procedure onInitializeReport
439
// set the Report titles and selection formula -- toggle the string/integer properties If ((psType_Header_Key(Self)) = "I") Begin Set ReportTitle to ("Print " * (psFileField(Self)) * (piHeaderNumber(Self))) Set SelectionFormula to ("{" + (psFileField(Self)) + "} = " + (piHeaderNumber(Self))) End Else Begin Set ReportTitle to ("Print " * (psFileField(Self)) * (psHeaderNumber(Self))) Set SelectionFormula To ("{" + (psFileField(Self)) + "} = '" + (psHeaderNumber(Self)) + "'") End End_Procedure // pass Header to print Procedure Print_It string sNum Integer iNum If ((psType_Header_Key(Self)) = "I") Begin Move sNum to iNum Set piHeaderNumber to iNum End Else Set psHeaderNumber to sNum Send Run_Report End_Procedure End_Object // print the current order. This message will be sent // by the print button Procedure PrintCurrentRecord Handle hDD Integer iNum iFieldNum String sNum sRepFileName sFileField Get Server to hDD // this will be the header_file DD If (Current_Record(hDD)) Begin // only do this if record exists Move ((psHeaderName(Self)) + ".Rpt") to sRepFileName Set Report_Name of Single_Record_Report to sRepFileName Get psFileField to sFileField Get piKeyFieldnum to iFieldNum // There is a limit here since we expect the psType_Header_Key to be an "I" or "S" (Integer/ String) If ((psType_Header_key(Self)) = "I") begin Get Field_Current_Value of hDD iFieldNum to iNum Move iNum to sNum Send Print_It to Single_Record_Report sNum End Else Begin
440
441
This step will shadow the Print button so it will not be available if there is no record to print.
From the Code_Mod.txt file, Highlight & Cut the appropriate code (shown below) / the First Object to bring up the editor Paste code in the bottom area
//------------------------------------------------------------------// Add to the bottom area of the Dept.Dept_Code dbForm // We want to disable the print button if there is no current record. // The DD notifies all DEOs of any record change. // We can augment any DEO's refresh message to see if a current // record exists and set the Enabled_State of print button accordingly. //------------------------------------------------------------------Procedure Refresh Integer iMode Integer iRec Forward Send Refresh iMode // if record exists, enable the print button. Get Current_Record of (Server(Self)) to iRec Set Enabled_State of oPrintButton to (iRec>0) //(iRec>0)evaluates to True/False End_Procedure
442
This step will add the OnClick procedure to the print button.
From the Code_Mod.txt file, Highlight & Cut the appropriate code (shown below) / the button object to bring up the editor Paste code in the bottom area. Paste over the existing procedure Compile and Test (Remember the button will be shadowed until a record is found)
Fi
310
// Added to the bottom of the oPrintButton Procedure OnClick Delegate Send PrintCurrentRecord // defined in view object End_Procedure
443
1. Can you print the selection range in the header of a Crystal report?
Workshop Project: If time permits and you need a challenge - add the code that would create a Wk_Sum record whenever a TimeCard record is saved/deleted.
444
Appendix A
Did you Discover Answers
445
Answer: Appendix C. New DataFlex Users Procedural Programmers Appendix C DataFlex Core Information Appendix C OOP Core Information
DOS Object Oriented Programmers Appendix C OOP Core Information Prior VDF Users Appendix C Prior VDF Users
Sample Name A Local Boolean Variable A Local Integer Variable A Global Integer Variable A Global String Variable A Class An Object An Integer Property A String Property A Variant Property A Constant A Local Integer Variable (used to hold an object ID) bVar iVar giVar gsVar cMyEdit oMyEdit piMyProperty psMyProperty pvMyProperty C_MyCounter hoObjID
446
Answer No. One of the rules for relationships is that the parent file must be uniquely indexed. Since there are no unique indexes this file cannot be a parent file, with a child file relating to it.
2. The lock in the upper right corner must be green to make changes to the first three tab pages. When opening a file it always comes up in red - Is there a way to default it to green?
Answer: Yes, within DDB the File menu, Configure option and Database Builder tab page there is a checkbox for Open tables in normal mode. Normal mode is when the lock is red (non-exclusive rights to the database). Uncheck the option for Exclusive (exclusive lock on the database) showing a green light for database changes.
3. When adding a new field in Database Builder, are the Add and Insert buttons required to add a new field?
Answer: No, you can simply type directly into a blank field row. The Insert button will allow you to insert a field between existing fields and the Add button will jump you to bottom of the grid on the first blank row.
4. When loading a complete file structure (with many relationships) into a new Filelist.CFG, is it important to load the .DEF files in any special file number position? Why?
Data Access Corporation 447
Answer: Yes, This is because of file relationships if the child is pointing to file 4 and you change the parents position in filelist to 9 the file relationship will not be loaded correctly. Therefore you will have to load the files in the same file number position. It is also recommended to add parent files before child files so the parent file number is created before the child attempts to relate to the file number.
5. Write down 3 different ways to open a database file in DDB. (open, not create) Answer: From the menu, select File|Open From the combo box Open As
6. What is End User Mode and how do you set up Database Builder in End User Mode? (hint look this up in the on-line help under the index tab)
Answer: In this mode, Database Builder cannot modify any file structures, indexes, or Data Dictionarys. You can only print file status reports and access the file-maintenance options. End User Mode allows your application users to access functions such as re-indexing, repair data, and other maintenance functions. Users will be locked out of all other functions. To place Database Builder in End User Mode, set the windows registry setting of VDF Default tag dbAdminMode variable as follows: dbAdminMode = OFF
448
2. What is Epoch and what has it to do with entering dates in a VDF application? Answer: EPOCH_VALUE sets the two-digit year value equal or above which dates are considered to be in the 1900s and below which dates are considered to be in the 2000s. The Set_Date_Attribute and Epoch_Value determines if it will add 1900 or 2000 to a year that was entered as two digit. This setting can be changed easily in the code created in the Studio. Open a program, and look at the code in the Program Code area. The default setting can be changed from the Tools | Configure Environment menu in the General tab page.
3. Predict and check the results of entering the following dates, with Epoch turned on and set to 30? 01/01/00 06/20/52 12/25/30
Answer: They are automatically converted based on the epoch setting selected. 01/01/2000 06/20/1952 12/25/1930
449
4. What would happen to the tab dialogs if the dialog box was not big enough to hold all three tabs? (add more tabs or shorten the tab dialog box to find out)
Answer: The tab pages will wrap. There are properties (like Tabwidth_Mode and Mutliline_State) that can alter tabs.
5. What would happen if you shortened the length of the last name window so that the entire last name entered wouldnt fit in the window?
Answer: It will scroll to fit as many characters as the length of the data field.
6. Run the program, and type in a last name of WWWWWWWWWW (type capital Ws until you reach the limit (which is the length of the field). Notice that it had to scroll to the right. Clear with the F5 key, and type in a last name of iiiiiiiiii (all small letters is to the limit). How do you determine what the size of a control should be?
Answer: Window applications can alter fonts styles which makes this difficult. Plus the fact that you do not know that will be entered (all W or i letters). The Studio will create a size by default that is a very good estimate for the correct size of a control based on the current typeface. If you know what the value of a control and need to alter the size at runtime, use the Text_Extent property. Below is a sample of this.
Procedure Activating Forward Send Activating Send AutoSize "WWWWWWWWWWWWWWWWWWWW" End_Procedure Procedure Autosize String Val Integer iExt iHt iWd Get Text_Extent Val To iExt Move (hi(ext)) to iHt Move (low(ext)) to iWd
450
7. When using the Object-Order Definition tool, is it important where Textbox objects are listed? Answer: No, they are non-focusable controls so they have no affect in the view navigation.
8. Run our program, and open up the Employee Entry View. Find a Record, then place the cursor on the parent window (Dept) and press Shift+F2 to delete. Wait! What is going to be deleted? The Department or the Employee? Why? Answer: Remember that the Accelerator keys send messages (in this case Request_Delete). The message will travel by delegation to the dbView, and then (because the dbView has it's server set to the Main_DD) the Request_Delete message travels to the Empl_DD. Then, since deletes travel downwards (in the DDO tree), the Employee record is deleted - Not the Dept. You cannot delete a parent record in most VDF programs unless the programmer explicitly codes it.
451
Answer: Normal behavior for the On_Key kAdd_Mode (which is what Shift+F10 sends) is to insert a blank line in the grid where the cursor is located. Our view made the Add-Mode key send the Append_A_Row that jumps us to the end of the table, and then down one row (Append_A_Row procedure).
2. In the DataFlex language, how do you continue a command line to the next line? Answer: Using the semicolon ; will allow you to continue a command to the next line.
3. Within the DeptEmpl View, go to the grid and enter some test data, but do not save with the F2 key. . . click on a window in the header . . . can you exit the line item without a save occurring? What if you use the down arrow or up arrow? Does the save occur?
Answer: Earlier, we set the Child_Table_State of the dbGrid to true. This enforces a save operation before navigation outside the current line is allowed.
4. When the Studio generates the code for an Object the Green Line in the Code Editor will be replace with what?
452
Answer: With all the Objects properties set in the Object Properties Tool for this object and any nested objects contained by this object.
5. When you find a Department record (in the header section), only the employees for that Department are found and displayed. How does the program know to show only related records in the dbGrid?
Answer: With the Studio running and the DeptEmpl View open, click on the Database Selector icon, and choose DDO Tree. Click the + sign next to EMPL_DD and take note of the settings . . . The DDO_Server means Empl is related to Dept but it is the Constrain file that will only allow related records to be displayed (a filter).
6. Create a new view with two dbForm controls, one showing the Empl.Code and the other one showing the Empl.Last_Name. Make the dbForm for the Empl.Code control using the Database Selector. Make the dbForm for the Empl.Last_Name using the Controls Palette. When you compile and run your new view did both of your controls show data when you find records? What extra step do you have to do with the Controls Palette when creating data-aware controls? Answer: If you are using the Database Selector the connection to the File.Field is already made. If you use the Controls Palette to make Data-aware controls you will have to use the Object Properties dialog (Database tab) and connect to the file.field.
453
1. Where in the Studio and Database Builder will a right-mouse-click call up a popup menu? Answer: The Right Click popup menu is available from almost every entry control in each dialog in Database Builder & the Studio. These menus are helpful for many things including cutting and pasting.
2. What are the advantages of validation tables over creating a parent related file? Answer: Fewer database tables are needed (with the static option there are no database tables used). Database Builder makes the creation and updating of validation tables very easy.
3. What are the advantages of a parent related file over a validation table. Answer: Advantage: Accessing the data for reports can sometimes be easier. Ex:In Crystal Reports, it would be easier to access the data when it is in a related parent file. Disadvantage: A related file would require its own separate file. Data in Validation Tables can be combined into a single file.
454
1. When using the magic wand button in the Structures tab page of Database Builder will it remove unneeded files from the required Child/Parent list? Answer: No! It will only add to the list it will not remove extra files that are already listed that is why it is important to remove all files before using the button. The Magic Wand Button will add to the list any Required Child and Required Parent files that match the file relationships that are not already in the list.
2. What is the difference between the Validation Error No. & Text on the Field Setting | Validation/Lookup Tab and Validation Error No. & Text on the Options tab? Answer: The setting on the Field Setting | Validation/Lookup Tab is only for one field. The setting on the Options Tab creates a Field_Error property where ifield is set to -1, which will then apply this error setting to every field in the file, applying this Error and Text to all fields that are not individually set.
3. In Database Builder under the METHODS tab if you select a method from the Unaugmented list what happens to the Unaugmented and Implemented lists? Answer: The selected method is removed from the Unaugmented list and added to the Impliemented list. A timer event fires and updates both lists.
455
456
Answer: CD means Create/Destroy. Selection lists are created only when they are poped up and destroyed upon exiting. This is done to speed in application load time. In a program, which contains many selection lists, this lets the program quickly load into memory when it starts. Note: Views are not CD-type objects. Views use a Deferred_View command. This will create the view when first activated, but does not destroy them upon exiting.
2. If you look in the properties of the selection list, the Ordering property (which index to use) is set to zero. Why is that?
Answer: Selection lists automatically re-sort themselves based on the field (column) that has the focus.
3. After the constraint in the Employee View is added, can you save an employee that has a termination date greater than zero? Answer: Yes, you can save an employee with a termination date but after it is saved you will not be able to bring the record up in the view again. Constrains only affect the finding and displaying of records.
457
4. How could you make the Selection List use the same DataDictionary constraints as the invoking view? (without copying or moving the OnConstrain code from one to the other) Answer: The Auto_Server_State property is exposed in the Studio from the Object Properties dialog. If you set this property to True in your Lookup it will use the DataDictionary of the invoking view and be identically constrained.
458
Answer: Yes
2. If I cancel the Request_Clear procedure in a container object that contains many dbForm objects will it affect the Request_Save? Answer: Yes, the Request_Save cascades many messages one of them is the Request_Clear message so now when you save it will not clear.
3. What would happened if Forward Send Creating was listed before the Move command in TimeCard DD objects Creating procedure we just added in the lab? Here is the code:
Procedure Creating // Since the TimeCard.In_or_Out is only one character long // the psInOut property value will be truncated Move (Uppercase(psInOut(Self))) to TimeCard.In_or_Out Forward Send Creating End_Procedure
Answer: The Empl.Logged field would be blank. Why . . . If you have a Creating procedure in the DDO of the view and a Creating procedure in the .DD file, Both will be executed if the DDO does a Forward send Creating. Looking at the DataDictionary Creating procedure it Move TimeCard.In_or_Out to Empl.Logged this means if the Forward Send Creating is done first there would be nothing in the TimeCard.In_or_Out field to move to the Empl.Logged field.
459
4. Look in the WinHelp to find the names of the other Accelerator-Keys. Answer: Select the Search key and type Accelerator then select Accelerator KeyMessage and Assignments of the Accelerator-Key-Message-Names.
5. Name as many ways as you can to make a procedure execute. Answer: Commands: Send Forward Send Delegate Send Broadcast Send On_Key ( and predefined Accelerator keys) Classes: (many classes can send messages) Buttons Radios List Events: Timers (will cover in the next lesson) Keyboard (as we type) Mouse
460
6. Create a new view with a grid displaying the Empl.Code; Empl.Last_Name and Empl.Term_Date fields. Use the RadioGroup Class to set up a dynamic constraint to show: All Employees Terminated Employees Active Employees
// This would be added to the Empl_DD object Property integer piConstrainVal 0 Procedure OnConstrain Integer iConVal Get piConstrainVal to iConVal If (iConVal = 1) Constrain Empl.Term_Date GT 0 If (iConVal = 2) Constrain Empl.Term_Date EQ 0 End_Procedure
// This would be added to the Empl View built with the Studio. Object RadioGroup1 is a RadioGroup Set Label to "Change Constraints:" Set Size to 39 56 Set Location to 3 7 Set Current_Radio to 0 Object Radio1 is a Radio Set Label to "All Empl Set Size to 10 39 Set Location to 11 5 End_Object // Radio1
Object Radio2 is a Radio Set Label to "Terminated Employees" Set Size to 10 37 Set Location to 24 5 End_Object // Radio2
461
Procedure Notify_Select_State Integer iToItem integer iFromItem Forward Send Notify_Select_State iToItem iFromItem Set piConstrainVal of Empl_DD to iToItem Send Rebuild_Constraints of Empl_DD Send Beginning_of_Data to oEmpl_Grid End_Procedure End_Object // RadioGroup1
462
2. What information can you get by clicking on "Help/About..." of a running VDF application? Answer: You can see how much memory is being used by the current applications. Note: You can customize your own about package: see DFAbout.Pkg
463
2. What does the S compiler option do? Answer: Compiling your code with the s symbol option will help in debugging. This option will create a larger compiled file because it creates a symbol table in the .EXE file. Now instead of a runtime error message that just has the message number it will give the message name.
3. If your users launch 3-4 copies of this program at the same time, how much memory will it use up? Answer: About 2% of system recourses for each copy: not very much! (VDF uses very few system resources).
464
2. How can you create an icon on the desktop to automatically run this application? Answer: Open the Window Explorer and Drag the compiled .EXE program to the desktop This will create a shortcut to the program.
3. After completing this lab, will you have to copy the CorpLogo.BMP when deploying your application? What would you suggest be done? Answer: Yes you would have to copy the CorpLogo.BMP file when deploying the application because we did not list the new file in the CorporationX.cfg. To correct this we would add the file via the Program |Properites dialog and then recompile.
465
2. Can you write a business rule so that a company must have a "NAME" (must not be blank?) Answer: Augment Validate_Save in the Company Data Dictionary to make sure the field is not blank or simply set the field option to REQ.
3. Can you write a business rule so that a company record can never be deleted? Answer: If you always use DataDictionarys, you can set the No_Delete_State property to true or augment Validate_Delete of the Company Data Dictionary so that it always returns a value of 1(so the delete will fail). It could also give a message to the customer that tells them what is happening. This will not stop manual deletes that do not use DataDictionarys.
466
4. In the Dept Backout and Update, we do not explicitly say "Save Company". When you delete or save a Dept record does the Company total balance get updated and saved? Why?
Answer: Yes, it will be saved. In the view, the "tree" of connected Data Dictionarys makes this happen. The SAVE message propagates up from the main-dd, saving all parent files. The Delete message will propagate downward in the DataDictionary structure, deleting all child records, and then deleting itSelf (as long as the Cascade_Delete_State is true). A SAVE is then sent upwards, saving all the parent files which will save all updates (running totals) to the parent records.
467
2. A few classes listed in the Maintain Class-List have the Image and Page columns empty. Why? Answer: These are classes that the Studio will not allow you to drag and drop (such as a DataDictionary) from the Controls Palette tool. Therefore they will not need an image or be listed under any of the Palette Pages.
3. In many lessons, we have discussed ways that make developing faster and easier. Can you name the files extensions that are created to speed development? Answer: TPV - Template Views TPL Template Lookups TPD Template Dialogs TPR Template Reports DFS - DatFlex SubComponents DFO - DataFlex Object Preferences DFC - DataFlex Classes for the Studio PKG - Package Files storing Classes and support code A full description of these files is listed on the next few pages. They can be stored Global or Locally: (local) workspace name\IdeSrc\filename (global) VDF 9.1\\usr\global\IdeSrc\filename
468
Files that speed Studio development: Template Views can be reused to speed development TPV - Template Views TPL Template Lookups TPD Template Dialogs TPR Template Reports Loaded by: File | New Component Saved by: File | Save as Template DFS Files: DatFlex SubComponents Loaded by: Component | Insert object SubComponent Saved by: Component | Save object SubComponent
More Information/Sample // Entire template view //Lab #4 did this creating the Hdr_Grid.TPV
//AB/ SUBCOMPONENT Object Setup is a Button Set Label to "Printer Setup" Set Location to 63 122 //AB-StoreStart Procedure OnClick Integer iReportObj Get Report_Object_ID To iReportObj Send DFPrintSetup To iReportObj End_Procedure //AB-StoreEnd End_Object // Setup //AB/ OBJECTDEF Object oButton is a Button //AB-StoreStart Procedure OnClick End_Procedure // OnClick //AB-StoreEnd End_Object
DFO Files: DataFlex Object Preferences Used to add extra code into the Studio created object. The sample to the right will add the Procedure OnClick to the object so it will not have to be entered.
469
DFC Files: DataFlex Classes To add your subclass to the Controls Palette takes 3 steps 1. Create your subclass package .pkg 2. Create the .DFC file 3. Copy the required 24X24 bitmap used by the Controls Palette to the \bitmap area. Add the subclass to the Maintain Class-List under the Tools pull-down. PKG Files: Package Files storing Classes
//AB/ CLASSDEF Class Button IS A AbstractControl Button ; ABMetaButtonMixin ; DefineABMetaButtonMixin // inherit is removed on purpose Property String Label Property NO_EXECUTE Boolean ; Default_State False Property String Bitmap Property Complex Size 14 50 Property Complex Location 0 0 Property String Status_Help End_Class // saved in a MyButton.pkg file Class cMyButton is a Button Procedure Construct_Object Set Size to 30 30 End_Procedure End_Class
4. In an earlier lesson, an Invoice_Style template was created in the Global area. What would have to be done to remove this global template? Answer: File | New Component select the template and press delete button. Or you can go to the \VDF 9.1\User\Global\IDESrc directory and directly delete the Invoice_Style.tpv file
470
Answer: Yes, DoProcess simply supplies the progress line, the main process is done in the OnProcess event.
2. Can you still use procedural Code instead of BPO to process records?
Answer: Yes, you can still do any of the procedural loops or For_All methods BUT they do not use DataDictionarys so your business rules are not being followed. This is why BPOs are the suggested method. In our lab was an example of when DataDictionarys could not be used because we were correcting the relationship field between two files after a newly created relationship was created.
471
Answer: Yes you can. In Crystal Reports, create a Parameter. A parameter will prompt the user for information used in running the report. For example, you can create a date parameter that asks the user for a date at runtime, such as invoice date > 1/1/2002 for all this years sales. When you create the selection formula within Crystal Reports, you can choose invoice date > (?parameter name). The parameter name will appear on the dropdown browse list with a ? in front of the name. Then create a text field in the report header and insert that parameter in the test field. This will print whatever selection entered as the parameter. If you don't want the user to enter a parameter, just set the default amount to be whatever you want it to be when you set the parameter up. If you need more info, check the Crystal Reports manual.
472
Appendix B
Problems & Solutions
473
Popup Messages/Questions
Problem: What is the quickest way to ask a yes/no question?
Solution: If you are simply asking a Yes/No question use the Confirm function found in dfconfirm.pkg:
Figure 311
Other popup boxes are Info_Box and Stop_Box (both in the Msgbox.pkg).
Figure 312
Figure 313
Figure 314
Send Info_Box "You do not have rights to this area!" Send Stop_Box It is strongly suggested you \n create a backup before continuing Get YesNoCancel_Box Do you wish to save the current setup profile?" to iRetVal
474
Syntax:
Workarounds: 1. Move the On_Key command to the bottom of the view so the object is already constructed.
475
1. Find the activate access method for the desired view (looking at the mainprogram.SRC file will show how it activates the views). For example, the access method for a Customer_Entry view would most likely be Activate_Customer_Entry. 2. Add the following line to the end of your program right before the Start_UI command. You may add this code within the Studio by editing the bottom-code area of your program.
This assumes that your main program has been created by the Studio and the main outer panel objects name is Main and its child client-area objects name is Client_Area. You can auto-activate as many views as you wish using this method. The last view activated will be the view that takes the focus.
476
ToolTip
Problem Can I set a ToolTip_Value on my buttons to explain when to use them?
Solution: At the present time you would have to create your own classes to do this. - but future versions of VDF may support this.
477
Solution: This sample will allow you to set the initial folder to the first listed directory that is listed in the bitmap path. If the directory you wish is not the first one then PathAtIndex function of the cWorkspace object can help filter out the N-th path.
Procedure Activating Integer hoWorkspace String sBitmapPath Get phoWorkspace of ghoApplication to hoWorkspace Get psBitmapPath of hoWorkspace To sBitmapPath Get PathAtIndex of hoWorkspace sBitmapPath 1 To sBitmapPath Set Initial_Folder To sBitmapPath Forward Send Activating End_Procedure // Activating // Take the first path entry
478
Solution: This sample ensures that the bitmap filename entered is limited to 15 characters.
Function Select_Bitmap Returns String String sBitmapFileName Integer iFieldLength iFileNameLength iField Forward Get Select_Bitmap To sBitmapFileName Get_Fieldnumber Empl.Picture_id To iField Get_Attribute DF_FIELD_LENGTH Of Empl.File_Number iField To iFieldLength Move (Length(sBitmapFileName)) To iFileNameLength If (iFieldLength < iFileNameLength) Begin Error 130 ("Filename '" + sBitmapFileName + "' too long (size=" + ; String(iFileNameLength) + ") for picture field (max=" + ; String(iFieldLength) + ; ")\nFilename and therefore selection will not be used!") Move "" To sBitmapFileName End Function_Return sBitmapFileName End_Function // Select_Bitmap
479
Procedure Set
Problem Why do some procedures act like a property?
Solution: This is because they have been created as a procedure set instead of simply a procedure. Procedure set is a short cut it builds a property and procedure in one. So when you set the property it also calls a procedure at the same time. Here is an example:
Procedure Set Item_Options_DisplayOnly integer item# integer state // two things were passed the item# which in our case T_Date## =1 // and state which is Crnt (true if non_zero & false if 0) Set Item_Option Item Item# to NoPut state Set Item_Option Item Item# to NoEnter state End_Procedure // if transaction header exist, disallow entry in date window Procedure Refresh integer iMode Integer iSrvr iCrnt Get Server to iSrvr // get the data_set // get record in data_set | | | -------------------------------------------| Get Current_Record of iSrvr to iCrnt // DispalyOnly = Noput & NoEnter // Date## has already been defined by entry_name_item Set Item_Options_DisplayOnly T_Date## iCrnt Forward Send Refresh iMode // Dont leave us sitting on a DisplayOnly Window If ((iCrnt and (Current_Item (Self) = T_Date##) Send Next End_Procedure // do normal refresh ----------| | | | | | | | | | | |
When I was learning OOP and using the old OOP Reference manual I was always looking at the beginning of this book at the property chart and then finding what I was looking for was under the procedure chart as a procedure set. Take a look at these charts in the old manual, you will find lots of procedure sets! Or look in the on-line help.
480
Solution: This sample will create a file called environ.txt and put the value data of .doc found in Windows Registry. [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Extensi ons] in a text file called environ.txt. This is normally not needed! Windows registry setting should really be altered within an interface program like the one found from within
use windows // In previous revisions of DataFlex (3.05x), the command Get_Foreign_Profile_String returned values from .INI files. // Visual DataFlex uses the same command but now retrieves values from the windows registry. // The Get_Foreign_ProfileString will copy values from the registry (regedit.exe). This is similar to Export // Registry File from the registry pull down. It will provide all parameter values. Care must be taken when // parsing the string into acceptable arguments. Incorrect values that are NOT found will return a null string // not an error. This command will NOT change any registry settings. To change settings use the Set_Foreign_Profile_String command. // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Extensions] string sValData sRegPath sKey sValueName // Must set the registry root to first two branches. set_registry_root to HKEY_LOCAL_MACHINE 'Software' // Include as arguments : path to registry key, key, value name to return value data move 'Microsoft\Windows\CurrentVersion' to sRegPath move 'Extensions' move '.doc' to sValueName get_foreign_profile_string sRegPath sKey sValueName to sValData direct_output 'environ.txt' writeln '.doc value is ' sValData close_output to sKey
481
Deployment
Problem: How do I deploy my application?
Solution: There is a white paper that explains the deploying of VDF applications. You can download it from our web site at http://www.dataaccess.com/.
482
Saving Resources:
Problem: I have a fairly large application and to make different views look a little different I started adding lots of fonts my application is now running much slower.
Solution: Changing colors does not use up your resources, so do this freely. Changing fonts; font styles (bold/italics) or sizes uses up resources FAST, so do this very sparingly.
483
484
Utilities | Configure Utilities [ Add button If you have an external program add it to the right side of the dialog otherwise press cancel
Figure 315
When entering the command line use the browse button to find the program to run. When typing in the command line use quotes around the entered data so directory names containing spaces will not be confused with command line partameters.
485
Maintain Class-Lists
The last item on the tool pull-down allows us to add or edit subclasses (tools) that the Studio will use.
The order of the tab pages in the Controls Palette can be altered by changing the order of the classes in the Maintain Class List tool.
Figure 316
The Global tab page lists classes the Studio will use in all workspaces. The Workspace tab page lists classes used only in the current workspace. Each time you change workspaces the Studio rereads this file.
If the Page column has an entry the Studio will add the class in the Controls Palette tool. The order of the Controls Palette tab pages are determined by the order in the list. If you add a new page name a tab page will be created with that name. In this example the tab pages would be listed Base; Data; Base Containers; and Data Containers. The controls listed under the tab
Figure 317
486
Field_Default_Value Property
This property is used to set defaults. Field_Entry_msg procedures (described later) and Field_Defaults procedures (described below) are the most common places the Field_Default_Value property is used. This example is from the OrderHea DataDictionary of the Order Sample.
Figure 318
Note (prior OOP programmers) This procedure is similar to the Entry_Defaults procedure in the DEOs.
The Field_Defaults procedure sets the field value without setting the DSOs Changed_State. This will allow the default to show in grids without creating unwanted records in the database upon entering and exiting a blank row.
Class OrderHea_DataDictionary is a DataDictionary Procedure Field_Defaults Forward Send Field_Defaults Date dDate SysDate dDate Set Field_Default_Value Field Orderhea.Date to dDate Set Field_Default_Value Field Orderhea.Terms to CASH End_Procedure //Field_Defaults
487
Appendix C
Core Information
489
Accelerator Keys
Function Key 1 2 3 4 5 6 7 8 9 0 R F Z X l r t b s B h e 490 Function Key S+ Function Key Help Save Record Exit Function Prompt Clear Panel Switch to Next Area Find Previous Find Next Find Switch to Action Bar Accept Next item Insert/Overtype Toggle Delete Character Cursor Left Cursor Right Cursor Up Cursor Down Selection Toggle Destructive Backspace Beginning of Line End of Line Erase to End of Line Beginning of Data End of Data Data Access Corporation Non-WP Bksp Skip Word Left Skip Word Right Beginning of Panel End of Panel Previous item Print Screen Refresh Screen Switch to Prev.Area Superfind Previous Superfind Next Superfind Add Mode on/off * Clear and Return Zoom Clear all Panels Switch Prev. Panel * Delete Record Trace Mode * C+ Function Key A+ Function Key User Key 1 User Key 2 Trace on/off * Exit Application Calculate Switch Next Panel *
Discovering Visual DataFlex Function Key u d E / + Copy Function Key S+ Function Key Scroll Page Up Scroll Page Down Cancel Mark
Appendix C Core Information C+ Function Key Scroll Page Left Scroll Page Right A+ Function Key
Paste Cut
491
Hot Key F12 F11 Ctrl + 1 Ctrl + 2 Ctrl + 3 Ctrl + 4 Ctrl + 5 Ctrl + 6 Ctrl + 7 Ctrl + L Ctrl + O Ctrl + N Ctrl + P Ctrl + S F1 Ctrl + Z Ctrl + X Ctrl + C Ctrl + V Del F7 F8 F9 Ctrl + F7
Data Access Corporation
Run EDITOR Code-List Code-Expand Next Insertion Point Match parenthesis Goto line Next ToDo item Uppercase Lowercase Toggle comments Indent Outdent Toggle Whitespace Delete Line Select Line Find Find again Replace Context Help Toggle Bookmark Previous Bookmark Next Bookmark Properties Record Macro Redo Set Repeat Count Toggle Overtype Line Open Above
Data Access Corporation
Ctrl + F8 Ctrl + Space Ctrl + J Ctrl + I Ctrl + ] Ctrl + G Ctrl + T Ctrl + Shift + U Ctrl + U Ctrl + / Tab Shift + Tab Ctrl + Alt + T Ctrl + Y Ctrl + Alt + F8 Ctrl + F F3 Ctrl + Alt + F3 Ctrl + F1 Ctrl + F2 Shift + F2 F2 Alt + Enter Control + Shift + R Control + A Control + R Insert Control + Shift + N
493
Sentence Cut Sentence Left Sentence Right Window Scroll Down Window Scroll Left Window Scroll Right Window Scroll Up Word Delete-To-End Word Delete-To-Start Word Left Word Left-Extend Word Right Word Right-Extend Document End Document End-Extend Document Start Document Start-Extend Home Extend Line End-Extend
Control + Alt + K Control + Alt + Left Control + Alt + Right Control + Up Control + PageUp Control + PageDown Control + Down Control + Delete Control + Backspace Control + Left Control + Shift + Left Control + Right Control + Shift + Right Control + End Control + Shift + End Control + Home Control + Shift + Home Shift + Home Shift + End
494
Some DataFlex terms are confusing to developers use to other languages Standard Term Table Column Row Index Database DataFlex Term Data File Field Record Index (K file) Visual DataFlex has no single database file type. DataFlex tables each are in their own individual file. For example, Access has a .MDB file that contains multiple tables. Embedded (DataFlex) data files each have a separate set of files (.DAT, .HDR, .VLD, .K*, etc).
495
The Main Utilities Studio The Studio is the hub of application development. It contains everything from powerful RAD wizards to links to all the other major utilities Database Builder Database Builder enables you to create, modify, and delete the database files used in a Visual DataFlex application. It supports creation and design of Data Dictionarys (.DD files), including declaration and configuration of the data-dictionary subclass required for every database file. In addition, it enables you to repair indexes and data, and to restructure files (including files from earlier revisions of DataFlex). Database Explorer Database Explorer allows you to browse through the list of data files of any environment or workspace and open the files to inspect their data. Many database features are incorporated in this utility such as the Database Export Wizard, which allows you to export your data to different formats. Compiler Once a program source-code file is created it must compile it into another file for the Visual DataFlex runtime to execute. The compiler does this operation.
496
File Relationships File relationships connect your files together. They stop data redundancy in your database table and allow your files to work harmoniously together. The whole key to solid code in Visual DataFlex is solid relational database tables. Your database structure must be correct to accomplish your needs.
The Parent-Child relationship is established within the Database Builder utility. If you have a parent file, OrderHea file and a child file, OrderDtl the OrderDtl file would relate to the parent OrderHea file. The related fields in both files must be the same type and length. In this case the related field is Order_Number.
497
The general rule to determine which file is the child and which is the parent is to determine which file will have many records to a single record in the other file. In this example there can be many child OrderDtl records for each parent OrderHea record. The exception to this logic is the one to one relationships. In these cases it make little difference which way the relationship points. An example of a One-to-One relationship is an employee file and a password file, you may need the password in a separate file for security but there should only be one password for each employee record
File Relationships Rules: 1. N to one relationship 2. Parent related field must be uniquely indexed 3. Related fields must be the same type and length
TimeCard
Wk_Summary
498
Orderdtl
St_Cl
The Orderdtl child file contains a related field for both Orderhea and Inventory and also needed data about the detail line item. However, the St_Cl file contains only two fields one relating to the Student file and the other field relating to the Classes file. The single purpose of this file is to link the two parent files together to solve the many to many relationship that is not supported directly. To find all the students in Biology 101 you simply find all the Class code Bio101 in the St_Cl file. To find all the classes that student 1013 is registered in, you again go to the St_Cl file and find all the records with student ID 1013.
499
Data Integrity Whenever data is stored, business rules are generated in order to ensure the data being saved is correct. The old saying Garbage IN = Garbage OUT results when the business rules are not followed.
Business rules are validations preformed prior to allowing any operation to the database table (such as saves or deletes). They can be something as simple as making sure the State Abbreviated field is always capitalized or as complex as making sure that an order has sufficient inventory before a save is allowed.
The Database Builder utility creates a DataDictionary class for each database table. This file has the extension of DD. A Database table called Customer will have a DataDictionary Class created in a file called Customer.DD that holds the business rules for the database. This means all business rules are centralized in one place. This makes updates and maintaining the business rules easier.
The last four tab pages of Database Builder generate the code to create this DataDictionary file from you.
500
What Happens During a Save to Keep the Related Fields the Same? When DataDictionarys perform a save operation, an Attach command is also performed. This moves the parent-related field to the child-related field. This is the reason that the parent related field, not the child related field should be added to entry views (wizards will replace any Child.Related_Field with the Parent.Related_Field automatically). In our example of the order program only the OrderHea.Order_Number field is present on screen. But everytime an OrderDtl record is saved the OrderHea.Order_Number field is moved into the OrderDtl.Order_Number field prior to the save. This is why when you look at the code for the Order example you will see that a parent record must be found before it allows the user to enter the dbGrid to enter child records.
If a child record was created without having found a parent record first, it would result in a disconnected orphan child record and would display in the grid whenever the parent record was blank. This is NOT what is wanted!
501
File Normalization Normalization is the elimination of data duplication between files. To create file relationships we need to duplicate the related field in both files in order to link the files together, but this should be the only data duplicated. A good file structure will eliminate the need to duplicate data among files.
When data is duplicated between files Maintenance must be duplicated in order to update the data. Data integrity is sacrificed, as the data is not updated properly.
Examples of Bad Normalization: Customer Addresses are maintained in several files Customer Name is used instead of a Customer Code field for relationships (names are not unique and can change exceptionally for woman when they marry/divorce)
502
Database files: Extensions Filelist.CFG DAT HDR K?? RPT TAG VLD FD DEF Description This file lists all database table file names Data files Header files used to repair the header of the .DAT file Index (Key) files making finds quicker Crystal Report files created by the Seagate Crystal Report program Field name file used by Database Builder/Database Explorer/Crystal Variable Length Data files stores the data when compression is used File Definition an ASCII file used by the compiler to convert File.Field names into File#.Field# ASCII Definition files - contains a database file definition
Common Application files: Extensions DD SRC VW RV PKG INC EXE Description Data Dictionary files Contains the Class with the Business Rules Main Source code files View code files Report View code files Package files external code files for classes etc Include files external code files Compiled VDF Code
503
Maintenance of Files
Database Builder utility is used for most maintenance that needs to be preformed on the database tables. Maximum Records: If you are using an embedded (DataFlex) database table, this number is very important. The embedded database uses the Max Records parameter for organizing its indexes efficiently. You should set a value for each file that is sufficiently large to accommodate the expected growth of records in the file. You should never allow the number of records in a file to exceed the Max Records; this can result in corruption of one or more indexes. Many developers will add into their code a feature that will check and adjust this number without user intervention. Each time you save a change to the Max Records parameter, Database Builder must rebuild the files indexes, and will do so automatically. When you set Max Records to 1, Visual DataFlex will treat the file as a system file and automatically place a check in the System File checkbox. Database Builder can also run a Percentage Filled Report, which will show how close your files are to this setting.
Figure 319
Set Max Records to 20% more than your expected size for the database table.
504
Reindexing Occasionally, index files will become corrupt and will need to be rebuilt. Corruption can occur if the computer is turned off while writing to the hard drive. Reindexing will read through the main file and rebuild all the index (.K*) files.
Figure 320
Reindexing can be accomplished from the Maintenance pull-down of Database Builder or programmable using the Sort command.
505
Definition of Classes and Objects: Classes are the tools and Objects are the instance of using those tools. That still sounds like Greek, so lets relate them to something in the REAL world. Think of Classes as a cookie cutter and every time you use this tool is an instance of the tool (a cookie)! If you use a Star Cookie Cutter, you will create a Star Cookie. Use this tool every time you want your cookies to have five points. If you want heart cookies you use the heart cookie cutter (tool = class). The cookie cutter and the cookies are both called a star or a heart but there is a big difference between them, just like there is a big difference between Classes and Objects. It is confusing because you call each by its cutter/cookie shape or by its class/object purpose. You have DataDictionary classes and DataDictionary objects; array classes and array objects. You would use the cookie cutter tool to create the cookies to eat. In OOP you would use the Class to create the Objects for the application to run. Someone has to create the tools. If you look at the FMAC file (a file that holds all the underlining commands to make the basic language work) you could see how the Enter Macro was created. These lines of code in FMAC make the Enter Macro command operational, much like code that make Classes operate. Most of the classes have corresponding package (.PKG) files that have the code to make the class/tool work. The code in FMAC does nothing by itSelf. You must use the Enter Macro Command in your source code in order for the program to allow the user to enter data. In OOP, you create objects from your class/tools to allow the user to interact and accomplish their required tasks. There are many classes/tools that come with the language. One of the things that you must learn is the most common classes (tools) that are used. One common class (tool) is an Array class. Each time you use this Array class (tool) you create an Array Object, (cookie). This object (cookie) will have all the functionality of the class (cookie cutter). In the DataFlex procedural language, you had three macros Enter Macro; EnterGroup Macro and the Report Macro. These were tools very much like Classes. Using these tools made coding faster and easier. One of the drawbacks of the 2.3b Enter and Report Macros were that you could only use them once per program because they used labels to navigate, and of course you could not have two labels with the same name. DataFlex Object Oriented tools do not have this limit. Reusing code (classes) over and over is the fundamental purpose of OOP.
507
Common Classes (Tools) Class Array Button DataDictionary Tool Use Used to store data as a temporary memory storage area. Its size grows dynamically to accommodate the storage requirements To create visual representations of keys or buttons that, when pressed by users, produce a specific action (event). The tool that provides database services (finds, saves, deletes and clears). Stores the Business Rules for the database table.
Some classes are product or application-type specific Character-Based Entry_View_Client VDF (Windows apps) DbView VDF (Web apps) cWebApp Class Use a container specially suited as the outer container of a view data entry tool (display & edit) of a single record data entry (display & edit) a scrollable, multi-column list of records data entry tool for text fields cWebReport cWebBusiness Process Used to create reports To contain and execute the statements to perform a batch process on an applications database files
Entry_Form Table
DbForm DbGrid
OOP terminology is sort of like learning a foreign language. At first, every time you learn a new word; you must convert it to your native tongue, or relate it to something you understand. So far you have Class = (Tool or Cookie Cutter, or Enter Macro) and Object = (an imprint from a class or Cookie, like the code using an Enter Macro).
508 Data Access Corporation
Lets look at some code. The comparison is between Procedural code with DOS object oriented classes. Procedural Example
// code for the enter macro is in FMAC
__.__ __ ___.__ /*
__.__ __ ___.__
Enter TimeFile Empl // Enter macro requires child file listed first
Object TimeCard is an Entry_Form TimeCard_Image // (using clause link to Data_Set left out for this example) Item_List
{AutoFind} {CapsLock}
{AutoFind} {CapsLock}
EnterEnd
End_Object
In the above example, TimeCard is the Object and Entry_Form is the Class. Classes are the tools and Objects are the instance of using these tools. Just knowing that the object was created from the Entry_Form Class you know its purpose is to allow the user to edit and display single records. The object is an imprint from the tool that it was created from. Just like cookies were imprints from the cookie cutter.
509
Procedures & Local Variables Procedural code had structural code where you used GoSubs to execute sections of code. In Object Oriented, you send messages but basically they are doing the same thing. Procedural Example
//declaring global variables Number nHours nRate nPay GoSub Calc_It // Jump to a label called Calc_It & execute the // subroutine until a Return command is encounter.
Calc_It:
// One Based
Get Field_Current_Value field Empl.Rate to nRate Get Field_Current_Value field Empl.Hours to nHours Calc (nHours * nRate) to nPay Set Field_Current_Value field Tcard.Pay to nPay End_Procedure
Notice the use of local variables in the OOP procedures and global variables used in the procedural code. The local variables used in procedures are dynamic variables (meaning they will grow as needed, so you no longer indicate the length of string variables). Local variables are destroyed and the memory released as soon as the end_procedure command is reached. This is much more efficient! The Get and Set commands retrieve and set properties. Properties are special object variables or item variables that are used to determine the current state of the object/item. Procedural code had predefined variables. For example, the Report Macro used PageEnd and PageFeed. The Move command could address these predefined variables directly. OOP properties (which are similar to predefined variables) use the get and set commands to obtain or change properties. You may have heard that Object Oriented Programming is Event Driven. That is an event triggers the direction flow that the program takes. Procedural programming is more sequential in its flow. At first, a programmer may feel he has lost control over the user that now has this mouse and can easily jump anywhere! These events that drive the program flow can be controlled. It just may seem different, at first, as you learn all the events that allow you to send messages (which are like gosubs to subroutines).
510
If your OOP page allows database table operations to the Customer file, the Customer_DD (DDO) is being used to perform these operations. The Server property will connect the entry object to the Customer DataDictionary Object. This DataDictionary Object will supply the database table operations for find, clear, save, and delete operations. The procedural Enter macro has the ability to perform database table operations (finds/saves/deletes/clears) within the macro tool itSelf. The DataDictionary class also has these functions built into the class. In OOP you will be using many tools, and it would be a waste to have each class (tool) understand how to perform the complex multi-user database table operations. Therefore, you separate these tasks out and whenever a class needs these database table operations, they are linked to the DataDictionary object that should be servicing it for finds, clears, saves, and deletes. In OOP you link your Data Entry Object DEO (Web Business Object -WBO in Web apps) and DataDictionary Objects (DDO) together to give the DEO/WBO access to the database table. Each DEO/WBO will link (via the Main_DD property) to their main DataDictionary Object. This is sort of like a computer operating system. If you wish your computer to save a file to the floppy drive, you do not ask the computer - you ask the operating system to ask the computer. The operating system knows how to do this and does it well, so you let it do all the work of finding all the fragmented parts of the file and moving them to the floppy in drive A. Then, it updates the File allocation table so the file will show up the next time you do a DIR A:. DataDictionarys do all the overhead work of rereading and locking your files. They do all these database table tasks so well that you should always allow them to perform these types of tasks.
511
Multiple DataDictionary Objects (DDOs) Lets look at a VDF view using DataDictionary classes.
Use Windows ACTIVATE_VIEW Activate_oView FOR oView Object oView is a dbView // A framework rule states that there should be a Data Dictionary Object for every File opened. Object Employee_DD is an Employee_DataDictionary End_Object Object TimeCard_DD is a TimeCard_DataDictionary Set DDO_Server to Employee_DD End_Object Object Empl_ID is an dbForm Set Server to (Employee_DataDictionary (Self)) Entry_Item Empl.ID End_Object Object Hours is an dbForm Set Server to (TimeCard_DataDictionary (Self)) Entry_Item TimeCard.Hours End_Object Object Rate is an dbForm Set Server to (TimeCard_DataDictionary (Self)) Entry_Item TimeCard.Rate End_Object End_Object
The DDO Server Clause establishes a two way communication between these DDOs.
Employee_Data_Set Object TimeCard Object Connected to Employee_DD Empl_ID Object Server Employee_DD Hours Object Server TimeCard_DD Rate Object Server TimeCard_DD
The Enter Macro had rules that had to be followed when you used related files. All files were listed after the Enter Command. The order that the files were listed was very important for the correct saving and deleting of the data in the related files. Lower (child) files were listed first, followed by higher (parent) files. In OOP, you connect the DEO/WBO to the main DataDictionary Object (DDO) via the
512 Data Access Corporation
Server property, just like in the last example. Then, if there are multiple related files, you connect the DataDictionary Objects together via the DDO_Server property. You link your DataDictionary Objects together just like the related file structure created in Database table Builder (DFFile). Hopefully, you are starting to see the power of OOP. You take classes (tools) and by making objects (imprints from them) you create an application that users can interact with to have access to the database table.
513
Encapsulation An object-oriented term that is heard often is encapsulation. The definition of encapsulation is combining data and procedures into a single entity capable of manipulating itSelf. The easiest way to understand these terms is to relate them back to procedural code. Individual programs in their own source code (.SRC or .FRM) file. Each a stand-alone (encapsulated) section of code.
Procedural Menus
Main Menu ----------------------------------------------Data Entry Menu Report Menu System Parameters Employee Entry ----------------------------------------------Employee ID _____ Dept ____ Name: __________________
Address __________________ Data Entry Menu ----------------------------------------------Employee Entry Department Entry Time Card Entry Department Entry ----------------------------------------------Dept ____ Name: __________________ City ____________ St__ Zip ____
Rate
____.__
514
Procedural code normally had a menu program that executed, via Chain wait commands, all the separate .FLX programs. An OOP application will combine all the views into a single application (.src) and from a starting page or menu bar launch the individual views (web pages).
The different views all can be displaying different Individual views each records from the same file. with their own .VW The DataFlex language still (WBO & ASP) file. only has one record buffer for each opened file, how is it possible that the views all display/save/delete different records? Each view contains its own DataDictionary object for the Employee file. The Employee view has an Figure 321 Employee_DataDictionary Object, the Department View might also be displaying an Employee record, however that view has its own Employee_DataDictionary Object. Remember these DataDictionary Objects service the view objects for Finds/Clears/Saves/& Deletes. They are responsible for making sure that the correct record is in the record buffer! This is a task that the Data Dictionarys do well. The user now can bring up all the views on screen at the same time and jump between them with the mouse! The DataDictionary just sits back and keeps track of the correct record for you! What a great tool (class).
515
Message Forwarding Procedural Code came with 3 macro tools, but Object Oriented has MANY.
UI_Object Menu List EntryList Wide_List Data_List Table The entire Hierarchy Chart is large. However only a handful of classes are used often. One tool is built off the tool above it. Instead of rebuilding the wheel each time you create a new tool, you simply add the new features in the new tool. The tools get more and more powerful as they are subclassed. An example of how the tasks are passed from class to class, would be similar to how networks and operating systems pass commands along. They do basically the same thing the classes are doing. If you are running a Novell network all commands typed at the prompt go to Novell. Novell will perform the task if it is a Novell command like NDIR or CAPTURE but if it is a DOS command, Novell just hands it to DOS to handle. If you type DIR, Novell will (take this command) find that it does not know how to do this task and forwards the command to DOS. Since DOS knows how to handle this command, the DIR task is performed. It would not be efficient to rewrite all the DOS commands in Novell just like it would not be effective to do this whenever you create a new class. DIR Command
Novell
DOS
Since Novell is built from DOS, there is no need to make Novell understand how to do a DIR. It only has to forward it to DOS to handle. Classes operate the same way. The message Bell is sent to an object built from the Button class. It may not know how to ring the computer bell but it will forward this message up to its super-class and if that
516 Data Access Corporation
super-class cannot ring the bell it will forward the message up the branch until a class understands how to ring the bell. Just like you do not care if Novell or DOS takes care of a command the user will not care who handles the message Send Bell. Just for your information the defining class for the message bell is the UI_Object Class. How do you find out? The On-Line help will list all predefined procedures and functions (similar to subroutines) in a chart. This chart will tell you the defining class. Looking up the procedure under the Defining Class section will give you a full description of the purpose and use of the message. Now that you are aware that messages may be passed up the class hierarchy structure, it is time to take a look at building a class. It is important to note that developers will find the DataFlex predefined classes to be sufficient for most programming needs, but occasionally there will be a need to build a class (tool). The most common class that you will need to build is a class built from the DataDictionary class. Database Builder makes creating DataDictionary classes very easy from four tab pages that allow you to fill in a group of forms and checkboxes. The Enter Macro had the database table operations built in, but in OOP they are separated out into the DataDictionary Class. In procedural coding, there are times when you needed to perform certain tasks during the lock state of save and delete operations. The Enter.Save and Enter.Edit were provided to perform operations such as automatically assigning the next available ID number from a SysFile or keeping track of running totals. In Object Oriented, the Creating Procedure is only called during a new save and the Update and Backout procedures are used to maintain running totals.
517
Event Driven OOP is an event driven language. Events are actions that trigger messages to flow. In OOP nothing is done until a message is sent. Therefore it is very important to know how to trigger these messages.
Description The purpose of some classes is to trigger messages. The button class is sends the OnClick event when clicked. (i.e.; Menu bars; Tool-bars). The purpose of accelerator keys is to send messages. (i.e.; F2 sends the Request_Save message and Shift+F2 sends the Request_Delete message. The purpose of the On_Key command is to trigger a message when the defined key stroke is pressed. (i.e.; On_Key Key_Alt+Key_P send Print_It. The Send command will trigger a message. There are many variations to the send command; Delegate; Forward; Broadcast. Many pre-existing messages can be augmented to perform extra processing or additional messages whenever they are normally triggered. A special command that starts the User Interface.
Accelerator Keys
On_Key
518
Building New Classes: New classes are built so objects built form them will contain the new class features. This is how the business rules are added into one location and affect all views. The CapsLock option is added into the DataDictionary class and after recompiling it will effect all views that contain this field. // Empl.DD File
// Employee_DD Class built from DataDictionary Class
Procedure Define_Fields Forward Send Define_Fields Set Main_File to Empl.file_number Set Field_Options Field Customer.State To DD_CAPSLOCK // other business rules
End_Procedure End_Class
Object Employee_DD is an Employee_DataDictionary End_Object //Empl.VW File Employee Entry View Use Empl.DD
519
The UIMS User Interface Management System (UIMS) is like a shell level in DOS. At the command line, DOS just sits and waits for the user to type a command and press return. The UIMS is similar to an operating system waiting for a command or an event to happen that will trigger (send) a message.
Customer DataDictionary
Object Customer_Grid is a dbGrid Set Server to (Customer_DD(Self)) Begin_Row Entry_Item Cust.ID Entry_Item Cust.Name Entry_Item Cust.Phone End_Row End_Object Start_UI (Customer_Grid(Self))
Customer_Grid
In the program nothing really happened until the last line, when the Start_UI command is reached. All the objects are simply built in memory. The Start_UI command is really two commands in one. It starts the User Interface (UI) rolling. Remember messages are just the gosub that will execute a procedure (subroutine). The UI starts and simply waits for those events to trigger the sending of messages that make the program run. There are many ways to trigger messages to be sent (e.g., keyboard entry, mouse clicks, timers firing, entry options, setting certain properties). At first, procedural programmers may feel like they have lost control to the user or UIMS. In procedural code the user was pushed straight through your code. The user
520 Data Access Corporation
could navigate up and down through the entry windows and with this limit, the programmer had complete control over the actions of the user. Now with the mouse the user can navigate anywhere - anytime or so it seems. The real skill of OOP comes with the coding of these events that will trigger your messages at the correct time. The more you code in Object Oriented, the easier it will become. One of the biggest benefits is the increase in data integrity. This is accomplished by separating the database table operations from the Data Entry operations. This is a logical separation and one that has many benefits!
521
Summary In this OOP overview many concepts have been quickly covered. There is still much to learn but hopefully you will have a good general understanding of some of the basic principals of object-oriented programming and how it works, so the rest of your reading is easier.
Topics Covered: An understanding of the terms Classes and Objects A general idea and use of the commonly used classes. An understanding of forwarding messages through the class hierarchy structure The use of Procedures to accomplish tasks and how to trigger them by sending messages. A general understanding of the DataDictionary Class. Its importance as the server of view Objects via the phMainDD property. How DataDictionary Objects are linked together with the DDO_Server property similar to the file relationship structure. The power of creating new classes (tools) in order to stop duplication of code. The need to create new classes (tools). Example: creating business rule in the DataDictionary class. How encapsulation of each view linked together via the .SRC file. General understanding of the UIMS operation. A general connection between Procedural code to Object Oriented code.
522
Prior DataFlex Character-Based OOP Users Modal state is now used in place of Block_Mouse_State. There are many changes and you should read the Whats New section whenever upgrading your application.
Everyone New to VDF8 Refer to the Whats New sections in the on-line help. There are so many items that have changed in the different versions of VDF. This great section will outline the many new improvements made to the latest VDF version(s). The links in this section will jump you to full descriptions of the great features that have been added.
523
524
Glossary
Glossary
The words in this list are used in Visual DataFlex documentation with specific meanings beyond their meaning in general contexts, even general computer-oriented contexts. Consult this list whenever you encounter a word in the documentation that seems to be used with a special meaning.
525
Glossary
Definitions A key, or combination of keys, that invokes an applicationdefined procedure. The keys are referenced within a program by a predefined name preceded by the letter "k," (e.g., kcancel). Each accelerator key is mapped to an actual key on the keyboard and the mapping can be changed through the DataFlex Configuration. See also Flex-Key. A reference created by the compiler to address the object. This reference can be used to address objects in the program. At compile time, the compiler creates a special function, which uses the same name as the object, which is being accessed. That function returns the object's absolute object identifier. For example, if Object b is nested within Object a, you would use (b(a.obj)) to reference Object b. This is the access method by which Object b may be referenced. See also Object; Object Identifier. A horizontal bar that contains pull down lists giving choices for specific actions. Like Menus A term denoting a parent, grandparent, great grandparent, etc., of an object or class. See also Child Object; Class; Descendent; Object; Parent Object. Is the methodology to construct and connect object-oriented sections together correctly. A parameter passed to a procedure, function, or a macro to control the process. See also Function; Macro; Procedure. The process by which an inherited procedure or function is given, adds functionality in a subclass. A procedure or function is augmented by defining a procedure or function with the same name as the inherited one and including in the new definition, a forward command that sends the message to the class from which it was originally inherited. See also Override.
Access Method
526
Glossary
Definitions A procedure in the Data_Set class called during deletes and edit saves that allows the programmer to code during a lock state (such as maintaining running totals). Like the Enter.Edit in DataFlex procedural code. The process in which a parent object sends the same message to all of its child objects. If the message sent returns a value, only the last value is retained. For example, an object might broadcast the message, initialize, to all of its children as preparation to further operations. Message delegation is turned off during a broadcast. See also Delegate. An area in the computers memory which is used to store and manipulate the data being entered by the user in the edit class. See also Class, Base; Edit. An area in the computers memory that contains a record from each opened database file. The place in memory where these records are active is called the record buffer. When a record has been read from disk to the record buffer, data can then be extracted, added to, and/or modified in that record. The record can then be written back to disk (saved). Likewise, in order to delete a record, the record must first be active. The record buffer is where DataFlex does its work on a given record. See also File, Database; Record. An area in memory where the active image is located. There are image-name-line options, resident and resource, which place an image in memory for the duration of the program. See also Current Image; Current Window; Image; Window. A naming convention database file which is relating to another file and there is a valid relationship established. This database file extracts the related fields from the related to database file (Parent) and allows for a seamless data structure within a program. See also Parent File.
Broadcast
Buffer, Edit
Buffer, Record
Buffer, Screen
Child File
527
Glossary
Definitions An object-creation block which is nested inside an objectcreation block. Parentage provides a route for the child object to inherit properties, including messages and accelerator keys. See also Descendent; Object; Parent Object. A group of properties, children and messages that define specific behaviors to objects. Classes are designed by behavioral description, or, a class may be constructed as the intersection of the properties of a set of similar objects. A class must be based on another class, called its superclass. See also Class, Base; Superclass. We can also think of them as Tools that our objects are built from. Like the Enter or Report macro in DataFlex procedural code. A set of classes supplied with Visual DataFlex defined `below' the level of DataFlex itself (as distinguished from classes created with the class command). The base classes, also called "data structures" are Message, Menu, DFList, Edit, Scrollb (Scroll Bar), and Array. See also Class; Superclass. A .PKG file that contains the source code for a class definition. This code is included in the program at compile time through the use command. Examples: Windows.PKG, DfAllEnt.PKG An abstract term denoting an area in memory that stores data. It is designed to be used as the source and destination for cut and paste operations. The clipboard is automatically created by the system, and is available to the programmer at any time a cut source or destination is needed. The clipboard is retained across chain and chain wait operations, so it can be used to transfer information between programs or modules of an application. The clipboard can receive all of the messages of the edit class objects. See also Edit; Object.
Class
Class, Base
Class Package
Clipboard
528
Glossary
Terms Command
Definitions A word or series of words in program source code which execute a predefined procedure (i.e., goto X1, sends execution to Label x1) or string abc (creates a variable named abc with a length of 80 characters). DataFlex commands are macros, which are defined in the file FLEX.CFL. FLEX.CFL is what the compiler reads as it processes your program source code. Commands can also be defined with compiler directives in programs and packages. See also Macro. The method of comparing values using any of the following logical functions: matches, contains, min, max, ior, iand, <>, >, <, =, <=, and >= in expressions, and ne, eq, lt, gt, ge, le, match, and in commands. See also Function. A procedure in the DataDictionary class called only during new saves that that allows the programmer to code during a lock state (such as assigning next available ID numbers). Like the Enter.Save in DataFlex procedural code. An active object currently being used. An object becomes the current focus in the focus list when 1) a message is sent or a command is executed to activate an object or group of objects, 2) a procedure or function uses the procedure_return or function_return command to return a non-zero value to a start_ui or ui_accept command, or 3) the user clicks the mouse cursor on an object which is already activated, but not the current focus. See also Focus List. The image being acted upon. Images are numbered consecutively (top to bottom) within a program when compiled. The image being acted upon is internally maintained by the current_image system variable. See also Buffer Screen, Current Window, Image, Window. A predefined integer that contains the number of the message that invoked the currently executing procedure. current_message is useful when the message number of a procedure must be passed to another procedure.
Comparison Mode
Creating Procedure
Current Focus
Current Image
Current Message
529
Glossary
Terms Current_Object
Definitions A predefined integer that always contains the absolute object identifier for the object owning the procedure currently executing. See also Focus, Focus List, Object, Object Identifier. The window being acted upon. Windows are numbered consecutively (left to right, top to bottom) within a program, regardless of the image they belong to when compiled. The window being acted upon is internally maintained by the current_window system variable. See also Current Image, Image, Window. A visual cue that shows users the current position of the mouse input focus (current position). See also Cursor Text, Cursor Selection. A visual cue whereby users indicate with the keyboard the choice they want to interact with. It is represented by highlighting the choice with an inverse bar. For example, if you were making a selection from a scrolling list, the selection cursor would be located on the choice in the list, which is highlighted. See also Cursor Text.
Current Window
Cursor, Mouse
Cursor, Selection
Cursor, Text
A visual cue that shows users the current position of the keyboard input focus (current location). See also Cursor Mouse, Cursor Selection. The .DAT files are the data files where DataFlex stores the raw data entered, unless compression is used in which case the data is stored in the .VLD file and the .DAT is used as a pointer to locate the correct record in the .VLD file
.DAT files
530
Glossary
Terms Date
Definitions A field, variable or window used for evaluating and storing dates. There are three formats supported; mm/dd/yyyy (USA), dd/mm/yyyy (European) and yyyy.mm.dd (Military), where mm indicates two digits representing the month, dd represents two digits representing the day, and yyyy represents four digits representing the year. Two-digit entry and recording of years is allowed optionally. The format is set as a system option in the DataFlex Configuration. Dates are stored in Julian form as numbers, allowing for operations requiring calculations without type conversion. The display is a de-coded representation of the numeric format storage. There is a date command, which defines a variable of Type Date. See also Variable, Window.
.DEF files
The .DEF files have an entire file structure of a database described in an ASCII format. These ACSII files can be created from DFFile or DFMaint and can be used in DFFile to create a duplicate file structure. The process by which a message is sent to the parent object of the current object. Any message that cannot be understood by the current object or the class of the current object is automatically delegated (sent to the parent of that object or class). This delegation continues until the message reaches the Desktop; if the Desktop cannot understand the message, an error is generated. There is also a delegate command in DataFlex that causes messages to be sent directly to the parent. Data-Entry Objects are objects that allow data-entry. A term denoting a child, grandchild, great grandchild, etc., of an object or class. See also Ancestor; Object; Class; Object; Parent Object. An "invisible" object which is the ultimate ancestor of all objects within a program. The desktop is the background upon which all other objects are displayed. Likewise, it is the final receiver of messages that are delegated by global objects. There can only be one desktop within a program. Deviations of objects from their superclass
531
Delegate
DEO Descendent
Desktop
Differentiation
Data Access Corporation
Glossary
Terms DSO
Definitions Data Set Objects are objects that are built from the Data_Set class or a subclass built from this important class. Data Sets Objects are used as the servers to the DEOs. They handle the database operation such as finds, clears, saves, and deletes. See Class, Base.
Edit
Encapsulation
A section of code that can operate alone This does not mean it needs no external connections. An object is an encapsulated code segment; it is a black box whose makeup you need not know exactly, just the interfaces that allow you to interact with it (i.e. what properties and messages can be sent to it). The object may have external dependencies, such as a DEO being connected to a DataDictionay Object. Options that are connected to an item Windows that will perform a desired action when the user enters or leaves a window. Example: {CapsLock} will force the contents of the window to only be capital letters: Field_Entry_msg property will send the corresponding message just prior to entering the window. The ability for a user to process requests for action at almost any time. When users navigate with the arrow keys, input, select items with the mouse, or press accelerator keys, the program is continually asked to respond to events. These events may be directed at any active object, or cause the activation of objects. Events that determine the flow of the program. Like a KeyProc used in DataFlex procedural code. See also User Interface.
Event-Driven Interface
Expression
A set of commands encompassed by "(" and ")" which are executed jointly to process data. All expressions return a value. Expressions can be nested. For example (length(trim(temp_string))), in this expression the variable temp_string is first trimmed then the length of it is calculated. See also Command.
Data Access Corporation
532
Glossary
Terms Field
Definitions A discrete piece of data that is of a defined type and size which is stored in a record. There are usually many fields in a record. Each field is given a name that is unique to that database file, and common to every record. Database fields are sometimes referred to as the elements in the file. You can have up to 255 fields per record. See also File, Database; Record. An area on disk that holds structured data, which makes up a particular information system. A database consists of records, which contain fields (file elements). Database file definitions contain the name of the file, the numbers, lengths, and types of the fields, which fields make up the indexes, etc. Database files are analogous to a file cabinet drawer (database file) containing folders of employees (records), which contain the employees employment form (the data in the employees employment form are the fields). See also Field; File System; Record.
File, Database
File, Index
A file (organized listing) used to expedite the finding of records for a database file. The file structure is B+ Multi-level ISAM. There are two types of index files; online (maintained automatically by the programs) and batch (must be reindexed prior to its use). Index files determine if the fields of a database file can be duplicated (the record number is part of the index) or not. An index file is created by the DataFlex Database Builder or the DataFlex Index Tool. See also Field; File, Database; Record; Reindex. Filelist.CFG contains a list of all the filenames (Rootname, DataFlex name, User name) for each file that is accessible.
Filelist.CFG
The numbered list of database files in a system, kept in a file default-named Filelist.CFG. The compiler and the runtime uses Filelist.CFG to find the physical disk fileset containing the desired data.
533
Glossary
Definitions Data in sequential files can only be accessed sequentially, rather than randomly as in database files. The read, readln and read_block commands are used to access the data in sequential files. One of the most common types of sequential files is ASCII text files.
File, System
A database file with unique limitations. The file can not contain more than one record, be indexed, or have a relationship established with another database file. The buffer of a system file is automatically loaded with the data contained in its record upon open. The purpose of this type of database file is to keep system (global) information in it (i.e., your company name, address, city, state and zipcode). See also Child File; File, Database; File, Index; Parent File. Any of 13 standard DataFlex functions activated by a single keypress or shift-key combination. The functions pertain to database operations (finding, deleting, saving) and text editing (backspace, arrows), and have standard names in DataFlex to make the function independent of the particular physical keys to which they are mapped. The mapping is configurable at each site, and for each machine using a multi-user license. See also Accelerator Key. See Current Focus.
Flex-Key
Focus
Focus List
A list of objects that are currently activated. This list is modified by the activation (activate) and deactivation (deactivate) of objects. This list is set up so that each object in the list knows 1) what object had the focus prior to its own activation (prior_focus), and 2) what object took the focus after it was activated (next_focus). In programmer terms, the focus list is a doubly-linked list. How this list is maintained is critical to the design of an application - the order of activation and parentage of objects must follow a particular structure for a program to function properly. The object that currently is capable of user interaction.
Data Access Corporation
Focus Object
534
Glossary
Definitions UIMS applications organize objects in a manner allowing logical navigation paths between objects. As objects activate and deactivate, this tree is updated to reflect the objects position in relation to other active objects. Four properties indicate the objects position: Prior_Focus, Next_Focus, Prior_Level, and Next_Level. The process of sending a message to the ancestor class of an object or class. If no ancestor of an object understands a message, then it is delegated to the parent of the object to which it was sent. The forward command causes messages to be sent to the ancestor class. See also Delegate. To reference an object not yet created. When it is necessary to reference an object not yet created, use the Register_Object command, so it creates an access method for that object. See also Access Method; Object. A block of code which incorporates a set of commands that jointly define messages sent to an object. The message is defined using the get command. A function is defined by the function and End_Function commands. Functions return a value of a particular type using the function_return command. Functions can not be nested. Functions are like subroutines in procedural code that always return a value. See also Command; Delegate; Message; Object; Procedure. Something is global when it is not contained within the bounds of a class, object, function or procedure. For example, a variable not specifically declared within a procedure is global. A procedure, function, or object is global when it is not nested within any other object. Global code and data structures can generally be referenced by any part of the program. An object whose parent is the desktop. These objects are described as `children of the desktop' or global objects, and may be addressed without access methods. See also Access Method; Child Object; Parent Object.
Forward
Forward Reference
Function
Global
Global, Object
535
Glossary
Terms Handler
Definitions A handler is another term for a message-handling procedure. The name comes from the idea that the handler "handles" or responds to a message it receives. See also Message; Procedure. An area in memory that holds static and data-output areas (Windows). In source code, an image (also referred to as a "page") is defined by a slash (/) in the first (0) column and followed by a name (page name) which must contain a letter in the first character. An image continues until the start of another image ("/pagename") or the end of the image section (indicated by "/*" at the start of the first line after the last image). Each image can be manipulated individually by the program. Images can be used for output to a device (printer, console or file). Each image is identified by a page name. See also Window. The ability for an object to change the image (visual property) at runtime. Certain objects can change their visual properties at runtime. For example, the edit object may change its height and width merely by changing the value of its size property. The scrollbar object adjusts its length based on the length of its parent. Images that can be changed at runtime are dynamic images. A special type of argument (often referred to as "flags") which conditionally controls command line execution. Boolean in nature, it can only be set to true or false. It is created with the indicator command and defaults to a false status until some other event in the program resets it to true (i.e., indicator select). Once defined, an indicator is addressed by enclosing its name in brackets ("[" and "]") to identify it to the command processor (i.e., [not select] return). The process of assuming properties and message handlers from an object's class. Inheritance saves the effort and potential error of having to define the properties and messages of every object explicitly. See also Subclass; Superclass.
Image
Image, Dynamic
Indicator
Inheritance
536
Glossary
Terms Instance
Definitions The coming to existence of an object (i.e., an object is an instance of a class). The realization of a class definition. In a class, the construct_object is the operation, which is executed on a new instance of the class to configure the instance to conform to the class's definition. See also Class; Object. One of three types of numeric representations that can be used as the subject of a command's execution or expression evaluation. A field, variable or window used for storing number types. Only whole numbers can be stored in this type, ranging from 0 to 2,147,483,647. There is an integer command, which defines a variable type integer. See also Variable; Window. A message not understood by the receiving object, its ancestors or the desktop. When the message reaches the desktop and it can not understand it, an error is generated. See also Message. A storage area for data associated with an object, displayed for user interaction. When an object, which contains items, is displayed for interaction with the user, the data for the items will be displayed in the windows of the object's image. The data for each item is initialized when the item is created, according to the command used to create the item. All items have a value property associated with them. The data stored in the value property of an item is a string and is displayed when the user is interacting with the object. Items may contain different types of data and maintain various states, depending on the class of the object in which the item is created. There are five types of item lists, which can be created by DataFlex; Static, Dynamic, Entry, Window and Array. See also Item List, Dynamic; Item List, Static; Object.
Integer
Invalid Message
Item
537
Glossary
Definitions A list where not all of the items in an object can be seen in the windows at once. Consequently these objects also automatically create a scroll bar to indicate when there are more items above or below the items currently displayed. The classes, which support dynamic item lists, are DFList, Checklist, Entrylist, and Formlist. The add_item and insert_item commands are used to create items in objects of these classes, while the delete_item message can be used to remove items from the list. The syntax for add_item and insert_item allow the item's message and value to be specified, but the item selection message is always sent to the object in which the items are created. See also Item; Item List, Static; Object. A list where all the items of an object can be seen in the windows at once. The classes that use static item lists are Menu, MenuBar, Button, Checkbox, Entry, and Form. Items in objects based on one of these classes must be created within an item_list-end_item_list structure using the on_item command. See also Item; Item List, Dynamic; Object. A program location identifier used by control commands (i.e., goto, gosub, return) to jump over commands and group of commands. It is defined as any continuous string of characters at the beginning of a line followed immediately by a colon (:). Labels must begin with a letter, which may be followed by up to 79 numbers or letters (no spaces or punctuation). A variable which cannot be referenced outside the procedure or function which defined it. They are defined by invoking the local command preceding the variable type. Multiple procedures may define local variables with the same name but each will have its own value. A local variable may not have the same name as a global variable. Local variables release their memory area upon the end_procedure line. See also Global; Variable.
Label
Local Variable
538
Glossary
Terms Macro
Definitions A set of code (which the compiler understands) that accepts arguments and textually substitutes the values of the arguments into the command model. The resultant commands are then compiled and included with the rest of the code. Macros can be defined directly within one or more programs, or they can be defined in packages. Macros are expanded every time the compiler finds a call to it. See also Command; Subroutine. There is a menu object class, and a user-interface element called menu. The class is frequently user to create the element in programs. See Menu bar Pulldown; Class, Base. An extension of the menu bar that displays a list of choices available for a selected choice in the menu bar. After a user selects a choice in the menu bar, the pulldown appears. Another term is Menu. A request for an object to perform one of its operations. It is not a behavior, it is a name (and the arguments) of a behavior. They are the only interface to an object. Messages are sent and received by the send, get, and set commands. These is also a message class. Messages are like a gosub in procedural code. See Class, Base. A type of property which has a finite number of values it can contain. The number of properties is usually three or more; properties with only two possible values are generally considered to be states, not modes. An example of a mode is search_mode which may be set to first_character, incremental, capital, and no_search. See also State, Property. Users are required to finish one task before moving to the next One of three types of numeric representations that can be used as the subject of a command's execution or expression evaluation. A field, variable or window used for storing number types. Only fixed point numbers can be stored in this type, ranging from .00000001 to 99,999,999,999,999.99999999. There is a number command which defines a variable of type Numeric. See also Variable; Window.
Menu
Message
Mode, Property
539
Glossary
Terms Object
Definitions An object is the realization of a class (sometimes referred to as the object's type). An object can be defined in terms of the properties and messages that it understands. The commands between object and End_Object commands are executed by the runtime (not the compiler) during the creation of the object. An object relationship to a class is similar to the variable's relationship to its type. See also Access Method; Global Object; Object Identifier. Objects are the instance of using a class. Like: the Enter Macro in procedural code An integer unique to each object assigned at runtime when the object command is executed. This integer is called the absolute object identifier. If an object is the child of the desktop the compiler issues a global object identifier. See also Access Method; Object. A style of programming which uses objects as the unit of software division and messages as the way to connect objects. Data is encapsulated within an object, making it part of the process and is not treated globally. The messages that are provided for the object class defined by the package. Of these, the important messages are listed under the package category of Usage. See also Usage, Package. A .PKG file that contains a predefined structure of objects that may be used in programs. Example: Confirm.PKG Commands that will allow you to define program action. Like a KeyProc in DataFlex procedural code. The practice of using message arguments in a class or object that have a slightly different purpose in the class from which they are inherited. Overloading is apparent to the programmer when it is used together with (unchanging) keywords, such as item, where the actual argument is something slightly different, such as a line number. See also Encapsulation; Polymorphism.
Object Identifier
Object-Oriented Programming
Operation, Package
540
Glossary
Terms Override
Definitions The process of redefining an inherited property or message. Creating a procedure, function, or property with the same name as the one inherited causes the new definition to be used in place of the old, thus overriding the inherited property. See also Augment. A body of source code frequently composed of several classes, objects and screen definitions (images). They are a finished piece of code including the user interface, ready for implementation into your program. Packages are plain ASCII files, but must use the extension .PKG in their filenames. An example is the List package which provides users with a class that defines a pop-up look up list. A portion of the screen, usually rectangular, containing data relating to a particular function among those displayed on the screen. Panels often contain several lines and several windows, and may pop up and disappear with user interaction. Panels representing sub-functions outside which the mouse is disabled (modal dialogs) are surrounded with a double line, while others, outside which mouse action is allowed, are surrounded with a single line. See also Image; Window. A parameter is a value, or one of several values included in a procedure or function call. These values are "passed" to the procedure or function to allow it to have some desired effect. For example, a procedure designed to draw a box on the screen could be passed the height and width of the box as parameters. A naming convention denoting a database file which is being related to and there is a valid relationship established. This database file requires the field upon which the relation is based to be uniquely identifiable (main index for that field must not contain record number). Once a valid relationship is established both the Parent and Child database files will feel like one large database. The benefits for relating database files are efficient utilization of disk space (reduce data redundancy), improved efficiency in changing data, greater consistency and an easier view of the system conceptually. See also Child File.
Package
Panel
Parameter
Parent File
541
Glossary
Definitions An object-creation block with nested object-creation blocks in it. Parentage provides a route for inheritance of properties and delegation of messages. See also Ancestor; Child Object. The characteristic of objects and message definitions that permits the use of object and variable names that match in more than one place without conflict between the same-named objects and/or messages. In object and message names, this arises from the fact that objects and their messages can be address from outside the object only through their full parentage. In the names of variables used in messages, it arises from the fact that message arguments are automatically created as local variables, and local variables are normally used when declared inside message definitions. See also Access Method; Encapsulation; Local Variable; Overloading. A movable window, fixed in size, in which users provide information that is required by an application so it can continue a user request. See also Menu bar Pulldown. A programming style which places emphasis on algorithmic description, or how a procedure works. Procedural programs are built out of procedures and global data used by the procedures. Data, when considered at all, is secondary, global, and often considered unrelated to procedures. See also ObjectOriented Programming. A block of code inside an object which incorporates a set of commands that jointly define messages sent to the object. The message is defined using the set and send commands. It is defined by the procedure and end_procedure commands. Procedures can receive and/or send messages. Procedures can not be nested. They are like a subroutine in procedural code. See also Command; Delegate; Function; Message; Object.
Polymorphism
Pop-Up Window
Procedural Programming
Procedure
542
Glossary
Terms Property
Definitions The characteristics determining the uniqueness of an object. The characteristics are determined by the class and set by the object itSelf. location is an example of a property. The information in a property may not necessarily have a direct effect on the appearance of an object. A property is simply a data storage area associated with a particular object. They are like predefined variables in DataFlex procedural code. See Menu bar Pulldown. One of three types of numeric representations that can be used as the subject of a command's execution or expression evaluation. A variable or window used for storing number types. Only floating point numbers can be stored in this type, in the range 10306. There is a real command which defines a variable of Type Real. See also Variable; Window. An area in a database file composed of fields (pieces of information) relating to a particular thing. Records are automatically assigned a unique record number when it is created. You can have up to 16.6 million records in a database file and 255 fields within a record. See also Field; File, Database. The process of redrawing all objects on the screen. This is done so that the screen shows the current state of the application or applications. The process of updating an index file. This process is generated by using the DataFlex Index Tool. Its use is to update batch index files and online index files which have become corrupt (due to programming error or hardware failure). See also File, Index.
PullDown Real
Record
Refresh Screen
Reindex
543
Glossary
Definitions A way to access objects which are created as immediate children of that class. The syntax is, the class name, followed by a period, the object name, and `.OBJ'. The identifier is relative in that it is only valid in relation to the class being defined, and cannot be used outside the class definition structure. A relative identifier is quicker and easier to use within a class definition, and is the preferred method to reference objects in class definitions. See also Class; Object. The shifting of the current focus from one object to another in the Focus List. See also Focus List; Object. A set of objects that are meant to be accessed as a single unit. When a parent object has its scope_state set to true, all of its children are within the scope. Objects which have the scope_state set to true are accessed by the msg_entering_scope and msg_exiting_scope messages. Scopes are used to isolate parts of the application which are independent of each other. See also Message; Object; Property. The class, all of the values of all the properties of an object and its children. If any of these change then the object has changed state. A property which may have one of two values. Examples would be on/off, true/false, right/left. A property which has some number of finite values greater than two is generally referred to as a mode. See also Mode, Property. A command used to create a variable of type ASCII, representing a string of characters which will have a consistent meaning (but with contents that vary). The variable created will default to 80 characters in length, if the length is not specified in the command line (i.e., string varname 40; this will create a variable of type ASCII called varname with a length of 40 characters). See also Variable. A naming convention denoting a descendent class; a class which inherits from another class. See also Inheritance; Superclass.
Rotate
Scope
State, Object
State, Property
String
Subclass
544
Glossary
Definitions See Image, Shared. A block of code created after the end of the program (abort or system command). A subroutine is defined with a label and normally ends with a return command. A subroutine is accessed by a gosub control command with the label identifying the subroutine. Subroutines are read by the compiler once (saves compile lines). They are created to stop redundant coding (same block of code is used in several places). See also Label. A class used to base a class-creation block on. An ancestor or parent of a class which provides properties and messages for its descendent to inherit. See also Class; Class, Base; Inheritance; Subclass. Many packages create commands exclusively for use with objects created from the class defined in the package. These commands are discussed in the "Support Commands" section of the documentation of each package. See File Sequential.
Superclass
Text
UIMS
User Interface Management System (UIMS) is a programming environment in which DataFlex programmers can create and maintain attractive, intuitive, and powerful user interfaces for applications. A procedure in the Data_Set class called during new & edit saves that allows the programmer to code during a lock state (such as maintaining running totals). Like Enter.Save The primary documentation of how to use a class defined by a package. This section documents the basic use and syntax of the package as well all the messages and attributes which we expect you to use under "normal" circumstances. Includes a file into the code if it has not already been included. Like #INCLUDE command.
Update Procedure
Usage, Package
Use Command
545
Glossary
Definitions The method by which the program communicates with the user. Examples are popupMenus, pop-up screens, error and prompt messages, scrolling windows, accelerator keys, etc. See also Event-Driven Interface. Validation refers to the process of determining whether some specified data meets a set of criteria. For example, before we save a new record, we might wish to validate it by checking that all the fields had been filled in with acceptable entries. In reference to the items of an object, value generally refers to the data which that item holds. For example, the value of a particular item of a list would be the text displayed in that item. Data values that can be changed in the course of a program's execution. They are stored in memory, and are of a fixed length. Variable names may be up to 80 characters in length, must begin with a letter, and may not contain a space. The data types stored in variables are Date, Numeric, Real and String. Once a variable is designated a data type it can contain information consistent with its type. If data is not of the same type it will convert it to the proper type when it is moved (see move command in the DataFlex Command Reference). See also Date; Number; Real; String. A method of reading data into the buffer from disk. Virtual objects only read the data necessary for interaction, as opposed to batch objects which read all of the data at once. This method of reading data is useful when handling large amounts of data. See also Object. A section of code (usually encapsulated in an Entry_View_Client Object and activated by way of selection from a pulldown menu). That handles one aspect of a large application. E.g., The data-entry section allowing customer entry. These independent views are coded and tested stand alone and then combined with other views to create an application.
Validate
Value
Variable
Virtual
View
546
Glossary
Terms Window
Definitions An area of an image designated for data output. A window is formatted to accept one of three data types (ASCII, Numeric, or Date). Data is validated based on the format given to the window. They are addressed by reference to the name of the image of which they are a component, and their sequential position in that image (i.e., move body.2 to body.6, copies the contents of the second window in the image called body to the sixth window of the image called body). The sequence is established by numbering the windows on each line from left to right, moving from the top to the bottom lines of the image. See also Current Image; Current Window; Image. 1) The DataFlex language has always used this to refer to an area of the screen with visible boundaries through which information is displayed. A window can be smaller than or equal in size to the screen. 2) A choice in the menu bar of multiple-document interface applications. See also Image. A system of numbering which uses zero as the first number (starts with 0). For example, the numbering of all items in objects is zero-based. This means that the first item in an object is always Item 0, not Item 1.
Window
Zero-Based
547
Glossary
548
Evaluation
Visual DataFlex Class & Manual
Students completing a class, please fill out both parts A and B. Students using the manual as a Self taught course, please answer only part B. When complete, simply pull this page out, fold on dotted line, tape where indicated, stamp, and drop in the mail. Part A: Date: Location: Instructor: ________________________ ________________________ ________________________ ____
Please rate the following on a scale from 1 to 10 (10 being the best) Class overall? Instructor? Training manual? Handouts and other training media? ____ ____ ____ ____
Additional Comments: _______________________________________________________________________ _______________________________________________________________________ _______________________________________________________________________ _______________________________________________ Training Manual errors: Page Number ___________ ___________ ___________ ___________ Discrepancy _______________________________________________ _______________________________________________ _______________________________________________ _______________________________________________
Data Access Worldwide Training Dept. 14000 S.W. 119 Avenue Miami, FL USA 33186-6017
-------------------------------------------------------------
tape here