Testing Projects and Components

Any Visual DataFlex component you create must be added to a project before it can be compiled, run, tested and deployed. Often when building an application your actual project or projects may be quite large. You can add new and changed components to these projects and test them as part of the large project and there will be times when you will need to do this. However, often you will want to test the component in a smaller test project. These test projects are easier to work with and do a better job of testing the component in a more standalone context.

This section describes how you will go about creating test projects.

While we will be referring to test projects, keep in mind that there is actually no such thing as “a test project”. A test project is just a project that gets used for test purposes. If your project is small enough your test project may be your actual project. If you use test projects, you may have a single test project or you may have many test projects, each one customized to handle a specific need. Your test projects may be used to test a single component (e.g. a view) or they may be used to test multiple components (e.g. views and reports). The components within a test project may end being entirely maintained by Workspace Explorer or you may wish to directly modify the contents of your test project. You may end up creating a test project from a template and using it without any modifications or your testing needs may require significant alterations.

Windows Projects versus Web Projects

Most of the discussion of test projects applies to windows projects. You are only allowed to create a single Web project per workspace and that project must be named “WebApp.src”. Therefore with a Web project, your main project and your test project are one and the same.

Creating New Projects

After you have created a workspace one of the first things you will want to do is create one or more projects. If you are creating a Web Project you must create that project and set things up so your project can be used over the Internet. If you will be creating Windows projects, you will probably want to first create a test project. If you know what other types of Windows projects you wish to create, you may create them at this point. More realistically you will create these additional windows projects as needed. Creating new projects is very easy.

The Test Windows Project

The Projects page in the Create New dialog contains a project choice called “Test Windows Project”. This is similar to the regular “Windows Project” but it has some extra features that are specially designed for testing windows components. Those are:

  • All components listed in the Views and Report menus are automatically activated upon startup. This assumes that you wish to test these and therefore you want them to be activated.

  • The size of the test panel is adjusted so that the view and report components fit.

  • Any resizing and locating view options are not saved and restored. When testing views you want them to appear as you designed them.

  • The Data Dictionary Debugger view is added to the project. This allows you to see the status of the DDOs within your views by pressing Ctrl+D.

In addition, the code for all of these testing extras is coded directly in to the test project source. This makes it easy for you to remove, alter and expand these features, as your testing needs require.

Adding New Components to a Project

Some components can be automatically added to a project. With windows projects, newly created views and reports are automatically added to a windows project. With web projects, newly created Web Browser Objects and Web Service Objects are automatically added to your Web project.

When these types of components are created they are always added to your current project. This lets you do something useful with your component after you’ve created it (i.e., you can compile, run and test it). Therefore, an appropriate project must be created and defined as “current” before you attempt to create one of these components.

If you are creating a Web component, you must first create and select the Web project. If you are creating a Windows component, you must first create and select a Windows project. If you are using a test project, which is encouraged, this means that you will want to make a test project your current project before or while creating a new windows component.

The Studio will make sure you are doing the right thing. For example, it will not allow you add a view to a Web project and it will not allow you to add a web object to a Windows project. The Create New dialog also makes it very easy for you to select an appropriate project for the appropriate component.

Some component types are not automatically added to a project. In these cases the project or, more likely, some other component will contain the code to handle the use of these components. For example, a modal dialog component used in a Windows project must be added to a project by the developer. Even though these components are not directly added to a project you will still be asked to select a project and the Studio will still check that the component type is appropriate for the project type. For example, you can never add a Windows dialog component to a Web project and you would never create an ASP or HTML page for a windows project. However, some components, such as a class, may be used in either type of project or both.

Adding and Removing Existing Components to and from a Project

A component, assuming it is of the proper type, can be easily added to the current project. Simply load the component, right click in the editor view or designer view and select the “Add component to project” option. You may also add multiple components to a project by right clicking on the project in Workspace Explorer and selecting “Add Components”.

A component can be removed from a project by selecting the appropriate context menu option within Workspace Explorer.

The Testing Process

A typical testing process may proceed as follows:

  1. Create your Test Windows Project. You may only do this once when you create your workspace.

  2. Create a new View with either a wizard or a template. Select your Test Project as the target project. Upon completion your component will be added to the project.

  3. Make any custom changes you need to your component. Set breakpoints as needed.

  4. Compile and run the test project.

  5. Debug your project as needed

  6. Fix any errors and go back to Step 3. It is expected that Steps 3 – 5 will be repeated many times. When you finally have things “right” go to step 7.

  7. You might want to add this component to your main project. If this is the case:

  • Change projects and select your main project

  • Add the component to the project, compile, run and test.

  • If you did your testing properly this will all work.

You may now wish to create and test another component. Repeat Steps 2 – 6 as needed. If you follow these exact steps, your test project would now contain two components: the older tested one and the one you just created. You might find that having both components is useful for testing in which case you would leave things as is. If you wish to remove the older component, click on Workspace Explorer and remove it.

Again it is worth noting that this describes the simplest method for testing projects and components. It is expected that developers will want to use this as a starting point. Some of the more advanced development strategies might include:

  • Load a test project and customize it any way you like.

  • You may wish to include your own class libraries and precompiled sections directly in your test project. In this scenario, your test project structure will probably look very similar to your actual project.

  • You can add additional debugging features to the project.

  • You can create your own test component templates so that any test component that gets created is customized to your needs.

  • If you add this component to a library all workspaces using this library will have access to the component.

  • You can test as many components as you wish within a single test project

  • You can create multiple test projects, each customized to handle a special need.

  • You can use a test project to test components that are not automatically added to the projects menu. For example, you could test a modal dialog by adding the dialog and creating a procedure that calls it. Place a breakpoint in the procedure and you are all set.

See Also

General Reference


Accelerator Keys

Accelerator-key definitions should be placed within the construct_object procedure to define new key functions and override inherited definitions. By default, all the non-private key definitions for the superclass are automatically inherited by the class being defined.

  • Assignments of the Accelerator-Key-Message Names

  • Names of the Physical Keys

See Also

General Reference


Assignments of the Accelerator-Key-Message Names

The standard DataFlex message names for accelerator-key functions are assigned to keyboard keys as shown below. In your programs, you can assign these names to other keyboard keys simply by using the physical keyname as shown in the list that follows the table below. For example, say you wanted to make Ctrl+P the key for prompts. The following statement would do so:

on_key key_ctrl+key_p send Prompt

If you wished to use the F4 key assigned to this function by default for something else, you could do so with the following statement:

on_key key_f4 send something_else

KACTION_BAR | F10
KADD_MODE | SHIFT+F10
KBACK_SPACE | Backspace
KBEGIN_OF_DATA | Ctrl+Home
KBEGIN_OF_LINE | Home
KBEGIN_OF_PANEL | Ctrl+up arrow
KCANCEL | Esc
KCLEAR | F5
KCLEAR_ALL | Ctrl+F5
KCLOSE_PANEL | Ctrl+F4
KCOPY | Ctrl+C
KCUT | Alt+V
KDELETE_CHARACTER | Delete
KDELETE_RECORD | Shift+F2
KDOWNARROW | down arrow
KEND_OF_DATA | Ctrl+End
KEND_OF_LINE | End
KEND_OF_PANEL | Ctrl+down arrow
KENTER | Enter
KERASE_END_OF_LINE | Ctrl+Backspace
KEXIT_APPLICATION | Alt+F4
KEXIT_FUNCTION | F3
KFIND | F9
KFIND_NEXT | F8
KFIND_PREVIOUS | F7
KHELP | F1
KINSERT | Insert
KLEFTARROW | left arrow
KNEXT_ITEM | Tab
KPASTE | Ctrl+V
KPREVIOUS_ITEM | Shift+Tab
KPRINT_SCREEN | Shift+F4
KPROMPT | F4
KREFRESH_SCREEN | Shift+F5
KRIGHTARROW | right arrow
KSAVE_RECORD | F2
KSCROLL_BACK | Page Up
KSCROLL_FORWARD | Page Down
KSUPER_FIND | Ctrl+F9
KSUPER_FIND_NEXT | Shift+F8
KSUPER_FIND_PREVIOUS | Shift+F7
KSWITCH | F6
KSWITCH_BACK | Shift+F6
KUPARROW | up arrow
KWORD_LEFT | Ctrl+left arrow
KWORD_RIGHT | Ctrl+right arrow
KZOOM | Alt+F9

See Also

Accelerator Keys


Names of the Physical Keys

KEY_ALT | KEY_SHIFT | KEY_CTRL
KEY_ENTER | KEY_TAB | KEY_BACK_SPACE
KEY_ESCAPE | KEY_UP_ARROW | KEY_DOWN_ARROW
KEY_LEFT_ARROW | KEY_RIGHT_ARROW | KEY_HOME
KEY_END | KEY_PGUP | KEY_PGDN
KEY_INSERT | KEY_DELETE | KEY_F1
KEY_F2 | KEY_F3 | KEY_F4
KEY_F5 | KEY_F6 | KEY_F7
KEY_F8 | KEY_F9 | KEY_F10
KEY_F11 | KEY_F12 | KEY_0
KEY_1 | KEY_2 | KEY_3
KEY_4 | KEY_5 | KEY_6
KEY_7 | KEY_8 | KEY_9
KEY_A | KEY_B | KEY_C
KEY_D | KEY_E | KEY_F
KEY_G | KEY_H | KEY_I
KEY_J | KEY_K | KEY_L
KEY_M | KEY_N | KEY_O
KEY_P | KEY_Q | KEY_R
KEY_S | KEY_T | KEY_U
KEY_V | KEY_W | KEY_X
KEY_Y | KEY_Z |

See Also

Accelerator Keys


Activating Views on Start-up

Normally, a program starts up with all views inactive. Users select the view or views they wish to work with by selecting an option from the view menu bar. If you wish, you may customize a program so that one or more views will appear automatically when the program is started.

To auto-activate a view, you should:

  1. Find the activate access method for the desired view. 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.

Send Activate_Customer_Entry of (oClientArea(oMain))

This assumes that your main program has been created by the Studio and the main outer panel object’s name is oMain and its child client-area object’s name is oClientArea.

You can auto-activate as many views as you wish using this method. The last view activated will be the view that starts with the focus.

See Also

General Reference


Monitoring Batch Processes

Of Special Note

See Status Panel Changes for a discussion on the improvements made to the Status Panel in Visual DataFlex 12.0.

A batch process is a process that is run to completion without any user interaction after it is launched. Typical examples of batch processes are reports and end-of-month updates. During a batch process, users usually will wish to monitor the status of the process and be able to interrupt and possibly cancel the process at any time. A special package (StatPnl.pkg) provides a predefined object, Status_Panel, to automate this process. While the status panel is very easy to deploy, it must be used properly. Usage of the status panel actually starts a second DataFlex process (program) that runs concurrently with the monitored (batch) process. These two processes must communicate properly.

The status panel will create and pop up a modal dialog that contains the following different areas:

  • Caption bar: This is the text that is displayed in the caption bar (e.g., Running Process)

  • Title area: This is an area below the caption bar that contains text for a title (e.g., End-of-Month Update).

  • Message area: This is another area, situated below the title area, that may be used to display message text (Archiving All Orders). This is often blank.

  • Status area: This should show the extent and rate of progress. This should change on a regular-enough basis for users to know that the update is progressing (e.g., Processing Order: 12343 Dated: 1/1/2006).

  • Cancel button: Optionally, a single button is created that may be selected to stop the process. By default it contains the text Cancel.

Normally text for the caption bar, title area, message area, and cancel button are defined once when the status panel is invoked at the start of the batch process. As the process proceeds, the process will continually update the status area and check to see if the cancel button has been pressed. The status panel is removed when the process is complete or if the process is canceled.

See Also

General Reference


The Status Panel in Reports and BusinessProcesses

If your batch process is handled by a report (BasicReport) or a business-process (BusinessProcess) object, status-panel support is already built into the class. In these classes, you initialize the status panel by setting several properties: report_caption, report_title, report_message for reports, or process_caption, process_title, process_message for business processes. You update a status value by sending the message update_status passing the status text to display. The object automatically checks for an interrupt (user presses the Cancel button), provided the allow_cancel_state property is set true. If an interrupt is encountered, a dialog will appear allowing the user to resume or cancel the process. Also, special provisions are made to handle errors that occur during the process.

This section will show you how to create a status panel for other batch processes where this capability is not already built in.

See Also

Using the Status Panel

Monitoring Batch Processes


Using the Status Panel

First you must include the status-panel class and object in your program. You should do this by adding the following command to the top of your program (following the use DfAllEnt.pkg):

Use StatPnl.pkg

This creates a global object named Status_Panel. All messages must be directed to this object. There is also a global handle that contains the object ID of this status panel. This variable, ghoStatusPanel can be used in place of the object name Status_Panel. This provides a cleaner more robust interface.

  • Initializing and Starting the Status Panel

  • Updating Status-Panel Activity

  • Checking for an Interrupt

  • Removing the Status Panel

  • Handling Errors in Batch Processes

  • Putting It All Together

See Also

Monitoring Batch Processes


Initializing and Starting the Status Panel

The caption, title, and message areas are initialized by sending the message Initialize_StatusPanel passing these three text strings.

Send Initialize_StatusPanel of ghoStatusPanel ;

"Running batch Process" ; // the caption

"Processing all Orders" ; // the title

"" // Message area (none in this sample)

Alternatively, these three text values may be set individually by setting the properties Caption_Text, Title_Text, and Message_Text.

Set Caption_Text of ghoStatusPanel to "Running batch Process"

Set Title_Text of ghoStatusPanel to "Processing all Orders"

Set Message_Text of ghoStatusPanel to ""

You can also change the label of the button to a value other than Cancel by setting the Button_Text property.

Set Button_Text of ghoStatusPanel to "Halt"

The status panel is invoked by sending the message Start_StatusPanel.

Send Start_StatusPanel of ghoStatusPanel

See Also

Using the Status Panel


Updating Status-Panel Activity

Once displayed, the status panel’s status area is updated by receiving the message Update_StatusPanel passing the status text to display.

Send Update_StatusPanel of ghoStatusPanel Customer.Name

Send Update_StatusPanel of ghoStatusPanel ;

( String(Order.Number) + ": " + String(Order.Date) )

You can also change the status text by setting the property Action_Text. Once the status panel is active, changes in any of the text-area properties (Caption_Text, Title_Text, Message_Text, Action_Text and Button_Text) will immediately appear on the status panel.

See Also

Using the Status Panel


Checking for an Interrupt

You may check to see if the Cancel button has been pressed with the function Check_StatusPanel. If it returns a non-zero value, the button has been pressed.

Get Check_StatusPanel of ghoStatusPanel to bStopIt

If bStopIt ... end process

If the Allow_Cancel_State property is false, the Cancel button is not displayed, and the process cannot be interrupted by users. This property is true by default in business-process objects, and false in report objects.

See Also

Using the Status Panel


Removing the Status Panel

The status panel is removed by receiving the message Stop_StatusPanel.

Send Stop_StatusPanel of ghoStatusPanel

When a process is complete, you must remember to remove the status panel. There are other times as well when you must remove the status panel.

It is very important that you always remove the status panel before attempting to perform any user input in the underlying process.

If you wish to respond to the cancel button by asking if the process should be stopped, you must first remove the status panel (send Stop_StatusPanel), and then ask the verification question. If the process should continue, the status panel must again be displayed (send Start_StatusPanel).

The other time when user input might be "unexpectedly" required is during an error. The normal DataFlex error handler pops up an error message box. This is usually not a desired occurrence in any batch process, and a method for controlling this is presented in the next section.

See Also

Using the Status Panel


Handling Errors in Batch Processes

First, we must understand how the error handler works in DataFlex. A global Integer named error_object_id determines which object should receive errors. Anytime an error occurs, the message error_report is sent to the object identified by this global Integer. When the standard error package, Dferror.Pkg (which is included in DfAllEnt.pkg), is used, a global error object is created and its object ID is moved to error_object_id. Anytime an error occurs, the message error_report is sent to the error object. You can turn any object into an error-handling object by creating an error_report procedure and moving its object ID to error_report_object.

Normally, when a DataFlex error is directed to the global error object, the object will display an interactive error message and allow users to proceed (unless, of course, the error is fatal). You usually need more control of errors during a batch process. The best way to do this is to redirect the errors to an object that handles batch errors in a customized fashion. The easiest way to do this is to direct the errors to the object that is running the batch process. This is what the report object does automatically. Not only does this allow handling of the status panel (which must be removed if the error is to be displayed), but it also allows users to decide how to handle the error.

This redirection could be done in the following fashion:

Object Process is a SomeClass

Property Integer piOldErrorId

Procedure Run_Batch_Process

integer iId

Set piOldErrorId to Error_Object_Id // remember old error object

Move Self to Error_Object_Id // make Self the error object

Repeat

:……run the batch process

Until (done)

Get piOldErrorId to iId

Move iId to Error_Object_Id // restore original error object

End_Procedure

Procedure Error_Report integer iErrorNumber integer iErrorLine string sErrorText

: handle custom error here

End_Procedure

End_Object

Here would be one way to handle errors with a status panel:

Procedure Error_Report integer iErrorNumber integer iErrorLine string sErrorText

Integer iId

Send Stop_StatusPanel of ghoStatusPanel // remove panel for error

// direct error to standard error handler

Get piOldErrorId to iId

Send Error_Report of iId iErrorNumber iErrorLine sErrorText

Send Start_StatusPanel of ghoStatusPanel // put panel back

End_Procedure

See Also

Using the Status Panel


Putting It All Together

This sample shows how a simple batch process might be created. In this example, we find all records and change the value of a single field. This process would be run by sending the message Run_Batch_Process to the object.

If an error occurs, we want the process to stop. If a user presses the Cancel button, we want to verify the cancel and possibly stop the process. Note that we always shut off the status panel before getting any user input. In this case, we must temporarily remove the status panel anytime an error occurs or the cancel button is pressed.

// at top of program

Use StatPnl.pkg // creates object: Status_Panel (can be accessed via global handle ghoStatusPanel)

:

Object Process is a SomeClass

Property Handle phOldErrorId // keep track of old (global) error object

Property Boolean pbErrorFound // set true means error occurs during process

Function Check_Stop_Process returns Boolean

handle hStatId // use this to keep ID of Status_Panel

Boolean bStopIt

Move ghoStatusPanel to hStatId // object ID of status panel

Get Check_StatusPanel of hStatId to bStopIt // check for user interrupt (cancel button)

If (bStopIt) Begin

// if we are to display a warning we must first shut off

// the status panel.

Send Stop_StatusPanel of hStatId

Get Confirm "Continue Process" to bStopIt

// if we did not stop the process we must restart the status panel

If Not (bStopIt) ;

Send Start_StatusPanel of hStatId

End

Function_Return bStopIt

End_Function

Procedure Run_Batch_Process

handle hErrorId

handle hStatId // use this to keep ID of Status_Panel

Boolean bStopIt

Set ErrorFound to False // this will get set T if an error occurs

Set OldErrorId to Error_Object_Id // remember old error object

Move Self to Error_Object_Id // make self the error object

Move ghoStatusPanel to hStatId // object ID of status panel

Send Initialize_StatusPanel of hStatId "Run Process" "Changing Field" ""

Send Start_StatusPanel of hStatId

Clear Vendor

Repeat

Find Gt Vendor.Id

If not (Found) Break

Send Update_StatusPanel og StatId Vendor.Id

Move "X" to Vendor.Marker

SaveRecord Vendor

Get ErrorFound to bStopIt // if error occurred, we quit.

If (bStopIt) Break

Get Check_Stop_Process to bStopIt // if true, user canceled the process

If (bStopIt) ;

Break

Loop

Send Stop_StatusPanel of hStatId

Get OldErrorId to hErrorId

Move hErrorId to Error_Object_Id // restore original error object

End_Procedure

Procedure Error_Report integer iErrorNumber integer iErrorLine string sErrorText

handle hErrorId

Send Stop_StatusPanel of ghoStatusPanel // remove panel for error

// direct error to standard error handler

Get phOldErrorId to hErrorId

Send Error_Report of hErrorId iErrorNumber iErrorLine sErrorText

Set pbErrorFound to True // indicate that an error has occurred

End_Procedure

End_Object

If a developer wishes to create a custom panel, he/she should use cProcessStatusPanel.pkg as a template. This panel can be visually modeled and changed any way you wish. Just save your new custom panel with a different file and object name and direct your status panel request to the new object.

If the new panel changes the interface and updates objects that are not currently defined, you want to make sure you send the message ProcessEvents after you've updated the object. This allows the object to paint when inside of a tight loop. For example, if you wanted to add a progress bar (cProgressBar) you would want to Send ProcessEvents after you update the progress bar.

e.g.

Procedure UpdateStatusBar

Send DoAdvance of oProgressBar

Send ProcessEvents

End_Procedure

Of course, if you use the standard interfaces in status bar and your forward send these messages this will be done for you.

See Also

Using the Status Panel


Shadowing

Shadowing refers to the process of making an object or an item unavailable for data entry. Usually the appearance of a shadowed object/item is changed in some way to indicate its unavailability. Two types of shadowing are supported: object shadowing and item shadowing .

When an object is shadowed, that object and its children are shadowed, overriding the inherent shadowed state of all such objects. This process recurses through all descendant generations of objects. When an object is not shadowed, the inherent shadowed states of its children take effect. Object shadowing is supported in all classes, including both control and container classes.

Item shadowing refers to the process of shadowing individual items within an object. This is used only with objects that support multiple items (lists, grids, menus, ToolBars, StatusBars).

  • Object Shadowing

  • Item Shadowing

  • The Complete Public Interface

  • Special Shadow-State Conditions

  • Visual Shadowing of TextBoxes and Labels

See Also

General Reference


Object Shadowing

An object may be shadowed inherently or contextually. An object is inherently shadowed when its own shadow state has been set to true. An object is contextually shadowed when one of its ancestors’ shadow states has been set to true. In this latter situation, the object’s inherent shadow state is of no effect, but the value of the property remains (latently) present in the object.

The primary interface for object shadowing consists of these messages.

Set enabled_state to True | False

This sets the object’s explicit shadow state. When this property is false, whether the object will actually be shadowed is a function of this property and the state of its ancestors’ enabled_state.

Get enabled_state to variable

This returns whether an object is shadowed, whether explicitly or implicitly.

Example: In the following example, the checkbox will determine if the radio-group object should be shadowed. When selected, the checkbox will send a message to its sibling radio-group object, passing a parameter to it indicating if the radio (and all of its children) should be shadowed.

Object MyContainer is a Container3d

Set Size to 80 80

Set Location to 10 10

Object MyCheckbox is a CheckBox

Set Location to 10 10

Set Label to "Disable Radios"

Procedure OnClick

integer iSelState

Get Select_State to SelState

Register_Object oMyRad

Send Disable to oMyRad iSelState

End_procedure

End_Object

Object MyRad is a RadioGroup

Set Label to "My Radio Group"

Set Size to 50 50

Set Location to 25 10

Object R1 is a Radio

Set Location to 10 10

Set Label to "Option 1"

End_Object

Object R2 is a Radio

Set Location to 25 10

Set Label to "Option 2"

End_Object

Procedure Disable integer iSelState

Set enabled_state to (not(iSelState))

End_Procedure

End_Object

End_Object

See Also

Shadowing


Item Shadowing

Item shadowing is supported by these messages:

Set Item_Shadow_State item Item_num to true | false

This sets the shadow state for a single item.

Get Item_Shadow_State item Item_num to variable

This retrieves the shadow state of a single item. Note that the object’s shadow state takes precedence over the item’s shadow state. If the object is shadowed, users will not be able to enter the item.

See Also

Shadowing


The Complete Public Interface

The messages listed in Object Shadowing and Item Shadowing will handle almost all of your interface needs. This section provides additional messages that may be required for more-advanced usage. Below is a list of the complete public object and item-shadowing interface

Enabled_state — boolean — true |false

Sets the object’s inherent shadow state. When this property is set, the object and all of its descendants are notified of the change as required. Changing this property will not affect the object’s actual shadowed state if an ancestor’s enabled_state is false.

Get enabled_state ascertains whether an object is actually shadowed regardless of whether inherently or contextually. If false, the object is shadowed and all of its descendants are shadowed (they cannot be entered). If true, the object is not shadowed (it is enterable) and none of its descendants is contextually shadowed by this object.

Note that the Get and Set versions of the enabled_state message are not true mirrors of each other. While this may seem illogical, it is designed to generate fewer programming errors. Most often, a program will explicitly set an object’s shadow state (set enabled_state), but will need to know whether an object is enterable (get enabled_state) regardless of how it got that way. If you need to know if an object’s shadow state has been explicitly set, you will need to query the explicit_shadow_state property. Get explicit_shadow_state is the true converse of set enabled_state.

Explicit_Shadow_State — boolean — true | false

This returns the object’s inherent shadow state. If true, this object’s shadow state has been explicitly set with a set enabled_state message. If false, it has not been set explicitly. When false, this property does not tell you whether the object is actually shadowed. This property should not be set.

Implicit_Shadow_State — boolean — true | false

This indicates if an object is contextually shadowed by an ancestor. This property should not be set.

The properties implicit_shadow_state, explicit_shadow_state and enabled_state interact in the following manner:

Explicit_shadow_state | Implicit_Shadow_State | Enabled_State
True | True | False
True | False | False
False | True | False
False | False | True

Shadow_Display — procedure

This procedure is called whenever a change in shadow state occurs, or when an object is paged. It is used to properly set the display to reflect an enterable or non-enterable object. By default, this sets visual attributes that are consistent with enabled and non-enabled objects in Windows. You may use this to set other custom conditions. This message should be forwarded and it is meant to be used as part of object shadowing and not item shadowing.

When augmenting this procedure, you may access the current shadow condition of the object by querying the enabled_state property and in more-unusual conditions, the implicit_shadow_state and explicit_shadow_state properties.

Item_Shadow_State item_num — boolean — true | false

This is used to set and get the shadow state of a single item. This is not needed in single-item objects, for which the state of the object is applicable.

Shadow_State [item_num] — boolean — true | false

The shadow_state property is provided primarily for legacy purposes. In prior revisions of DataFlex for Windows, it was used at times for object shadowing and at times for item shadowing. Because of this dual purpose, its use will always be somewhat confusing. It is probably easier to choose to not use this property at all and to use the properties enabled_state and item_shadow_state instead. Therefore, you are encouraged not to use get/set shadow_state in your programs.

Shadow_state has been configured to do the most-logical thing based on the class of the object. If an object is not multi-item, shadow_state works the opposite of enabled_state. If the object is multi-item, the property works the same as item_shadow_state.

In single and no-item objects (non-multi-item), the following pairs are equivalent:

Set Shadow_State to True -- Set enabled_state to false

If (Shadow_State(Self, 0)).. -- If(Object_Shadow_State(Self))..

Note that when using shadow_state in an expression, an item number must be passed.

This pair is inversely related:

Get Shadow_State to var -- Get enabled_state to var

In multi-item objects, the following are equivalent:

Set Shadow_State 3 to True -- Set Item_Shadow_State 3 to True

Get Shadow_State 4 to state -- Get Item_Shadow_State 3 to state

If (Shadow_State(Self, 5)).. -- If(Item_Shadow_State(Self, 5))..

See Also

Shadowing


Special Shadow-State Conditions

Tab Dialog and Tab Dialog Pages

Tab dialogs have items, so they support both the object and the item-shadowing mechanisms. You can shadow any tab button by setting its Item_Shadow_state property. When shadowed, the button will appear shadowed and users will be unable to select that button and therefore unable to see the shadowed-tab page.

Normally, you will not wish to set the Item_Shadow_state in the tab dialog. Instead, you will want to set this property inside the tab page. A special property named Button_Shadow_state supports this capability.

Tab pages actually support two types of shadowing: button shadowing and object shadowing. They provide different functionalities:

Enabled_state

If this property is set false in a tab page, users will be allowed to navigate to the page and see its contents. They will not be able to navigate into the page. The focus will remain on the tab button.

Object MyTabDialog is a TabDialog

Set Location to 10 10

Set Size to 100 100

Object My1stPage is a TabPage

:

End_Object

Object My2ndPage is a TabPage

Set Enabled_State to false // can view but not enter

:

End_Object

End_Object

Button_Shadow_State:

If this property is set true in a tab page, both the page and the button will be shadowed, making it impossible to ever display the shadowed tab page.

Object MyTabDialog is a TabDialog

Set Location to 10 10

Set Size to 100 100

Object My1stPage is a TabPage

:

End_Object

Object My2ndPage is a TabPage

Set Button_Shadow_State to true // cannot view or enter

:

End_Object

End_Object

See Also

Shadowing


Visual Shadowing of TextBoxes and Labels

When a container is shadowed, that object and all of its descendants will display in the appropriate shadowed format. Form and edit areas will change to the gray disabled color, and buttons and groups will be shadowed. This is all automatic and is handled by shadow_display.

When a TextBox appears within a shadowed container or when a label’s entry object is shadowed, it is less clear how the TextBox should appear. The text can either be shadowed or it can be left unaltered. The default behavior is as follows:

  • When a TextBox is inherently shadowed or when a label’s entry object (like a dbForm) is inherently shadowed, the text display is not altered.

  • When a TextBox or a label is contextually shadowed by a container parent (like a group), the text display is shadowed.

The following examples should make this clear.

Object oMyGroup is a Group

Set Location to 10 10

Set Size to 100 200

Set Label to "My Group"

Object oMyForm is a Form

Set Location to 10 70

Set Size to 13 50

Set Label to "My Label" // form will be gray, label text will be normal

Set enabled_state to false

End_Object

Object oMyTextbox is a TextBox

Set Location to 10 140

Set Label to "Additional Label" // text will be normal

End_Object

End_Object

In this example, the label will not be shadowed, but the form will appear with the gray disabled color.

Object oMyGroup is a Group

Set Location to 10 10

Set Size to 100 200

Set Label to "My Group"

Set enabled_state to false

Object oMyForm is a Form

Set Location to 10 70

Set Size to 13 50

Set Label to "My Label" // form will be gray, label text will be shadowed.

Set enabled_state to false // doesn’t matter what this is

End_Object

Object oMyTextbox is a TextBox

Set Location to 10 140

Set Label to "Additional Label" // text will be shadowed.

End_Object

End_Object

In this example, the label will also appear shadowed because it is shadowed by its container. If the shadow_state was reset to false in the group object, the label would again appear normal but the form would remain gray (because it is still shadowed).

This behavior can be modified with the property Label_Shadow_Display Mode. This determines how text is shadowed in a textbox or label. The values for this property are:

  • TBSHADOW_ON_GROUP Visually shadow text if object is contextually shadowed (by ancestor). This is the default value.

  • TBSHADOW_ON_NONE Never visually shadow the text.

  • TBSHADOW_ON_LOCAL Visually shadow text if object is inherently shadowed.

  • TBSHADOW_ON_ALL Visually shadow text whenever the object is shadowed.

In the following example, the label will never display shadowed text.

Object oMyGroup is a Group

Set Location to 10 10

Set Size to 100 200

Set Label to "My Group"

Set enabled_state to false

Object oMyForm is a Form

Set Location to 10 70

Set Size to 13 50

Set Label_Shadow_Display_Mode to TBSHADOW_ON_NONE

Set Label to "My Label" // form will be gray, label text will be normal

End_Object

Object oMyTextbox is a TextBox

Set Location to 10 140

Set Label_Shadow_Display_Mode to TBSHADOW_ON_NONE

Set Label to "Additional Label" // text will be normal

End_Object

End_Object

See Also

Shadowing


Understanding RGB Colors

The term RGB is an acronym for Red, Green, Blue– the three primary colors used to create a composite color.

Any color you specify will be made up of various intensities of red, green and blue. So, for example, red would be made of high intensity red with no green or blue; black would have no red, green or blue; and white would have full intensity red, green and blue. The intensity of each color ranges from 0 (no intensity) to 255 (full intensity).

The Visual DataFlex color scheme supports both physical and logical colors known as Standard and System, respectively.

  • Standard Colors

  • System Colors

  • Color Anomalies

  • The RGBColorSystem Class

See Also

General Reference


Standard Colors

When you set the color of an object to a Standard—or physical—Color, you will supply an RGB color and the closest approximation to that color will be displayed (dependent upon graphic-card capabilities). Here is the list of symbols you can use:

clAqua | clMaroon
clBlack | clNavy
clBlue | clOlive
clDkGray | clPurple
ClFuchsia | clRed
clGray | clSilver
clGreen | clTeal
clLime | clWhite
clLtGray | ClYellow

See Also

Understanding RGB Colors


System Colors

System—or logical—Colors differ to Standard Colors in that the actual RGB color is determined from the settings on the machine.

So, for instance, if you wanted a dbForm to have the same background color as other Windows controls that accepted user-input, you would set the color to clWindow. This color is usually white, but by setting it to clWindow, the color will automatically change whenever the user changes the colors on their machine. If you had set it to the clWhite Standard Color, it would always appear white, regardless of the colors configured on the machine.

All the System Colors have symbols representing their usage. Use clWindow when you want to use the color known as "Window" in the Windows configuration; similarly, clWindowText maps to "Window Text" and clBtnFace maps to "Button Face" – which is the color used by Windows for all 3-d objects.

Here is the list of symbols you can use:

clScrollBar | ClHighlight
clBackground | ClHighlightText
clActiveCaption | ClBtnFace
clInactiveCaption | ClBtnShadow
clMenu | ClGrayText
clWindow | ClBtnText
clWindowFrame | ClInactiveCaptionText
clMenuText | ClBtnHighlight
clWindowText | cl3dDkShadow
clCaptionText | cl3dLight
clActiveBorder | ClInfoText
clInactiveBorder | ClInfoBk
clAppWorkSpace |

See Also

Understanding RGB Colors


Color Anomalies

Checkbox

The Checkbox control contains a square area where the check mark is displayed. This area is not colored with the Color property, but by the "Window" System Color defined on the target machine. The Color property will color the remaining background of the control.

Radio

The Radio control contains a circular area where the radio mark is displayed. This area is not colored with the Color property, but by the "Window" System Color defined on the target machine. The Color property will color the remaining background of the control.

ComboForm

In ComboForms, colors behave differently depending upon the value of the Entry_State property.

If this property is False (meaning the user must select a value from the list), the color of the form and the text in it are as expected. If the property is True, the color of the form and its text are defined by the Windows System Color for "Window" and "WindowText" respectively.

In both cases, the drop-down list element of the control also uses the colors defined by the Windows configuration.

Button

You cannot change the color of a button at all. The color is determined by the System Color clBtnFace for the background and clBtnText for the label.

TabDialog

You cannot change the color of a TabDialog at all. The color is determined by the System Color clBtnFace for the background and clBtnText for the labels. However, you can set the background color of each of the pages using the Color property; but you should do this with caution, as it will probably not look right, especially if the user changes their System Colors.

See Also

Understanding RGB Colors


The RGBColorSystem Class

The RGBColorSystem (RGBColor.pkg) converts RGB colors values to their respective color-name etc. This class is used in the Studio to display the colors; you can use this class to provide a list to populate a comboform or popup-menu etc. Consult the source-code for this class to see the interface. The following sample code demonstrates its usage:

Use DFAllEnt.pkg

Use RgbColor.pkg

Object oRGBColorSystem is a RGBColorSystem

// Create an instance, to receive the colors

End_Object

Class cColorCombo is a ComboForm

Procedure Construct_Object

Forward Send Construct_Object

Set Size To 100 100

Set Entry_State 0 To False

End_Procedure

Procedure OnAddColor String sColorName Integer iColorId

// This event is received once for each color to add

Send Combo_Add_Item sColorName

End_Procedure

Procedure OnChange

Integer iColor

String sColor

Get Value 0 To sColor

// Now convert the name to its color-id

Get ColorNameToColorId of oRGBColorSystem sColor To iColor

Set Color To iColor

End_Procedure

End_Class

Object oPanel is a Panel

Set Size To 100 270

Set Label To 'Using the RGB Color System'

Object oStandard_cc is a cColorCombo

Set Location To 10 100

Set Label To 'Standard:'

// Now enumerate the colors. This sends the OnAddColor

// message to the current object (defined in the

// class) passing a symbol representing the style

// of colors that are required.

Send DoEnumColorNames of oRGBColorSystem msg_OnAddColor Self csStandard

End_Object

Object oSystem_cc is a cColorCombo

Set Location To 30 100

Set Label To 'System:'

Send DoEnumColorNames of oRGBColorSystem msg_OnAddColor Self csSystem

End_Object

Object oAllColors_cc is a cColorCombo

Set Location To 50 100

Set Label To 'All Colors:'

// You may want to set the Combo_Sort_State

// property to False to stop automatic sorting.

Send DoEnumColorNames of oRGBColorSystem msg_OnAddColor Self csAnyStyle

End_Object

End_Object

Start_Ui

See Also

Understanding RGB Colors


User Confirmations and Queries

Most of the time, your program runs in a non-modal state. Users may choose to navigate and enter data in the order of their choosing.

There are times when you need the program to stop this user-driven system, pop up a dialog panel, ask a question, and based on the answer, take an action. There are several ways to create and use modal popup objects.

If you need to ask a (Yes/No" question, you should use the Confirm package, which is documented in this section. If you require a different response (e.g., Yes/No/Cancel), or you need a series of responses, you could use the message box, or you could create your own modal panel. Both of these techniques are discussed later in this section.

  • The Confirm Function

  • Confirming Data Entry Operations

  • Using the Confirm Package

  • Using Message Boxes

  • Modal and Non-Modal Operations

  • Creating a Modal Popup Object

See Also

General Reference


The Confirm Function

The confirm function can be used to pop up a "Yes/No" confirmation. When called, it pops up a Windows Yes/No message box. The message-box caption will be Confirm and it will present the passed question, allowing users to select the Yes or No button. The syntax for using the function is as follows:

Get Confirm QuestionString to bReturnValue

Argument Explanation

QuestionString The question to be presented.

ReturnValue 0 if response is Yes, 1 if response is No

This can be used at any point in your program and provides a very easy method to ask a "Yes/No" question. For example:

Procedure Run_Report

Boolean bFail

Get Confirm "Print Aged Balance Report Now?" to bFail

If not (bFail) ;

Send Start_Report of oAgedReport

End_Procedure

The confirm package is defined in the DFConFrm.pkg and is automatically included in DFAllEnt.pkg. You do not need to explicitly "use" it. This means that confirm and message box support are "built right in there" as a resource.

See Also

User Confirmations and Queries


Confirming Data Entry Operations

Sending Confirmations Automatically

DEOs send confirmation messages during important data-entry operations (saves, deletes, clears, exiting). This gives the program a chance to secure confirmation of critical operations from users. Each DEO class has properties that determine what confirmation message is sent for each of these operations.

These messages are usually functions. If the function returns a zero value, the confirmation passed. If it returns a non-zero value, the confirmation failed.

You can use these confirmation functions to pop up a confirmation dialog box asking a particular question (e.g., Save this Record?). The popup confirmation is a standard windows message box which allows the user to respond by pressing Yes or No. After a response, the confirmation panel will disappear and the function will return a zero (yes) or non-zero (no) value according to the response from the operator.

The DFConfrm.pkg package creates objects to provide such capabilities. It also creates a number of functions that allow you to use these objects. This includes a general-purpose confirmation function (where you pass the question to be asked) and a series of pre-defined confirmation functions.

A DEO needs to know what verification message it should send during a save, delete, clear and exit. Each DEO has properties that contain the message number to be sent for the appropriate verification. These verification properties are verify_save_msg, verify_delete_msg, verify_data_loss_msg and verify_exit_msg.

If the values of one of these properties is zero, the DEO will delegate and use the message definition in its parent DEO. If the parent's property value is zero (and all of its DEO ancestors are also zero), no message will be sent.

All you need to do is to assign the appropriate function messages in DFConfrm.pkg to the appropriate DEO-verify message. The function messages available are listed below.

Save_Confirmation

Prompts: Save this Record?

DEO usage:

Set Verify_Save_Msg to GET_Save_Confirmation

This will most often be used with entry forms and editors that are children of entry forms. Note that when you set the confirmation messages, you need to add the GET_ prefix. Had the function been a procedure, you would have needed the MSG_ prefix.

Delete_Confirmation

Prompts: Delete this Record?

DEO usage:

Set Verify_Delete_Msg to GET_Delete_Confirmation

This will most often be used with entry forms and editors that are children of entry forms.

Line_Save_Confirmation

Prompts: Save this Line?

DEO usage:

Set Verify_Save_Msg to GET_Line_Save_Confirmation

This would be used with grids and editors that are children of grids.

Line_Delete_Confirmation

Prompts: Delete this Line?

DEO usage:

Set Verify_Delete_Msg to GET_Line_Delete_Confirmation

This would be used with grids and editors that are children of grids.

Data_Loss_Confirmation

Prompts: Abandon Changes?

DEO usage:

Set Verify_Data_Loss_Msg to GET_Data_Loss_Confirmation

This message only gets sent when a clear or clear all would result in the loss of data.

Exit_Loss_Confirmation

Prompts: Changes Exist. Exit this window?

DEO usage:

Set verify_exit_msg to GET_Exit_Loss_Confirmation

This message is sent whenever you close (deactivate) a DEO view and there are changes in the view.

No_Confirmation

DEO usage:

Set Verify_operation_Msg to GET_No_Confirmation

Defeats delegation to parent. If a confirmation function is not assigned to a DEO's verify property, the DEO will use the message from its parent DEO. For example, a text_edit DEO will use the same verifications that its parent entry form uses.

Normally, this is good. The no_confirmation message tells the DEO to not use a confirmation prompt and not to use its parent's prompt. This is often needed with the parent-entry-form / child-grid-DEO structure. You want a save confirmation for the entry form and no confirmation for the grid. If you don't assign the grid a verify_save_msg, it will use its parent's entry-form message. You must set the grid's verify message to GET_No_Confirmation.

Sending Confirmations Manually

You can send confirmation messages manually. This is useful if you need to send these messages under conditions that your DEO does not normally handle. Below is an example of directly calling a DEO function.

In this example, we want the standard save message (Save this Record?) to only be sent when a new record is saved. When an edited record is saved, we want the save to proceed without confirmation. We would augment the DEO's request_save procedure to handle this.

// This assumes that this DEO's Verify_Save_Msg is set to no_confirmation.

//

Procedure Request_Save

Integer iRec iServer

Boolean bStat bChanged

// get current record in server. If 0, it is new.

Get Server to iServer // the DDO we are using

Get Current_Record of iServer to iRec

Get Should_Save to bChanged // is the DDO changed?

// if a new record and there are changes confirm the save.

If (iRec=0 AND bChanged) Begin

Get Save_Confirmation to Stat // OK=0

If (bStat) ;

Procedure_Return // non-zero=TRUE=not OK, exit

End

// Normal save will not perform a confirmation

forward send Request_Save

End_Procedure

The Confirm Function with DEOs

You can send custom confirmation prompts by using the confirm function. It requires that you pass it the prompt to be displayed. The following example shows how you could use the confirm function to make the above example prompt, Save this NEW record?

Procedure Request_Save

Integer iRec iServer

Boolean bStat bChanged

Get Server to iServer

Get Current_Record of iServer to iRec

Get Should_Save to bChanged

If (iRec=0 AND bChanged) Begin

Get Confirm "Save this NEW record?" to bStat // OK=0

If (bStat) ;

Procedure_Return // non-zero=TRUE=not OK, exit

End

Forward Send Request_Save

End_Procedure

You can also use the confirm message to create custom confirmations for a DEO or new confirmations for all DEOs. If we wanted to change an entry form's save prompt to Save this Order?, we would augment the verify_save procedure in the entry-form object:

Set verify_save_msg to GET_Verify_Save // normal save hook

// Create custom Verify_Save for this ONE object.

Function Verify_Save Returns integer

Boolean bResponse

Get confirm "Save this Order?" to bResponse

function_return bResponse

// Here is an alternative method that would combine the above

// three commands into a single command.

//

// function_return (Confirm(Self, "Save this Order?"))

//

End_Function

When we create a verify_save function in a DEO, we are changing the behavior of the one DEO. We could also use confirm to create a new confirm message that all objects could use. We would do this by creating the new function FOR BaseClass (which really means for all classes). We would then assign a DEO's verify message to that new function. The following would allow us to create a "California-style" save message:

Function Verify_Save_California_Style FOR BasClass returns Integer

Boolean bNoWayDude

Get Confirm "Save this record, Dude?" to bNoWayDude

function_return bNoWayDude

End_Function

Your DEO would use this prompt by placing the following in your DEO:

Set Verify_Save_msg to GET_Verify_Save_California_Style

See Also

User Confirmations and Queries


Using the Confirm Package

It is very easy to hook DEOs into confirmation messages. Your program must first include the DfConfrm object package (which is included, by default, in DFAllent.pkg). Each DEO should contain code that looks like the following:

Set Verify_Save_Msg to GET_Save_Confirmation

Set Verify_Delete_Msg to GET_Delete_Confirmation

Set Verify_Data_Loss_Msg to GET_Data_loss_Confirmation

Set Verify_Exit_Msg to GET_Exit_loss_Confirmation

By default the dbView class defines the above confirmations as their default. The dbGrid class changes the save confirmation (to disable the confirmation -get_no_confirmation) and the delete confirmation (to ask for a line delete confirmation -get_line_delete_confirmation). You would only need to change a class or object if you needed to change these defaults.

You are encouraged to create your own confirm package. This could contain different or additional prompts. You might also want to create your own custom DEO subclasses that contain the prompts that you always want to appear in your programs.

The following example would create a custom dbView subclass that always verifies saves, deletes, and clears, but does not verify, exits:

Class dbView_xyz is a dbView

Procedure construct_object

forward send construct_object

Set Verify_Save_Msg to GET_Save_Confirmation

Set Verify_Delete_Msg to GET_Delete_Confirmation

Set Verify_Data_Loss_Msg to GET_Data_loss_Confirmation

Set Verify_Exit_Msg to GET_No_Confirmation

end_procedure

end_class

When your confirm logic is placed in subclasses that all objects use, your programs will no longer need to set the properties in each DEO and you will be assured that all of your DEOs will behave consistently. This will also make it very easy to add more-sophisticated verification capabilities to all of your objects. It shouldn't be too hard to create classes that allow confirmations to be turned on and off at the user level.

See Also

User Confirmations and Queries


Using Message Boxes

The message box is a Windows DLL that is used by all Windows programs to present simple pop-up messages and to ask simple pop-up questions. You may access this functionality at a variety of levels.

If you need to ask a standard "Yes/No" question, it is simplest to use the confirm function (e.g., get confirm "Are you sure?" to RetVal). The use of the confirm function is documented in the Confirming Data Entry Operations topic.

The next level consists of a number of messages that access the most-commonly needed message-box functions.

A final level allows you to access the message box at the Windows level. This requires that you understand the Windows message-box DLL interface.

For more information refer to Dialog and Message Box Functions.

See Also

User Confirmations and Queries


Modal and non-Modal Operations

User-interface objects may be modal or non-modal. An object that is non-modal will allow users to interact with other objects outside the object without first having to complete the operation within the object. If an object is modal, users are required to complete all interaction within the object before exiting the object.

Whenever possible, objects should be non-modal. The nature of an event-driven system and the nature of mouse navigation encourage the use of non-modal objects. In an event-driven system, users determine the order of events. In a modal environment, the program determines the order of events.

Upon occasion, an object must be modal. Modal objects are usually popup objects. Based on some event (e.g., a user presses the save key), a modal object will appear asking a question or a series of questions (e.g., Save this record?). Upon completion, the modal object is removed. The program (as opposed to the user) then decides what action to take. Non-modal implies user-driven; modal implies program-driven. Note that while most modal objects will be popup objects, not all popup objects will be modal.

In a DataFlex program (or any event-driven program), the program's user-interface mode will be non-modal most of the time. This user-interface mode is started by executing the Start_UI command, which starts the UI event processor. Events can be key events, mouse events, or timer events. The program runs in this UI mode until the program is completed. The last line of most DataFlex programs is a Start_UI command. This starts the UI event processing, which will continue until the program terminates.

Upon occasion, a modal user-interface event will need to occur on top of this modeless operation.

The purpose of the next section, Creating a Modal Popup Object, is to describe how to handle modal popup objects. This was created to answer the commonly asked question, "While I know how to create complex event-driven views, I do not know how to perform the simple task of popping up a dialog box, asking a question (or questions) and continuing my program based on this response. How do I this?" This problem could be generalized as, "How do I perform a modal task in a modeless environment?" The solution to this will be presented in an incremental, tutorial fashion.

If we start with the modal object, we will start in the wrong place. Instead, we must start with the task. You want to perform a task and, based on the outcome of the task, perform some other task. This will be a modal task. Until the task is completed, nothing else should happen. A modal task is program-driven and not user-driven.

See Also

User Confirmations and Queries


Creating a Modal Popup Object

Here is the approach for designing and creating a modal task. First you define the problem and design an interface to perform the task. Let's say that we need to know if it is proper to accept overtime hours. Our interface might look like the following:

Object Name: overtime

Function:    ApproveOvertime returns Boolean

Return: True if approved, False if denied

This is all we need to know to use this object in our program. The procedure initiating the modal task would look like the following:

Procedure Process_Hours number iTotalHours

Boolean bResponse

Number nOTHours

If (iTotalHours > 40) Begin

Get ApproveOvertime of oOvertime to bResponse

If (bResponse) ;

move (iTotalHours 40) to nOTHours // hours approved

else ;

move 0 to nOTHours // hours not approved

move 40 to iTotalHours

end

send EnterHours iTotalHours nOTHours

End_Procedure

At this point, we only worry about the interface. We have an object named overtime that understands the message ApproveOvertime. It will perform a task and return a result. At this level, this is all we need to know. We do not even know if the task involves user interaction or not. This is the responsibility of the task object. That level of detail should be hidden from the rest of the program (it is encapsulated).

We will look at three completely different methods of handling the task. These are all valid and completely interchangeable.

Option 1: Non-user-interface - Return an answer based on existing data.

Object oOvertime is a cObject // use a simple class

// Do not allow if employee.ot_type = "S" (salaried)

Function ApproveOvertime returns Boolean

if (Employee.ot_type = "S") ;

function_return False

else ;

function_return True

End_Function

End_Object

Option 2: Pass the buck chain wait to another program which may or may not perform a UI task. If it is a UI task, it will be modal since a chain waited program cannot interact with its parent program. This method is not necessarily recommended. It is included because this is a method that procedural DataFlex developers use all the time.

Object Overtime is a cObject

Function ApproveOvertime returns Boolean

chain_wait "ot_pgm" export_files

// use some time-honored procedural trick to figure out what happened

// in the chain -waited program and return a status_value.

function_return status_value

End_Function

End_Object

Option 3: Require user input - We will now need to create and use a modal popup object. To do this, we must do the following:

  1. Make sure the object is a modal-popup object. This is simple—we should base the object on the modalPanel or dbModalPanel class.

  2. Pop up the object. We send the message popup to do this.

  3. When finished with the object, send close_panel.

  4. Figure out what happened and return a status value.

You could do this as follows:

Object Overtime is a ModalPanel

// we use this to track the return value

Property Boolean pbOvertimeOk

Set Label to "Allow Overtime?"

Set size to .. ..

// note that modal panels will locate automatically

// Let's assume that OT_is_Good and OT_is_Bad should complete the popup

Procedure AcceptOk

Set pbOvertimeOk to True // mark this property as OK

send Close_Panel // and close the pane

End_Procedure

Object oOTButton is a Button

Set Location to .. ..

Set Label to "OT is OK"

Procedure OnClick

Delegate Send AcceptOk // we define this message

End_Procedure

End_Object

Object oNoOTButton is a Button

Set Location to .. ..

Set Label to "No OT"

Procedure OnClick

Delegate Send Close_Panel // this is understood by ModalPanel

End_Procedure

End_Object

Function ApproveOvertime returns integer

Boolean bResponse

Set pbOvertimeOk to False // set a default value of no OT

Send Popup // This may change pbOvertimeOk

Get pbOvertimeOk to bResponse

Function_Return bResponse

End_Function

End_Object

This example presents the suggested structure for all modal pop-up objects. Please note the following

  • If the object is modal (based on ModalPanel, dbModalPanel, or the property Modal_State is set to true) the object is invoked when it is sent the message popup.

  • Whenever possible, do not send the popup message from outside of the object. Instead create a public message that performs the desired task. In this sample, our task was not to pop up a modal object; our task was to determine if overtime was allowed. An interface should reflect an object’s purpose, not its function.

  • A modal panel is closed by sending the message close_panel . This message is also sent automatically by other operations like clicking on the Close button in the panel’s upper right hand corner.

The best way to determine what happened within a modal panel is to have object data (i.e. a property) which can be inspected after the popup is complete. In this sample, we created a status property which was initialized to 0 upon start-up and is only set to 1 if the Ok button is selected.

Finally, notice that this was designed starting with the interface. The object that started this (invoked the prompt) is not responsible for any of this. It simply asks an object a question through an agreed-upon interface. It has no idea how the response will be generated. It is asking a question of a black box.

If you design your interface first and then worry about implementation, everything becomes much easier.

See Also

User Confirmations and Queries


Language Translation Guide

The purpose of language translation is to make it possible to compile and run an end-user application in the language of choice.

As you will see, selecting your application deployment language requires a number of steps, including running the application on a computer that is running the appropriate regional version of windows. For this reason we expect the selection of a language to be a fairly static process. Once you have configured your computer and Visual DataFlex for a particular language we do not expect you to change it. Anytime you do change it, you will need to follow the steps listed here.

Please note that these changes affect the applications you write. They do not affect the Visual DataFlex tools and the documentation you use to build your applications. Those tools remain in English.

This topic is divided into two sections:

  • Selecting Your Language from a list of already selected languages. This assumes that all of the language translations have already been made and you just need to use those translations. This section will also deal with some of the translation issues that you may face with your own application.

  • Creating or Updating a Language deals with the steps required to add a new language to Visual DataFlex. This involves creating and translating a number of files. If the language you need is not supported, you will need to start here. We list this second in the hope that most of you will find your language of choice and be able to skip this entire section.

See Also

General Reference


Selecting Your Language

This section will use the symbol <language> to represent the name of the language you are selecting.

First, you need to determine if your language is currently supported. The best way to do that is to open the file in your pkg directory named LanguageText.pkg. The top of the file will list all supported languages and should contain something like the following:

Enumeration_list

define Language$English

define Language$Nederlands

define Language$Svenska

define Language$Deutsch

End_Enumeration_list

If your language is not supported, you need to go to the next section, add the language, then come back here.

If your language is supported, you should have a set of files in a directory created for your language. We will refer to that as your “language directory”. Let’s assume that those files are located in usr\language\<Language>. You will need to copy files from this directory into various other directories.

Run the Correct Regional Version of Windows

Some of the text provided in your application comes from windows. The message boxes (used for errors, confirmations, etc.), the open file dialogs, and much more get their language text from windows. When you run your application you will want to run it on the proper version of windows or your translation will be mixed.

Installing Your Error files

  1. First make sure you make a copy of all error data files in your \usr directory to some other safe location. Copy flexerrs.dat and dferr???.dat.

  2. Copy all error files from the language directory into your \usr directory. You will want to copy flexerrs.dat and dferr???.dat

  3. If you are not using a custom version of flexerrs, you are done.

  4. If you are using a custom version of flexerrs, you are going to need to make sure that your custom errors are properly merged into the translated file. Some developers maintain a single customized flexerrs in \usr while other may maintain custom flexerrs in each workspace. If you have customized files you must make sure they are up to date.

Installing Your Collate File

If your language requires a special df_collate.cfg you will want to install this into your bin directory and then re-sort all your databases.

  1. Make sure you have copied the current df_collate.cfg in \bin to a safe location.

  2. Copy the df_collate.cfg from your language directory to the \bin directory. You must make sure that this file resides in your bin directory and that no copies of it exist in any other path that can be found with dfpath.

  3. Resort all database files including abData and ddData.

Any time you install a new df_collate.cfg you will need to re-sort all your data files. Most of these files can be sorted within Database Builder by selecting the desired workspace and sorting.

Note: Earlier versions of DataFlex used a file named collate.cfg. The proper file name is now df_collate.cfg.

Installing Your Text Language Files

Important Note: The above steps must be run on any system running your application. The following steps of installing language text files must be run on your development machine. This makes sure that your compiled application will contain text in the appropriate language.

  1. Your language directory should contain a number of .inc and .pkg files that need to be copied to your \pkg directory. These all have unique names so you should not have to worry about copying over files from a different language. These files may already be copied into your \pkg directory. If they are not, copy them.

Here is list of files that must be installed in your pkg directory

  • Language_<Language>.inc

  • Language_DD_<Language>.inc

  • Language_Winprint_<Language>.inc

  • WinPrintViewer_<Language>.ini

  • Language_WebApp_<Language>.inc

  • DefaultToolbar_<Language>.pkg

  • DfStdBtn_<Language>.pkg

  • File_pm_<Language>.inc

  • Help_pm_<Language>.inc

  • Helpa_pm_<Language>.inc

  • Navi_pm_<Language>.inc

  • Win_pm_<Language>.inc

  2. The files MDIApplication.tpl and TestWindowsProject.tpl contain the default menu items and include files. If the translated files are not already in your \Pkg\Config directory, you should copy those from your language directory to your \Pkg\Config directory. Note that in this case, the MDIApplication.tpl and TestWindowsProject.tpl files in your \Pkg\Config directory will be overwritten.

  3. The file Language_Current.inc defines which language you are currently using. This file can be located in the \pkg directory can be loaded within the Studio and changed. Simply change the define command to use your language. This is what Language_Current.inc might looks like:

// define current language (see LanguageText.pkg for a list

// of supported languages).

// to change current language.

// 1. Check LanguageText.pkg for the list of supported languages.

// 2. Change code below to one of the selected languages

// 3. Precompile ALL packages

Define Language$Current for Language$Nederlands

  4. Pre-compile all packages.

A Note on the Text Translation Files

The files Language_<Language>.inc, Language_winprint_<Language>.inc and Language_DD_<Language>.inc contain a list of all text used by our packages. Our packages now use text symbols (e.g. C_$Cancel) instead of text (e.g. “Cancel”). These include files provides the translation (e.g. #replace C_$Cancel “Cancel”). This makes it easy to provide text for various languages.

When you write your programs we do not expect that you will need to use these kinds of symbols in your application. You would only need to do that if you are writing an application or set of packages that needs to be multi-lingual. Therefore, you will not need to change the way you are writing your applications.

You will note that we have not used this same text/symbol substitution method on the files that contain menu objects and tool bar objects (e.g. File_pm_Svenska.inc, DefaultToolbar_Svenska.pkg). In those files we are actually translating the text directly in the code. We did it this way because these are just samples. We expect you to create your own menus and toolbars using these as starting points. If we had created these packages using text symbols we would be providing you with bad, hard-to-read samples. As you alter these files you will want to be using normal in-place strings and not replacement symbols.

You are now done.

See Also

Language Translation Guide


Creating or Updating a Language

If your language is not yet supported or you need to changes to an update you need to read this section.

It is our intention that most developers will not need to make these changes or, therefore, need to read this section. Translations, at this level, will be made by DAW partners. We will then make these translation files available on our web site to all developers.

To make Visual DataFlex ready for a different language you will need to:

  • Create a df_Collate.cfg with the correct collating order of your language

  • Convert the database error files to your language

  • Convert the include files which contain all text used in the packages

  • Convert any tool bar, status bar and menus that you use that might contain text

  • Convert template files to contain the desired menu items and include files

  • Register your language in LanguageText.pkg

Here is a list of all files that you need to change:

1. The collate file must be created for your language

  • Df_collate.cfg

2. These error files must be translated

  • flexerrs.dat

  • dferr001.dat

2. This file must be updated with new language names

  • LanguageText.pkg

3. These files must be renamed and translated

  • Language_English.inc

  • Language_DD_English.inc

  • Language_Winprint_English.inc

  • DefaultToolbar.pkg

  • DfStdBtn.pkg

  • File_pm.inc

  • Help_pm.inc

  • Helpa_pm.inc

  • Navi_pm.inc

  • Win_pm.inc

  4. These files must be translated and have their #include and use commands adjusted

  • MDIApplication.tpl

  • TestWindowsProject.tpl

Hopefully you will not need to create all these files. In many cases you will updating these files from a previous version. If this is the case, you will just be updating the changes – a fast process.

These steps are described below in detail.

Create your df_collate.cfg file

Your translation language may or may not require a special collate config file. If a special collating sequence is not required, you may skip this step and not include a collate file in your language directory.

If a special collating sequence is required you will need to create a file named df_collate.cfg and place it in your language directory. The method for creating such a file has not changed so the chances are good that you already have this file. Previous versions of Visual DataFlex gave this file a different name, collate.cfg. The proper name is now df_collate.cfg.

A section at the end of this document titled, “More Information on Creating a Collate File” describes the process for creating the df_collate.cfg file.

The same collate file name, df_collate.cfg is used for different languages. As you rename, move and copy this file, be careful. We suggest that you keep copies of this and translated files in a separate language directory. For example, you may wish to keep files in directories named ..\usr\language\<Language>. You will not actually open these files from this directory.

When you have finished working on this file you should copy them back to your language directory.

Convert the database error files to your language of choice

Visual DataFlex contains several error files that contain the text for all errors. You will want to convert the text to the language of your choice. Since all versions of Visual DataFlex use the same named error files (flexerrs.dat, dferr001.dat, dferr002.dat. etc.) you need to make sure that your program finds the correct version of those files. Normally, those files are found in the \Usr directory.

The same error file names must be used for different languages. As you rename, move and copy these files, be careful. We suggest that you keep copies of all of your translated error files in a separate language directory. For example, you may wish to keep files in directories named ..\Usr\Language\<Language>. You will not actually open these files from this directory.

So, we suggest that you take the current error data files in the \Usr directory and store them somewhere safe. If you have partially translated error files, copy them in to \Usr and start with them. If you do not have partially translated files, use the current files.

You can use Visual DataFlex’s Error Maintenance Utility to view and edit error text.

As you translate, you will notice that these errors messages are limited to 40 characters. We recognize that this can make translation difficult - just do the best you can with this.

Errors may change with any revision. Be sure to check for changes with each new revision and add or change any translations as needed

Convert include files which contain all text used in the packages

You will need to translate the following text include files:

Language_<Language>.inc

Language_DD_<Language>.inc

Language_Winprint_<Language>.inc

As you change the text, note that the parameters (%1, %2, etc.) may be moved around and used however you wish. Also note that you can change the length of the messages to any length required (limit is actually 1024).

These files can be created and maintained in the \pkg directory (as there is no naming conflict with existing files). When finished, you should copy these to your language directory

Convert any tool bar, status bar and menus that you use that might contain text

Normally developers customize tool-bars, status bars and menus. To do this, they usually use our menu, toolbar and status bar packages as starting points. Therefore we want to translate these files so they can be used as examples. However, we do not want to use the text substitution method we used with our class packages as this would be very hard to read and would provide a bad model for developers to follow. Therefore we need translate all text directly in the standard toolbars and menus. We need to translate the following files.

DefaultToolbar.pkg Our Basic Toolbar sample

DfStdBtn.pkg Older Toolbar sample (replaced by DefaultToolbar.pkg)

File_pm.inc File menu

Help_pm.inc Help menu without “about” option

Helpa_pm.inc Help menu with “about” option.

Navi_pm.inc Navigation Menu

Win_pm.inc Windows menus

Note that our standard status bar, DefaultStatusbar.pkg does not require translation

We suggest you use the same file name convention used in the other files. Append the “_<Language>” to these files when you translate them.

For example, DefaultToolbar.pkg would be named DefaultToolbar_Deutsch.pkg.

These files can be created and maintained in the \pkg directory (as there is no naming conflict with existing files). When finished, you should copy these to your language directory.

You can use any kind of tool you wish to aid in the translation of these files. Keep in mind that there are very few text files and it is quite easy and fast to work with these within a text editor.

Here is some advice:

The first time you do this translation you should make copies of the original files, renaming them as required. Load these into an OEM editor (the Studio works well) and translate the text. Try it. This is a fast process.

If you are translating an update (e.g. 8.3) the process is even simpler. We suggest you take the standard (English) files from your new and previous versions and do a file compare. That will generate a list of every line that has changed. We expect that list will be small. Now, load your previous revision translated file and make the changes as needed.

Warning: Remember that all of this text has to be stored in OEM format. Not all editors support OEM. For example, editing these files within notepad will not give you the desired results. If you edit these files within the Studio, it will always be correct.

Convert template files to contain the desired menu items and include files

The two templates used to create new Windows projects (MDIApplication.tpl) and new Windows Test projects (TestWindowsProject.tpl) contain the menu structure of a typical MDI application.

You will need to copy those files from \Pkg\Config into your language directory and translate them, also replacing the included and used files with the name of the files you translated.

The typical code in the English version of those files is

DFCreate_Menu Main_Menu

#INCLUDE File_pm.inc

DFCreate_Menu "&View" ViewPopupMenu is a ViewPopupMenu

End_Pull_Down

Set Status_Help To "Available Views"

DFCreate_Menu "&Report" ReportPopupMenu is a ViewPopupMenu

End_Pull_Down

Set Status_Help To "Available Reports"

#INCLUDE Navi_pm.inc

#INCLUDE Win_pm.inc

#INCLUDE Helpa_pm.inc

End_Menu // Main_Menu

Use DefaultToolbar.pkg // Tool-Bar object.

Object oClientArea is a ClientArea

End_Object // oClientArea

Use DefaultStatusbar.pkg // Status-Bar object.

The above code will need to be adjusted to the desired language in the two template.

Register your language in LanguageText.pkg

You must make sure that your language is supported within LanguageText.pkg. Once defined, you can then select this language or any other supported language by changing the language selection package named Language_Current.pkg.

LanguageText.pkg defines all supported languages and is used to include the appropriate language text in your application. Here is what a typical file will look like:

// Package.pkg

// Generic Language include file.

// List all languages supported

Enumeration_list

define Language$English

define Language$Nederlands

define Language$Svenska

define Language$Deutsch

End_Enumeration_list

#Include Language_Current.inc // this will define Language$Current

#IFSAME Language$Current Language$English

#Include Language_English.inc

#ENDIF

#IFSAME Language$Current Language$Nederlands

#Include Language_Nederlands.inc

#ENDIF

#IFSAME Language$Current Language$Svenska

#Include Language_Svenska.inc

#ENDIF

#IFSAME Language$Current Language$Deutsch

#Include Language_Deutsch.inc

#ENDIF

Notice that this uses the convention of defining a language name with the line

Define Language$<Language>

Then defining all language files names as FileName_<Language>.

These files can be created and maintained in the \pkg directory (as there is no naming conflict with existing files). When finished, you should copy these to your language directory.

You are done.

More Information on Creating a Collate File

DataFlex’s collation sequence governs the creation and updating of indexes to database files and the sequencing of entries in various lists, including a number of the utilities. It also governs relative evaluation (greater than, less than) of strings. The file df_collate.cfg controls the precedence of characters for collation both for DataFlex utilities and for programs being run under the runtime system.

Serious disruption, including damage to data, can occur as a result of uninformed or malicious tampering with df_collate.cfg, which is a plain text file. If your system permits protecting the file in any way from being edited or deleted, you should employ such means immediately.

Df_collate.cfg defines collating precedence by the order in which it "mentions," or covers, each character in the character set you are using. If you use DataFlex in a language other than English, or have special collation requirements of any kind, you may wish to check and modify df_collate.cfg for your specific requirements. If you ever base indexes on characters in the extended ascii range (above 127), check the collation sequence carefully, even if your work is done exclusively in English. If you change df_collate.cfg, any database files that were created using a different collation sequence must be reindexed completely before any further use. If this step is not taken, searching the database will be disrupted immediately, and updates to indexes for additions, deletions, and edits will also occur incorrectly, making the searching problem progressively worse.

We strongly recommend that if you modify df_collate.cfg, you: (a) keep a backup copy of df_collate.cfg in a different directory; (b) add comments to the file indicating the nature, time, and authorship of the changes; and (c) test the resultant collation sequence carefully using a test program and data before it is used with any data that is in actual use.

Df_collate.cfg is a plain text file, and may be edited with any text editor. Every non-blank line of it must begin either with one of the three keywords or with a double slash (//), which may be followed by a comment. The keywords, which must be capitalized, are

  • Single, for specifying the precedence of a single character by use of its ASCII code in decimal. For example, SINGLE 32 refers to the space character.

  • Range, for specifying the precedence of a range of characters by use of their ASCII codes in decimal, separated by a space. For example, RANGE 0 31 refers to the characters from ASCII 0 to ASCII 31, the control characters. Characters within a RANGE will be collated in the order of their ASCII codes.

  • Text, for specifying the precedence of characters by use of the characters themselves, embedded in quotation marks. For example, TEXT "AaBbCc" refers to the first three letters of the alphabet in both upper and lower cases. Characters in a TEXT statement will be collated in the order in which they are listed between the quotation marks, and may not include any "white space" characters (space, tab, etc.).

All command lines may be used as many times as desired, and should be intermingled so as to be in the order in which you desire the ranges and characters to be collated. Every character in your character set must be specified, and no character may be referred to twice throughout the file. Spaces should not be used except after keywords and between the bounds of a range. Errors of this kind in df_collate.cfg can seriously impair use of databases, and any changed df_collate.cfg should be tested thoroughly before it is placed into actual use.

This is df_collate.cfg the way Data Access Worldwide ships it with Visual DataFlex. As such, it is a definition of the DataFlex default collating sequence.

//

// Standard DataFlex Collate Table

//

// Control Characters

RANGE 0 31

// Special Characters

RANGE 32 47

RANGE 58 63

RANGE 91 96

RANGE 123 255

// Number

RANGE 48 57

// Alpha Characters

TEXT "@AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"

// Finished.

See Also

Language Translation Guide


Visual DataFlex Specifications

See Also: File Names & Extension Types, Logical Structure of a Database File, Visual DataFlex Data Types, Building Tables and Data Dictionaries

Features

  • Visual DataFlex Studio - advanced Integrated Development Environment, with many built-in classes and completely customizable components and subclasses.

  • Advanced source-level debugger.

  • Studio Code Explorer makes navigating, editing, and debugging programming code a breeze.

  • Integrated source-level debugger to help track down and fix problems.

  • Studio wizards for building numerous programming components, including applications, views, and importing ActiveX controls and consuming web services.

  • Database Builder for building database tables and reusable DataDictionaries.

  • Database Explorer for advanced raw table data viewing and editing.

  • Object-oriented 4th generation programming language (4GL).

  • Data Access Connectivity Kits for accessing different databases (e.g. ODBC-compliant databases, Microsoft SQl Server, IBM DB2, and Pervasive.SQl) from Visual DataFlex (automatically installed with Visual DataFlex).

Requirements

Please refer to the Installation and Environment Guide to ascertain the requirements for memory, disk space, and operating system version that apply to your version of Visual DataFlex.

Platforms

Supported platforms are Windows 2000, XP and Server 2003. Please refer to the Installation and Environment Guide for more details.

Structure

Extended relational DBMS with data-independent utilities and command language.

Connectivity Kits

Visual DataFlex supports access to numerous different database formats through Connectivity Kits. Connectivity Kits are available for IBM DB2, Microsoft SQL, Pervasive.SQL and ODBC connectivity. Data Access Connectivity Kits allow for seamless conversion to and from, as well as direct access to, various different database formats without recompilation of applications. With the exception of the ODBC, all Connectivity Kits are direct drivers from Visual DataFlex, and thus allow direct and fast access to the database.

Database Specifications (All Databases used with Visual DataFlex)

Maximum DBMS tables per filelist | 4095
Maximum filelists per application | Unlimited

Embedded (DataFlex) Database Record & Table Specifications

Maximum data elements (fields) per table | 255
Maximum characters in physical table name (root name) | 40
Maximum characters in addressable table name (DataFlex name) | 8
Maximum table file size | 2 Gigabytes (2,147,483,647 Bytes)
Maximum records per table | 16.7 Million (16,700,000)
Maximum record size | 16 Kilobytes (16,384 Bytes)
Data table type | Packed, fixed-length random access
Numeric storage formats | Packed BCD fixed point. Floating point
Numeric precision | Fixed point: 8 places after decimal point. Floating point: 16 significant digits. DECIMAL type adds 16.16 support.
Numeric range | Fixed: ±9,999,999,999,999,999. 9999999999999999 with DECIMAL type. Floating: ±1.0e±306

Embedded (DataFlex) Database Index Specifications

Maximum indexes per table | 15
Maximum segments per index | 16
Maximum index key length | 256 Bytes

Embedded (DataFlex) Database Field Specifications

Maximum characters in field name | 15
Maximum data element (field) size | 16 Kilobytes (16,384 Bytes)
Maximum size of ASCII field | 255 characters
Maximum size of text field | 16 Kilobytes (16,384 Bytes)
Size of date field | 3 Bytes (Fixed)
Maximum size of numeric field | 99,999,999,999,999.99999999 to -9,999,999,999,999.99999999 (14.8 places)
Maximum size of binary field | 16 Kilobytes (16,384 Bytes)

Application / Coding

Specifications for Visual DataFlex data types can be found in the Language Guide.

All of the below specifications are per application. Each Visual DataFlex application can call other applications (including other Visual DataFlex applications), and even return to the same place in the code after doing so using the runprogram command.

Maximum lines per program | 128 million (128,000,000)
Maximum line length in Code Editor | 255 characters
Maximum compilable statement length | 4095 characters (a statement exceeding 255 characters must be broken up into multiple lines of code, separated by a semicolon, which indicates a continuous statement ).
Maximum custom error message length | 2048 characters
Maximum number of devices that can be simultaneously opened for sequential file I/O | 10
Program file characteristics | Protected source, semi-compiled
Maximum number of objects | 2,147,483,647
Maximum object messages | 3,072
Maximum number of classes | 32,768
Maximum size of compiled program without symbols | 2 Gigabytes (2,147,483,647 Bytes)
Maximum data tables open concurrently | Memory limited only
Types of arguments | Text Strings Numeric fixed point Numeric floating point Integer Date (extended Julian)

Visual DataFlex Identifiers

Visual DataFlex identifiers must begin with a letter a-z or A-Z. This includes all identifiers in the language: variable names, class names, object names, table names, etc. (i.e. any name used in your program code).

Visual DataFlex Program File

When a Visual DataFlex application is compiled, a file with an .exe extension is created (e.g., MyApplication.exe). To execute a Visual DataFlex application, simply double-click on the .exe file in Windows Explorer.

Argument Size

Visual DataFlex has a global argument size, which controls the maximum size a local string variable and a text database field can be addressed in an application. The default argument size in Visual DataFlex is 64 Kilobytes. This is already larger than the maximum size of an embedded (DataFlex) database record, but if you are using non-DataFlex databases or accessing sequential files in your application, you may need to increase the argument size. The maximum possible argument size is 2,000,000 (2 million) bytes. For performance reasons, you should keep the argument size as low as is needed for your application.

You can use the get_Argument_Size command, to determine what the current argument size is and the set_Argument_Size command to increase the current argument size.

Example

Procedure DoAdjustArgumentSize

integer iArgSize

get_Argument_Size to iArgSize

if (iArgSize<131072) ;

set_Argument_Size 131072

End_Procedure // DoAdjustArgumentSize

This example increases the current argument size to 131072 if it is less than 131072 (128 Kilobytes).

See Also

General Reference


General Reference

  • Testing Projects and Components

  • Accelerator Keys

  • Activating Views on Startup

  • Monitoring Batch Processes

  • Shadowing

  • Understanding RGB Colors

  • User Confirmations and Queries

  • Language Translation Guide

  • Visual DataFlex Specifications