DVX BASIC IDE Guide

DVX BASIC is a Visual BASIC development environment for DVX. It provides a VB3-style integrated development environment with a code editor, form designer, project system, and a full interactive debugger -- all integrated into DVX itself.

This guide covers every feature of the IDE: menus, toolbar, editor, form designer, project management, debugger, and auxiliary windows.

IDE Windows

The DVX BASIC IDE is modeled after Visual Basic 3.0. It consists of several floating windows arranged on the DVX desktop:

The IDE compiles BASIC source into bytecode and runs it in an integrated virtual machine. Programs execute in cooperative slices, yielding to DVX between slices so the GUI remains responsive. Call DoEvents in long-running loops to keep the event loop flowing.

File Menu

Edit Menu

Run Menu

View Menu

Window Menu

Tools Menu

Help Menu

Toolbar

Code Editor

Form Designer

Project System

Properties Panel

Toolbox

Debugger

Locals Window

Call Stack Window

Watch Window

Breakpoints Window

Immediate Window

Output Window

Find / Replace

Preferences

Keyboard Shortcuts

File Menu

  Menu Item              Shortcut   Description
  ---------              --------   -----------
  New Project...                    Create a new DVX BASIC project.
  Open Project...                   Open an existing .dbp project file.
  Save Project                      Save the current project file to disk.
  Close Project                     Close the current project (prompts to save unsaved changes; Don't Save also discards unsaved Project Properties changes).
  ---
  Project Properties...             Edit project metadata (name, author, version, startup form, icon, etc.) and the command line arguments used when the program is run from the IDE.
  ---
  Add File...            Ctrl+O     Add a .bas, .frm or .cls file to the project. If no project is open, creates an implicit project from the file. A file that cannot be read, or is 64 KB or larger, is refused with a message.
  New Class Module                  Add a new, empty class module (Class1.cls, Class2.cls, ...) to the project and open it in the Code Editor. See Class Modules under Project System.
  Save File              Ctrl+S     Save the active file to disk.
  Save All                          Save all modified files in the project.
  ---
  Make Executable...                Compile the project and save it as a standalone .app file. Prompts for a debug or release build.
  ---
  Rename File...                    Give the file selected in the Project Explorer a new name, on disk and in the project. See Renaming a File under Project System.
  Remove File                       Remove the selected file from the project (prompts to save if modified).
  ---
  Exit                              Close the IDE (prompts to save unsaved changes).

A project (.dbp) or source file (.bas, .frm, .cls) named on the IDE's command line opens when the IDE starts, so double-clicking one in the File Manager, or starting it from the Program Manager, opens it in the IDE.

Files are saved exactly as edited (LF line endings). Each save writes a temporary file first and replaces the original only when the write succeeded. Opening a project that fails to load keeps the current project open and removes the failed entry from the Recent list.

Edit Menu

Back to Overview

Edit Menu

  Menu Item    Shortcut   Description
  ---------    --------   -----------
  Cut          Ctrl+X     Cut the selection (text, or the selected control in the form designer) to the clipboard.
  Copy         Ctrl+C     Copy the selection to the clipboard.
  Paste        Ctrl+V     Paste from the clipboard. A pasted control keeps all of its properties.
  ---
  Select All   Ctrl+A     Select all text in the active editor.
  ---
  Delete       Del        Delete the selected text, or the selected control and everything inside it (in the form designer).
  ---
  Find...      Ctrl+F     Open the Find/Replace dialog.
  Find Next    F3         Find the next occurrence of the search text (also after the dialog is closed).
  Replace...   Ctrl+H     Open the Find/Replace dialog with replace enabled.

Cut, Copy, Paste, Select All and Delete act on the window you last worked in: the form designer's selected control, or the text of the code, output or immediate window.

Run Menu

Back to Overview

Run Menu

  Menu Item                Shortcut         Description
  ---------                --------         -----------
  Run                      F5               Compile and run the program. If paused at a breakpoint, resumes execution with debugging disabled (runs free).
  Debug                    Shift+F5         Compile and run with the debugger active. Breakpoints are active but execution does not pause at the first statement. If paused, resumes to the next breakpoint.
  Run Without Recompile    Ctrl+F5          Re-run the last compiled module without recompiling.
  Stop                     Esc              Stop the running program. Run, Debug and the project commands stay disabled until the program has finished shutting down.
  ---
  Step Into                F8               Execute one statement, stepping into SUB/FUNCTION calls. If idle, starts a debug session and breaks at the first statement.
  Step Over                Shift+F8         Execute one statement, stepping over SUB/FUNCTION calls.
  Step Out                 Ctrl+Shift+F8    Run until the current SUB/FUNCTION returns.
  Run to Cursor            Ctrl+F8          Run until execution reaches the line where the cursor is positioned.
  ---
  Output Window to Log                      Checkbox: when enabled, PRINT output (each line once) and compile and runtime error reports are also written to the DVX log. Persisted in preferences.
  ---
  Toggle Breakpoint        F9               Toggle a breakpoint on the current editor line.
  ---
  Clear Output                              Clear the Output window.
  ---
  Save on Run                               Checkbox: when enabled, all modified files are saved automatically before compiling. Persisted in preferences.

View Menu

Back to Overview

View Menu

  Menu Item        Shortcut   Description
  ---------        --------   -----------
  Code             F7         Switch to Code view for the active file (or the file selected in the Project Explorer).
  Designer         Shift+F7   Switch to Design view for the active form file. With a module (.bas) active it reports that the file is not a form. The designer keeps its unsaved state while you work in a module.
  ---
  Toolbar                     Checkbox: show or hide the toolbar. Persisted in preferences.
  Status Bar                  Checkbox: show or hide the status bar. Persisted in preferences.
  ---
  Menu Editor...   Ctrl+E     Open the Menu Editor dialog for the active form (a form must be active). Allows designing menu bars with captions, names, levels, checked state, and enabled state. See Menu Editor below.

Window Menu

Back to Overview

Window Menu

  Menu Item          Description
  ---------          -----------
  Code Editor        Show or raise the Code Editor window.
  Output             Show or raise the Output window.
  Immediate          Show or raise the Immediate window.
  Locals             Show or raise the Locals debug window.
  Call Stack         Show or raise the Call Stack debug window.
  Watch              Show or raise the Watch debug window.
  Breakpoints        Show or raise the Breakpoints window.
  ---
  Project Explorer   Show or raise the Project Explorer window.
  Toolbox            Show or raise the Toolbox window.
  Properties         Show or raise the Properties panel.

Tools Menu

Back to Overview

Tools Menu

  Menu Item        Description
  ---------        -----------
  Preferences...   Open the Preferences dialog (editor settings and project defaults).
  ---
  Debug Layout     Checkbox: toggle a debug overlay that shows widget layout boundaries. Useful for diagnosing widget layout issues.

Help Menu

Back to Overview

Help Menu

  Menu Item            Shortcut   Description
  ---------            --------   -----------
  DVX BASIC Help       F1         Open the DVX BASIC help (language reference, IDE guide, and control reference).
  DVX API Reference               Open the DVX developer API reference.
  ---
  About DVX BASIC...              Show the About dialog with version and copyright information.

Back to Overview

Toolbar

The toolbar is organized into four groups separated by vertical dividers. Each button has a tooltip showing its name and keyboard shortcut.

File Group

  Button   Shortcut   Action
  ------   --------   ------
  Open     Ctrl+O     Add a file to the project (same as File > Add File).
  Save     Ctrl+S     Save the active file.

Run Group

  Button   Shortcut   Action
  ------   --------   ------
  Run      F5         Compile and run the program.
  Stop     Esc        Stop the running program.

Debug Group

  Button          Shortcut         Action
  ------          --------         ------
  Debug           Shift+F5         Start or resume a debug session.
  Step Into       F8               Step into the next statement.
  Step Over       Shift+F8         Step over the next statement.
  Step Out        Ctrl+Shift+F8    Step out of the current procedure.
  Run to Cursor   Ctrl+F8          Run to the cursor position.

View Group

  Button   Shortcut   Action
  ------   --------   ------
  Code     F7         Switch to Code view.
  Design   Shift+F7   Switch to Design view.

Back to Overview

Code Editor

The Code Editor is the primary editing window for BASIC source code. It occupies the center of the screen, below the toolbar and above the Output and Immediate windows.

Object and Function Dropdowns

At the top of the Code Editor are two dropdown lists:

A WithEvents variable (Dim WithEvents acct As Account, also Private or Public, in a module, a form or a class module) is listed as an object; its events are the ones its class module declares with Event. Picking one of them creates the handler acct_EventName with the event's own parameters, so it matches what the class raises. Selecting the variable when it has no handler yet creates the handler for the class's first event, as a control's default event is created.

The editor shows one procedure at a time. Each procedure has its own buffer, and switching between them is instantaneous. The (General) section contains module-level declarations and code.

Text outside the procedure being shown is never lost: lines typed above or below the SUB move to (General), a second SUB typed into the buffer becomes a procedure of its own, and a procedure whose SUB line was deleted becomes (General) text. When you leave an event handler that was generated and never edited it is removed; empty SUBs and FUNCTIONs you wrote yourself are kept. After a save the editor shows exactly what was stored (blank lines around a procedure are normalized). A section too large for the editor opens read-only, with a message in the status bar.

Syntax Highlighting

The editor applies real-time syntax coloring as you type. Seven categories are highlighted in distinct colors; the colors themselves are editable in Tools > Preferences > Colors.

  Category          Examples
  --------          --------
  Default Text      Identifiers, whitespace.
  Keywords          IF, THEN, FOR, NEXT, SUB, FUNCTION, DIM, PRINT, SELECT, CASE, DO, LOOP, WHILE, WEND, END, EXIT, CALL, GOSUB, GOTO, RETURN, DECLARE, CONST, TYPE, AND, OR, NOT, XOR, MOD, etc.
  Types             INTEGER, LONG, SINGLE, DOUBLE, STRING, BOOLEAN, DATE, VARIANT, OBJECT, COLLECTION, TRUE, FALSE, NOTHING, EMPTY, NULL
  Strings           "Hello, World!"
  Comments          ' This is a comment, REM This is a comment
  Numbers           42, 3.14, &HFF, date literals such as #2026-09-30# and #1/15/2026 10:30 AM#
  Operators         =, <, >, +, -, *, /, \, &

Date literals are colored as numbers only when they are real dates, as the compiler reads them; the # of a file number (CLOSE #1) is not. Some words are colored like keywords without being reserved -- built-in type names, Empty, Null, EACH, EVENT, WITHEVENTS, and the console and graphics statements such as CLS, LOCATE, COLOR, SCREEN, PSET, CIRCLE, PAINT, PCOPY and PMAP. A program may use them as its own names, and after a dot (Text1.Width, Picture1.Point) they are shown as ordinary names.

Editor Features

Back to Overview

Form Designer

The Form Designer provides a visual design surface for editing .frm files. Switch to it with Shift+F7 or the Design toolbar button. It opens in a separate window showing a WYSIWYG preview of the form.

Design Surface

Opening a form in the designer does not mark it modified. A control whose Visible property is False is still shown on the design surface (the setting applies when the program runs). Disabling a container greys the controls inside it; a control's own Enabled = False is kept when the container is enabled again. A .frm file without an AutoSize line opens without AutoSize; AutoSize = True wins over Width and Height lines. Text values (Caption, Text and so on) are limited to 379 characters.

Menu Editor

The Menu Editor (View > Menu Editor, Ctrl+E) edits the active form's menu bar and popup menus. Menus nest at most 15 levels (0-14); indenting refuses when any item below would go deeper. OK rejects an item nested more than one level below the item above it, and a blank item that has sub-items (it must be named); blank items without sub-items are dropped. The window's close box cancels. Renaming a menu item renames its event handlers in the code and updates the ContextMenu setting of the form and its controls; inserting, deleting and moving items does not rename anything.

Form Properties

Forms have the following design-time properties: Name, Caption, Width, Height, Left, Top, Layout (VBox or HBox), Centered, AutoSize, Resizable, HelpTopic and ContextMenu.

Properties Panel

Toolbox

Back to Overview

Project System

Project Files (.dbp)

A DVX BASIC project is stored as a .dbp file (DVX BASIC Project). The project file records:

The file sections all have the same shape: one FileN line per file, numbered from 0, and a Count line:

[Modules]
File0 = main.bas
Count = 1

[Classes]
File0 = account.cls
File1 = ledger.cls
Count = 2

[Forms]
File0 = form1.frm
Count = 1

How Projects are Compiled

When the project is compiled, all source files are concatenated into a single source stream: the modules first, then the class modules, then the forms. The IDE tracks which lines belong to which file so error messages and debugger locations point to the correct .bas, .cls or .frm file. The code section of each .frm file is preceded by a hidden BEGINFORM marker that ties its code to its form, and the code of each class module is likewise marked with its class name; a class module's header lines are not compiled.

Compile-Time Validation

Before the source is handed to the compiler, the IDE scans every .frm file and cross-checks the forms against the widget registry and the statements that reference them. Three classes of error are caught and reported without producing a binary:

These checks use the same metadata the Properties panel and Toolbox read from each installed control, so property and method names always match the current widget set without any separate list to maintain.

Project Operations

  Operation             Description
  ---------             -----------
  New Project           Creates a blank project with a name and directory. A default .frm file is added automatically.
  Open Project          Opens a .dbp file and loads all referenced files into memory. A project file that is 64 KB or larger, or cannot be read, is not loaded; opening it later reports "Cannot load <file>: unreadable or larger than 65535 bytes." Carriage returns are removed when files are loaded.
  Save Project          Writes the .dbp file to disk.
  Close Project         Closes the project, prompting to save unsaved changes.
  Add File              Adds a .bas, .frm or .cls file to the project. Opening a file without a project auto-creates an implicit project.
  New Class Module      Adds a new class module to the project and opens it (see Class Modules below).
  Rename File           Gives a file a new name on disk and in the project file (see Renaming a File below).
  Remove File           Removes a file from the project (prompts to save if modified). Removing the startup form clears the Startup Form setting.
  Project Properties    Opens a dialog for editing project metadata (name, author, company, version, copyright, description, icon, help file, startup form) and the Arguments for runs from the IDE.

Renaming a File

Select a file in the Project Explorer and choose File > Rename File. Type the new file name; the extension may be left out (a module stays .bas, a class module .cls and a form .frm, and cannot be given another kind's extension). The file is renamed in the project's directory and the project file is saved at once with the new name, so the two always agree. Nothing changes, and a message says why, when the name is not a valid file name, when another project file or any file in the directory already has it, or when the file or the project file cannot be written -- an existing file is never overwritten. A file that has never been saved is simply given the new name, and is written under it when you save.

A class module named after its file (it has no Attribute VB_Name line, or one that matches the file name, as File > New Class Module writes it) takes the new name as its class name: its Attribute VB_Name line is changed to match (an edit that is saved with the file, like any other). The new name must then be a valid name that no other form or class module uses. Code that uses the old class name is not changed. A form keeps its Name property; rename the form itself in the Properties window.

Project Explorer

The Project Explorer is a tree view window listing all project files, in three groups: Forms, Modules and Classes. Double-click a file to open it: .bas and .cls files open in Code view, .frm files open in Design view. The selected file in the Project Explorer determines the target for View > Code and View > Designer commands.

Class Modules

A class module (.cls file) defines a kind of object for your program: its member variables, properties and methods. The BASIC Language Reference describes how to write one (see Objects and Class Modules); this section covers working with them in the IDE.

A new class module starts with these header lines:

VERSION DVX 1.00 CLASS
Attribute VB_Name = "Class1"

Option Explicit

Leave the VERSION and Attribute lines at the top of the file; they are not compiled as code. Each class name must be different from the other class names and the form names in the project.

Back to Overview

Properties Panel

The Properties panel (Window > Properties) has two sections:

Each control type exposes different properties (e.g., Caption, Text, Width, Height, MaxWidth, MaxHeight, Weight, Alignment, Enabled, Visible, and type-specific properties like DataSource and DataField for data-bound controls).

Form Designer

Back to Overview

Toolbox

The Toolbox (Window > Toolbox) is a floating palette of buttons, one for each available control type. Every widget registered with DVX that has a BASIC name appears in the toolbox.

Click a tool to select it (the active tool name is stored in the designer state), then click on the form to place a new instance. Click the same tool again to deselect it and return to pointer mode.

Available Controls

  VB Name         Description
  -------         -----------
  CommandButton   Push button that triggers a Click event.
  Label           Static text label.
  TextBox         Single-line text input field.
  TextArea        Multi-line text editor.
  CheckBox        On/off checkbox.
  OptionButton    Radio button (mutually exclusive within a group).
  ListBox         Scrollable list of items.
  ComboBox        Drop-down combo box.
  DropDown        Simple drop-down list.
  PictureBox      Canvas for drawing and images.
  Frame           Grouping container with a labeled border.
  VBox            Vertical layout container.
  HBox            Horizontal layout container.
  WrapBox         Flow layout container that wraps items to the next row.
  Splitter        Resizable split between two child panes.
  ScrollPane      Scrollable container for large content.
  TabStrip        Tabbed container with multiple pages.
  ListView        Multi-column list with headers.
  TreeView        Hierarchical tree control.
  ProgressBar     Progress indicator bar.
  HScrollBar      Horizontal slider/scrollbar.
  SpinButton      Numeric up/down spinner.
  Line            Horizontal or vertical separator line.
  Spacer          Invisible spacing element for layout.
  Timer           Non-visual timer that fires periodic events.
  Toolbar         Toolbar container for buttons.
  StatusBar       Status bar at the bottom of a form.
  Terminal        ANSI terminal emulator control.
  Data            Data control for binding to a database.
  DBGrid          Data-bound grid for displaying database query results.

Image and ImageButton controls are not in the Toolbox; they can still be written into a .frm file by hand and are then edited in the Properties panel like any other control.

Form Designer

Back to Overview

Debugger

The DVX BASIC IDE includes a full interactive debugger. The debugger has three states:

  State       Description
  -----       -----------
  Idle        No program loaded or running.
  Running     The program is executing.
  Paused      Execution is paused at a breakpoint or step point. The IDE is fully interactive -- you can inspect and change variables, set or clear breakpoints, step, continue, or stop.

Starting a Debug Session

Breakpoints

Setting Breakpoints

Breakpoint Validation

Not every line can have a breakpoint. The IDE validates the line content and silently refuses to set breakpoints on:

Breakpoint Storage

Each breakpoint records the file it belongs to, the line number within that file, and the procedure name (Object.Event). Breakpoints are stored in the project and survive compilation.

Visual Indicators

Breakpoint Adjustment on Edit

Breakpoints follow their statements when lines are added, removed, joined, split or pasted. A breakpoint whose line is deleted is removed.

Stepping

  Action          Shortcut         Behavior
  ------          --------         --------
  Step Into       F8               Execute one statement. If the statement is a SUB/FUNCTION call, step into it.
  Step Over       Shift+F8         Execute one statement. If the statement is a SUB/FUNCTION call, execute the entire call and break at the next line in the current scope.
  Step Out        Ctrl+Shift+F8    Run until the current SUB/FUNCTION returns to its caller.
  Run to Cursor   Ctrl+F8          Run until execution reaches the line under the cursor.

Debug Run Behavior

When a program is running under the debugger:

Stopping

Press Esc or click the Stop toolbar button at any time to halt execution. The program is terminated, the debugger returns to Idle, and the IDE restores any designer or code windows that were hidden at the start of the run.

Locals Window

Call Stack Window

Watch Window

Breakpoints Window

Back to Overview

Locals Window

When the debugger pauses, the Locals and Call Stack windows are auto-opened (if not already visible). The Watch and Breakpoints windows can be opened manually from the Window menu.

Shows variables for the current execution scope. Displayed as a three-column ListView:

  Column   Content
  ------   -------
  Name     Variable name (internal mangled names like static variable placeholders are filtered out).
  Type     Data type: Integer, Long, Single, Double, String, Boolean, Date, Variant, Array, UDT, or the type of object. Array types show the element type (e.g., Integer()).
  Value    Current value. Strings are shown in quotes. Booleans as True/False. Arrays show bounds and element count (e.g., Integer(0 To 9) [10]). Uninitialized arrays show (uninitialized).

Variants show the value they currently hold, or Empty or Null; an OPTIONAL Variant parameter the caller left out shows Missing. Object variables show Nothing, or which object they refer to: the class name of a class instance, a Collection with its number of items, or the form or control.

The Locals window displays:

The Watch window and the Immediate window follow the same rules. The window is resizable.

Call Stack Window

Back to Overview

Call Stack Window

Shows the current call chain as a two-column ListView:

  Column      Content
  ------      -------
  Procedure   Procedure name (or (module) for module-level code).
  Line        Line number where execution is paused (shown for the topmost frame).

The current location is shown first, followed by each caller in the call stack (walking from the deepest frame back to the module entry point). Up to 32 frames are displayed.

Watch Window

Back to Overview

Watch Window

Allows monitoring arbitrary expressions while debugging. The window has a text input at the top and a two-column ListView below:

  Column       Content
  ------       -------
  Expression   The watch expression text.
  Value        Evaluated result (or <error> if evaluation fails). Blank when not paused.

Adding Watch Expressions

Type an expression in the text input and press Enter. Up to 16 watch expressions can be active at once.

Watch Expression Syntax

Watch expressions support:

Editing and Deleting

Breakpoints Window

Back to Overview

Breakpoints Window

Lists all set breakpoints as a three-column ListView:

  Column      Content
  ------      -------
  File        Project file path.
  Procedure   Procedure name (Object.Event format, or (General)).
  Line        Code line number within the file.

Debugger

Back to Overview

Immediate Window

The Immediate window is an interactive REPL at the bottom-right of the screen. Type a line of BASIC and press Enter to evaluate it. Results appear inline below your input. Enter evaluates the line it is pressed on (a line split by Enter is joined back first); Enter on an empty line does nothing. A statement that does not finish (for example DO: LOOP) is stopped with "Error: Statement did not finish; stopped."

Expression Evaluation

If the input is not a recognized statement keyword, it is automatically wrapped in a PRINT statement. For example, typing 2 + 2 evaluates as PRINT 2 + 2 and displays 4.

You can also type full statements:

Parse or runtime errors are displayed inline with an Error: prefix.

Inspecting Variables While Paused

When the debugger is paused at a breakpoint, the Immediate window has access to the running program's state. Expressions like count or name$ & " test" display live values.

Assigning Variables While Paused

When paused, you can modify variables in the running program directly from the Immediate window using assignment syntax:

variableName = newValue

The optional LET keyword is also accepted:

LET variableName = newValue

Assignment works for:

The new value is written directly into the running program's variable (local, global, or form scope). A confirmation message is displayed, and the Locals and Watch windows update automatically to reflect the change.

If the assignment target cannot be resolved (unknown variable, out-of-bounds index, wrong type), an error message is displayed.

Back to Overview

Output Window

The Output window is a read-only TextArea at the bottom-left of the screen. It displays:

The output buffer holds up to 32,768 characters; when it is full the oldest lines are dropped. The window always shows the newest output. Use Run > Clear Output to clear it.

INPUT statements prompt the user via a modal InputBox dialog; the prompt text is also echoed to the Output window. A program that has its own screen window types its INPUT there instead.

The Program's Screen Window

A program that uses the console or graphics statements gets a window of its own, the size of its screen mode (80x25 text, or 640x480 or 320x200 graphics), titled with the project's name. Alt+Enter in that window (or FULLSCREEN in the program) shows it on the whole screen; Alt+Tab brings the desktop back and the program continues. Keys typed in the window go to the program (INKEY$ and INPUT). The window stays open after the program's code has finished, so its output can be read; closing it ends the program.

Back to Overview

Find / Replace

Open with Ctrl+F (Find) or Ctrl+H (Replace). The Find/Replace dialog is modeless -- it stays open while you continue editing.

Dialog Controls

  Control                    Description
  -------                    -----------
  Find input                 The text to search for.
  Replace checkbox + input   Enable replacement mode and enter replacement text.
  Scope                      Radio group: Function, Object, File, or Project. Default is Project.
  Direction                  Radio group: Forward or Backward.
  Match Case                 Checkbox: case-sensitive search.

Buttons

  Button        Action
  ------        ------
  Find Next     Find the next occurrence. Function scope searches the current procedure, Object scope the selected object's procedures, File scope the current file and Project scope every file. At the end of the current procedure the search wraps around to its start.
  Replace       Replace the current match and find the next one.
  Replace All   Replace all occurrences within the selected scope.
  Close         Close the dialog.

Keyboard Shortcut

F3 repeats the last search (Find Next) without opening the dialog, also after the dialog was closed (then searching the whole project, ignoring case). Scope and direction chosen with the keyboard take effect like mouse clicks.

Back to Overview

Preferences

Open via Tools > Preferences. Settings are saved to dvxbasic.ini in the app's config directory. The dialog has two tabs.

General Tab

Editor Section

  Setting                                          Description                                                                           Default
  -------                                          -----------                                                                           -------
  Skip comments/strings when renaming              When renaming a control or form, skip occurrences inside comments and string literals.  On
  Require variable declaration (OPTION EXPLICIT)   When enabled, newly created projects have OPTION EXPLICIT on by default.                Off
  Tab width                                        Number of spaces per tab stop.                                                         3
  Insert spaces instead of tabs                    When enabled, pressing Tab inserts spaces. When disabled, inserts a real tab character. On

New Project Defaults Section

These fields set the default values for new project metadata:

  Field         Description                                   Default
  -----         -----------                                   -------
  Author        Default author name.                          (empty)
  Publisher     Default publisher/company name.               (empty)
  Version       Default version string.                       1.0
  Copyright     Default copyright notice.                     (empty)
  Description   Default project description (one line).       (empty)

Colors Tab

Customizes the syntax-highlighting colors used in the code editor. The left side is a list of seven color entries (Default Text, Keywords, Strings, Comments, Numbers, Operators, Types). Select an entry to see its color, and its red, green and blue amounts, on the right. Click Change... (or double-click the entry) to pick a new color in the color box: click a basic color or mix one with the Red, Green and Blue sliders or number boxes, then click OK. Changes are applied to the open editor when you click OK in the Preferences dialog.

Back to Overview

Keyboard Shortcuts

  Shortcut         Action
  --------         ------
  Ctrl+O           Add File
  Ctrl+S           Save File
  Ctrl+A           Select All
  Ctrl+X           Cut
  Ctrl+C           Copy
  Ctrl+V           Paste
  Ctrl+F           Find
  Ctrl+H           Replace
  Ctrl+E           Menu Editor
  F1               DVX BASIC Help
  F3               Find Next
  F5               Run
  Shift+F5         Debug
  Ctrl+F5          Run Without Recompile
  Esc              Stop
  F7               Code View
  Shift+F7         Design View
  F8               Step Into
  Shift+F8         Step Over
  Ctrl+Shift+F8    Step Out
  Ctrl+F8          Run to Cursor
  F9               Toggle Breakpoint
  Del              Delete

Changes in This Release

Back to Overview

Changes in This Release

This release fixes a large number of problems in the language, the runtime, the controls and the IDE. Most programs keep working unchanged. Three changes need attention in existing programs: variable scope (see Module Variables Need SHARED), the order of the bytes in a color, and text stored in numbers (see Colors and Numbers Follow Visual Basic).

Module Variables Need SHARED

DVX BASIC now uses the QBasic scope rules. A SUB or FUNCTION sees a variable declared at module level (including the code section of a form) only when it is declared with DIM SHARED, or named in a SHARED statement inside the procedure. Before, every module variable was visible everywhere.

See: Variable Scope and SHARED

Colors and Numbers Follow Visual Basic

See: Color Functions

See: Data Types

Language

Objects, Classes and Variants

See: Objects and Class Modules

See: Events

See: Interfaces (Implements)

See: Variants

Sound, Joysticks and Frames

See: Sound, Joysticks and Frames

Runtime

Forms and Controls

IDE

Back to Overview


DVX BASIC 1.0 -- Copyright 2026 Scott Duensing

Data Types

DVX BASIC supports the following data types. Each type has a corresponding type suffix character that can be appended to variable names.

Primary Types

  Type       Size       Suffix   Range / Description
  ----       ----       ------   -------------------
  Byte       1 byte     (none)   0 to 255
  Integer    2 bytes    %        -32768 to 32767
  Long       4 bytes    &        -2147483648 to 2147483647
  Single     4 bytes    !        32-bit float, approximately 7 digits precision
  Double     8 bytes    #        64-bit float, approximately 15 digits precision
  Currency   8 bytes    @        -922337203685477.5808 to 922337203685477.5807, exact to four decimal places
  String     variable   $        Variable-length, reference-counted, dynamic string
  Boolean    2 bytes    (none)   True (-1) or False (0)
  Date       8 bytes    (none)   A date and time of day from 1/1/100 to 12/31/9999
  Variant    varies     (none)   Any value at all: a number, text, a date, an object, an array, or the special values Empty and Null (see Variants)

Object Types

An object variable does not hold a value of its own; it refers to an object that lives elsewhere, so two variables can refer to the same object. Store a reference with Set, use the object's properties and methods with a dot, and set the variable to Nothing when you are done with it.

  Declared As     Holds
  -----------     -----
  Control         A control on a form (any type of control)
  Form            A form
  Object          Any object: a form, a control, an instance of a class module or a Collection
  ClassName       An instance of that class module (see Objects and Class Modules)
  Collection      A Collection object (see Collection Object)
Dim c As Control
Set c = Text1
c.Text = "Hello"

Dim people As New Collection
people.Add "Ann"

An object variable that has not been Set holds Nothing. Control, Form and Object variables accept each other's values; a variable declared As a class name or As Collection accepts only an object of that kind, or Nothing: an object of another kind raises error 13 (Type mismatch), and a value that is not an object at all raises error 424 (Object required). The Source parameter of the DragDrop and DragOver events is a Control.

See also: Objects and Class Modules

Internal Types

These types are not directly declarable but are used internally by the runtime.

  Internal Type   Description
  -------------   -----------
  Array           Reference-counted multi-dimensional array (up to 8 dimensions)
  UDT             User-defined type instance (created with TYPE...END TYPE)
  Object          Reference to a form, a control, a class instance or a Collection; declarable as Control, Form, Object, a class name or Collection
  Ref             Reference to a variable, array element, TYPE field or class member variable (what a ByRef parameter holds)

Type Suffixes

Type suffixes can be appended to variable names to declare their type implicitly:

count%  = 42         ' Integer
total&  = 100000     ' Long
rate!   = 3.14       ' Single
pi#     = 3.14159265 ' Double
price@  = 19.99      ' Currency
name$   = "Hello"    ' String

Numeric Literals

  Form               Example                Description
  ----               -------                -----------
  Decimal integer    42                     Values -32768..32767 are Integer; larger are Long
  Hex integer        &HFF, &H1234           Hexadecimal literal (0-9, A-F)
  Octal integer      &O10, &O77             Octal literal (0-7)
  Binary integer     &B1010, &B11111111     Binary literal (0-1)
  Integer suffix     42%                    Force Integer type
  Long suffix        42&, &HFF&             Force Long type
  Floating-point     3.14, 1.5E10, 2.5D3    Any number containing a decimal point or exponent is Double by default
  Single suffix      3.14!                  Force Single type
  Double suffix      3.14#                  Force Double type
  Currency suffix    19.99@, 5@             Force Currency type (more than four decimal places round, halves to even)
Note: Both E and D can introduce an exponent (e.g. 1.5E10 and 2.5D3 are equivalent forms of a scientific-notation double).

A literal with an Integer or Long suffix and a fraction or exponent is rounded (1E3% is 1000, 2.5% is 2). The most negative values -32768% and -2147483648& are valid. A trailing decimal point is allowed (1. is the Double 1). A numeric literal too long to read is a compile error.

Type Promotion

When mixing types in expressions, values are automatically promoted to a common type: Byte -> Integer -> Long -> Single -> Double. A Currency with a Byte, Integer, Long or Currency stays Currency (see Byte and Currency below). Whole-number arithmetic keeps the type of its operands: an Integer result too large for an Integer becomes a Long (32767 + 1 is the Long 32768) and a Byte result outside 0 to 255 becomes an Integer, but a Long result too large for a Long raises error 6 (Overflow), as in Visual Basic. Convert an operand when a larger result is expected: CDBL(2147483647) + 1 is 2147483648.

+ joins two strings. When a string meets a number in an arithmetic operator (including +) or a comparison, the string must hold a number, as in Visual Basic: "1" + 2 is 3 and " 2.5 " * 2 is 5, but text that is not a number ("abc" + 2, "12abc" + 2) raises error 13 (Type mismatch). VAL reads the number at the start of any text instead (VAL("12abc") is 12). Use & to join text and numbers, and VAL / STR$ to convert explicitly.

Assignment Conversion

Storing a value into a variable declared as Byte, Integer, Long, Single, Double, Currency, String, Boolean or Date (by suffix, by AS clause, by DEFtype, or as a typed parameter, STATIC variable, FUNCTION result, TYPE field or array element) converts the value to that type: a number stored in a String variable becomes its text as STR$ gives it without the leading space ("5"). Text stored in a numeric variable must be a number, as in Visual Basic: "12" and " 3.5 " convert, while text that is not a number ("abc", "12abc") raises error 13 (Type mismatch) and the variable keeps its value. DEFtype statements also give parameters, STATIC variables and FUNCTION results their default type. Byte, Integer and Long round to the nearest whole number, with halves rounding to the nearest even number (2.5 becomes 2, 3.5 becomes 4), and raise error 6 (Overflow) when the result does not fit; Currency rounds to four decimal places the same way. Single keeps about 7 significant digits, so PRINT shows at most 7 digits of it. Boolean stores True for any non-zero number or non-empty string and False otherwise. Date takes a number as a date's number of days and reads a string as a date (error 13 when the text is not a date, error 6 outside 1/1/100 to 12/31/9999); INPUT into a Date variable reads the date the same way. A variable declared with DIM but without a type is Single (or the DEFtype for its first letter). A variable that is never declared keeps whatever type the assigned value has. A variable declared with a type holds that type from the start, before anything is stored in it: VARTYPE of a Long that was never assigned is 3 (vbLong) and of a String 8 (vbString).

Dim n As Integer
n = 3.7            ' n is 4
n = 40000          ' Error 6: Overflow
n = "12"           ' n is 12
n = "twelve"       ' Error 13: Type mismatch (n is still 12)
Dim b As Boolean
b = 3              ' b is True
Dim s
s = 1 / 3          ' s is Single: prints 0.3333333
x = 1 / 3          ' x was never declared and keeps the Double: prints 0.333333333333333

Boolean Values

Boolean values use -1 for True and 0 for False. Any non-zero numeric value is treated as True in a conditional context. The keywords True and False are reserved and may be used anywhere a Boolean value is expected.

Byte and Currency

A Byte holds a whole number from 0 to 255 in one byte. Storing a value outside that range raises error 6 (Overflow). Arithmetic on two Bytes gives a Byte when the result is 0 to 255 and an Integer otherwise; negating a Byte gives an Integer. CBYTE converts a value to a Byte.

A Currency holds an amount of money exactly: it counts ten-thousandths, so it has four decimal places and adding, subtracting or multiplying amounts never drifts (adding 0.1@ ten times gives exactly 1). A value with more decimal places is rounded to four, halves to the nearest even digit (CCUR(2.00005) is 2, CCUR(2.00015) is 2.0002), and a result outside the Currency range raises error 6 (Overflow). +, - and * on a Currency and a Byte, Integer, Long or Currency give a Currency; with a Single or Double they give a Double, and / always gives a Double. Comparisons of Currency values are exact. PRINT and STR$ show a Currency with only the decimals it needs (12.5); FORMAT$ lays it out like any other number. A FOR loop with a Currency counter steps exactly. CCUR converts a value to a Currency.

Dim total As Currency
Dim i As Integer
For i = 1 To 3
    total = total + 19.99@
Next
Print total               ' 59.97
Print FORMAT$(total, "0.00")

GET and PUT store a Byte in 1 byte and a Currency in 8 (see GET / PUT).

Date Values

A Date holds a calendar date and a time of day, as in Visual Basic: the whole part of its number counts days from 12/30/1899 and the fraction is the time (0.5 is noon, so 36526.5 is noon on 1/1/2000). Days before 12/30/1899 are negative numbers whose time still counts forward from midnight: -1.25 is 6:00 AM on 12/29/1899. CDBL gives a date's number and CDATE turns a number back into a date.

Write a date literal between # signs. The month comes before the day; a year can also come first, and month names (full or abbreviated) work too. A time can follow the date or stand alone:

Dim d As Date
d = #1/15/2000#                  ' January 15, 2000
d = #2000-01-15 15:30#           ' year first, 24-hour time
d = #Jan 15, 2000 3:30:00 PM#
d = #3:30 PM#                    ' a time alone is on 12/30/1899

Two-digit years 00 to 29 are 2000 to 2029 and 30 to 99 are 1930 to 1999. Date is not a reserved word, so a program may still use Date (or any of the date function names) for its own variables and procedures; the program's own name wins.

PRINT, STR$, CSTR and the & operator show a date as m/d/yyyy h:mm:ss AM (1/15/2000 3:30:00 PM). A date at midnight shows only the date and a time on 12/30/1899 only the time; a Date variable that was never assigned is 12:00:00 AM. Use FORMAT$ for any other layout.

Adding a number of days to a date, or subtracting one, gives a date (fractions are parts of a day, so d + 0.25 is six hours later); subtracting one date from another gives the number of days between them as a Double. Comparisons put dates in time order, and a string compared with a date is read as a date:

Dim due As Date
due = Date + 30                     ' thirty days from today
If due > #12/31/2025# Then Print "Next year"
Print #3/1/2000# - #2/1/2000#       ' 29 (2000 is a leap year)
If due = "1/15/2026" Then Print "Match"

A Date variable has no Empty or Null state (a Variant does): a date that is out of range is error 6 (Overflow), and text that is not a date is error 13 (Type mismatch).

See also: Conversion Functions

See also: Variants

Variants

A Variant is a variable that can hold any kind of value: a number, text, a date, True or False, an object or a whole array. It takes on the type of whatever is stored in it, and can change type each time something new is stored. A Variant can also hold two special values that no other type has: Empty (nothing has been stored yet) and Null (the value is unknown or missing).

Dim v As Variant
Print TypeName(v)       ' Empty
v = 42
Print TypeName(v)       ' Integer
v = "forty-two"
Print TypeName(v)       ' String
v = #1/15/2000#
Print TypeName(v)       ' Date
v = Null
Print IsNull(v)         ' True

Declare a Variant with AS VARIANT. Arrays of Variants (DIM list(10) AS VARIANT), Variant parameters, and FUNCTIONs and properties AS VARIANT work the same way; each element of a Variant array starts Empty. A variable declared with DIM but no AS clause, or never declared at all, is not a Variant: it keeps the older rules described under Assignment Conversion.

Storing a Variant in a variable of another type converts the value to that type, as for any other assignment. A Variant that is given an array gets its own copy of the array, as in Visual Basic: after v = list, changing list(1) does not change v(1), and w = v copies again. The same holds when a Variant holding an array is passed BYVAL, stored in an object's member or added to a Collection. Index it like the array itself, v(1).

Dim list(2) As Integer, v As Variant
list(0) = 1
v = list                ' v holds a copy
list(0) = 5
Print v(0); list(0)     ' 1 5

Empty

Empty means that nothing has been stored in the Variant yet. A new Variant is Empty, and assigning Empty makes it Empty again. In arithmetic Empty counts as 0 and in text as "", so a counter kept in a Variant needs no starting value; PRINT shows nothing for it.

Dim total As Variant
total = total + 5       ' Empty counts as 0: total is 5
If IsEmpty(v) Then Print "Nothing stored yet"

Null

Null means "no valid value" -- for example a field that was never filled in. Null spreads through most expressions: anything calculated from a Null is Null too, so a missing value is not mistaken for a real one.

  Expression                                    Result
  ----------                                    ------
  Null + 1, Null * x, -Null, Not Null           Null
  Null = 1, Null < x, Null = Null               Null (a comparison with Null is never True)
  Abs(Null), Int(Null), Fix(Null), Sgn(Null)    Null
  Left(Null, 1), UCase(Null), Len(Null), ...    Null (the Variant string functions; see below)
  "Name: " & Null                               "Name: " (& treats Null as "")
  Null & Null                                   Null
  False And Null                                False
  True Or Null                                  True
  False Imp Null, Null Imp True                 True
  Any other And, Or, Xor, Eqv or Imp with Null  Null

An IF, ELSEIF, WHILE, DO or LOOP condition that is Null counts as False. Any other use that needs a real number -- storing Null in a numeric, Boolean or Date variable, CINT(Null) and the other conversion functions, a string function ending in $ such as UCASE$ or LEFT$, or an array subscript -- raises error 94 (Invalid use of Null).

As in Visual Basic, the string functions without $ are Variant functions that pass Null through: LEFT, RIGHT, MID, UCASE, LCASE, TRIM, LTRIM, RTRIM, CHR, HEX, OCT, STR, SPACE and STRING give Null when their text (or number) argument is Null, and so do LEN, INSTR, INSTRREV, STRCOMP, LIKE and the date parts YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, WEEKDAY and DATEPART. Their $ forms (LEFT$, UCASE$ ...) always give text and raise error 94 for Null.

Because Null = Null is itself Null, test for Null with ISNULL, never with =:

If IsNull(price) Then
    Print "No price yet"
Else
    Print "Price: "; price
End If

Empty and Null are not reserved words: a program that declares its own variable or constant named Empty or Null keeps using it.

Variant Functions

  Function      Returns   Description
  --------      -------   -----------
  VARTYPE(v)    Integer   A number for the kind of value v holds (see VarType Constants): vbEmpty (0), vbNull (1), vbInteger (2), vbString (8), vbObject (9) and so on. For an array it is vbArray (8192) plus the element type, so an Integer array is 8194 and a Variant array 8204.
  TYPENAME(v)   String    The name of the kind of value: "Byte", "Integer", "Long", "Single", "Double", "Currency", "String", "Boolean", "Date", "Empty", "Null", "Error" (a left-out OPTIONAL argument), the name of a TYPE, "Integer()" for an array, and for objects the class name, "Collection", "Nothing", or the type of a form or control.
  ISEMPTY(v)    Boolean   True when v is Empty.
  ISNULL(v)     Boolean   True when v is Null.
  ISNUMERIC(v)  Boolean   True when v is a number, True or False, Empty, or text that reads as a number ("12", "1.5"). False for Null, dates and other text.
  ISOBJECT(v)   Boolean   True when v is an object reference, including Nothing.
  ISARRAY(v)    Boolean   True when v is an array.
  ISMISSING(v)  Boolean   True when v is an OPTIONAL Variant parameter the caller left out (see Procedures).
  ISDATE(v)     Boolean   True for a Date or text holding a date (see Date and Time Functions).
  CVAR(v)       Variant   v unchanged, as a Variant.
  ARRAY(a, ...) Variant   A Variant holding an array of copies of the values, numbered from OPTION BASE (0 unless OPTION BASE 1); ARRAY() is empty (UBOUND -1).
Dim days As Variant
days = Array("Mon", "Tue", "Wed")
Print days(1)               ' Tue
For Each d In Array(1, 2, 3)
    Print d;
Next
Sub Describe(ByVal v As Variant)
    Select Case VarType(v)
        Case vbEmpty
            Print "(empty)"
        Case vbNull
            Print "(unknown)"
        Case vbString
            Print "Text: "; v
        Case Else
            Print TypeName(v); ": "; v
    End Select
End Sub

See also: Data Types

See also: VarType Constants

Operators

Operators listed from highest precedence (evaluated first) to lowest precedence (evaluated last). Parentheses override precedence and may be nested freely.

  Precedence     Operator                  Description
  ----------     --------                  -----------
  1 (highest)    ^                         Exponentiation
  2              - (unary), + (unary)      Negation (unary plus is a no-op)
  3              *  /                      Multiply, float divide
  4              \                         Integer divide
  5              MOD                       Modulus
  6              +  -                      Addition, subtraction (+ also concatenates strings)
  7              &                         String concatenation
  8              =  <>  <  >  <=  >=  Is  Like  Comparison (returns Boolean)
  9              NOT                       Logical/bitwise NOT
  10             AND                       Logical/bitwise AND
  11             XOR                       Logical/bitwise exclusive-or
  12             OR                        Logical/bitwise OR
  13             EQV                       Logical/bitwise equivalence
  14 (lowest)    IMP                       Logical/bitwise implication

Arithmetic Operators

  Operator   Description
  --------   -----------
  +          Addition (or string concatenation when both operands are strings)
  -          Subtraction (or negation when used as a unary prefix)
  *          Multiplication
  /          Floating-point division (result is always Single or Double)
  \          Integer division (result is Long, fractional part discarded)
  MOD        Integer modulus (remainder)
  ^          Exponentiation (result is Double)

Comparison Operators

Comparison operators return True (-1) or False (0).

  Operator   Description
  --------   -----------
  =          Equal to
  <>         Not equal to
  <          Less than
  >          Greater than
  <=         Less than or equal to
  >=         Greater than or equal to
  Is         Both sides refer to the same object (objects only)
  Like       The text on the left matches the pattern on the right

String comparisons are controlled by OPTION COMPARE. With OPTION COMPARE BINARY (the default) strings are compared by byte value. With OPTION COMPARE TEXT comparisons are case-insensitive. A comparison with Null gives Null (see Variants).

Is compares object references, not values: a Is b is True when both refer to the very same object, and x Is Nothing tests for an object variable that holds no object. Either side may be a form or control name. Using Is on something that is not an object raises error 424 (Object required).

text Like pattern is True when the whole of text matches the pattern. In the pattern, ? stands for any one character, * for any run of characters (none too), # for one digit 0 to 9, [list] for one character in the list and [!list] for one character not in it; anything else stands for itself. A list holds characters and ranges such as a-z ([A-Za-z0-9_]); to match a literal ?, *, # or [, put it in brackets ([*]). OPTION COMPARE TEXT makes the match ignore case. Like with Null gives Null, and a pattern with a [ that has no ] raises error 93.

If name$ Like "A*" Then Print "Starts with A"
If code$ Like "[A-Z]##" Then Print "A letter and two digits"
If file$ Like "*.[!b]*" Then Print "Not a .b... extension"

TypeOf object Is TypeName is True when the object is of that type. TypeName can be a class module's name, Collection, Form, Control (any control), Object (any object that is not Nothing), or a control type such as TextBox. It is False for Nothing. Use Not TypeOf ... Is ... for the opposite test.

If player Is Nothing Then Set player = New Player
If a Is b Then Print "Same object"
If TypeOf Source Is TextBox Then Print Source.Text

Logical / Bitwise Operators

The logical operators work on Boolean values and also perform bitwise operations on integer values. With Null they give Null unless the other side decides the answer (False And Null is False, True Or Null is True); see Variants.

  Operator   Description
  --------   -----------
  NOT        Logical/bitwise complement
  AND        Logical/bitwise AND
  OR         Logical/bitwise OR
  XOR        Logical/bitwise exclusive-or
  EQV        Logical/bitwise equivalence (same as NOT (a XOR b))
  IMP        Logical/bitwise implication (same as (NOT a) OR b)

String Concatenation

Use & to concatenate strings. The + operator also concatenates when both operands are strings. Prefer & because it does not depend on operand types.

result$ = "Hello" & " " & "World"
result$ = firstName$ & " " & lastName$

' + also concatenates when both operands are strings
greeting$ = "Hi " + name$

Statements

Multiple statements can appear on one line separated by : (colon). A line can be continued onto the next physical line by ending it with an underscore (_) preceded by whitespace. Comments start with ' (apostrophe) or the REM keyword and run to the end of the line. The character ? is a shorthand for PRINT.

a = 10 : b = 20 : c = a + b        ' three statements on one line

total = price * quantity _
      + shipping + tax              ' one statement continued across lines

REM This is a comment
' So is this
? "Hello"                           ' same as PRINT "Hello"

Declaration Statements (DIM, REDIM, CONST, TYPE, DECLARE)

Conditional Statements (IF, SELECT CASE)

Loop Statements (FOR, DO, WHILE)

Procedures (SUB, FUNCTION, DEF FN)

Flow Control (EXIT, CALL, GOTO, GOSUB, ON)

Input/Output (PRINT, INPUT, DATA/READ)

Miscellaneous Statements (ON ERROR, SHELL, SLEEP, END)

Sound, Joysticks and Frames (BEEP, SOUND, PLAY, STICK, STRIG, FRAMEWAIT)

Objects and Class Modules (NEW, PROPERTY, Class_Initialize, Me)

Collection Object (Add, Remove, Item, Count)

Declaration Statements

DIM

Declares variables and arrays with an explicit type. If no type is given, the type defaults to whatever DEFtype (if any) is in effect for the variable's first letter; without a DEFtype statement the default is Single.

DIM variable AS type
DIM variable(upperBound) AS type
DIM variable(lower TO upper) AS type
DIM variable(dim1, dim2, ...) AS type
DIM variable() AS type
DIM variable AS UdtName
DIM variable AS STRING * n
DIM variable AS NEW ClassName
DIM SHARED variable AS type
DIM variable1 [AS type], variable2 [AS type], ...

An array declared with bounds is a fixed array. DIM variable() with empty parentheses declares a dynamic array that has no storage until a REDIM gives it bounds; using it before then raises error 13. An array that is first created by REDIM, and an array parameter, are dynamic too (see ERASE for the difference).

One DIM can declare several variables, separated by commas. Each one takes its own AS clause; a name without one gets its suffix or DEFtype type (Single by default), so DIM a, b AS STRING makes only b a String. Arrays can have up to 8 dimensions; more is a compile error. A variable declared with type suffix does not need the AS clause:

Dim name$, count%, total&       ' suffixes infer the types
Dim first, last As String, list(10) As Integer

Examples:

Dim name As String
Dim count As Integer
Dim values(100) As Double
Dim matrix(1 To 10, 1 To 10) As Single
Dim Shared globalFlag As Boolean
Dim record As PersonType
Dim fixedStr As String * 20
Note: A module-level variable is visible inside a SUB or FUNCTION only when it is declared with DIM SHARED (or named in a SHARED statement in that procedure). See Variable Scope below. Inside a SUB or FUNCTION, DIM declares a local variable that is recreated on each call (use STATIC to retain its value between calls). A SUB or FUNCTION holds at most 64 parameters and local variables together, including a few hidden ones that statements such as ON ... GOTO, SWAP and READ into array elements use while they run; a procedure that needs more fails to compile with "Too many local variables".

Fixed-length strings (STRING * n) are padded with spaces and truncated when assigned so their length is always exactly n.

DIM variable AS NEW ClassName (or AS NEW Collection) creates a new object at the DIM and stores it in the variable; without NEW an object variable starts as Nothing. See Objects and Class Modules.

Variable Scope and SHARED

DVX BASIC follows the QBasic scope rules:

DIM SHARED total AS LONG       ' visible in every SUB and FUNCTION
DIM count AS INTEGER           ' module code only

SUB AddUp(n AS INTEGER)
    total = total + n          ' the module variable
    count = 1                  ' a local variable, not the module's count
END SUB

SUB ShowCount
    SHARED count               ' this procedure uses the module's count
    PRINT count
END SUB

DIM SHARED and REDIM SHARED are only allowed at module level. Inside a procedure use the SHARED statement:

SHARED variable [()] [AS type] [, variable [()] [AS type] ...]

SHARED gives the procedure access to the named module variables (write name() for an array). The AS type, when given, must match the module variable's declaration. Naming a variable that does not exist at module level creates it there (in a form's code, as a variable of that form).

How Names Are Found

Every name in a program is looked up the same way, in this order:

A SUB or FUNCTION can be called before its definition, and a TYPE, ENUM or class -- with its member variables and procedures -- can be used before it is declared: the compiler reads every declaration first. A name after a dot is a member of the object before it: when that object's class is known (see Objects and Class Modules) the member is looked up in the class when the program is compiled, else when it runs.

PUBLIC / PRIVATE

At module level, PUBLIC and PRIVATE can be used in place of DIM, as in Visual Basic. PUBLIC declares a variable that every SUB and FUNCTION can use (the same as DIM SHARED); PRIVATE declares one that only module-level code sees (the same as DIM).

Public highScore As Long        ' same as Dim Shared highScore As Long
Private tries As Integer        ' same as Dim tries As Integer

PUBLIC and PRIVATE may also be written in front of SUB and FUNCTION. Outside a class module they change nothing, because procedures are visible to the whole program anyway. In a class module they decide what code outside the class can use; see Objects and Class Modules. Inside a procedure, use DIM.

REDIM

Reallocates an array, optionally preserving existing data. The array may have been declared with DIM name() or with bounds, or not declared at all (REDIM then declares a dynamic array).

REDIM array(newBounds) AS type
REDIM PRESERVE array(newBounds) AS type
REDIM SHARED array(newBounds) AS type

REDIM SHARED (module level only) also makes the array visible in every SUB and FUNCTION, like DIM SHARED.

ReDim items(newSize) As String
ReDim Preserve scores(1 To newCount) As Integer

CONST

Declares a named constant. The value is worked out once, when the program is compiled, and can never change -- you cannot assign a new value to a constant or pass it by reference. Several constants can be declared in one CONST statement, separated by commas.

CONST name = expression
CONST name AS type = expression
CONST name = expression, name = expression, ...
Const MAX_SIZE = 100
Const PI = 3.14159265
Const APP_NAME = "DVX App"
Const DEBUG_MODE = True
Const HEADER As String = "=== Report ==="
Const LAUNCH = #7/20/1969 8:17 PM#
Const LAST_INDEX = MAX_SIZE - 1, HALF = MAX_SIZE \ 2
Const TITLE = APP_NAME & " " & "1.0"
Const CRLF = Chr$(13) & Chr$(10)
Const TEAL = RGB(0, 128, 128)
Const BIG = MAX_SIZE > 50

The value can be any expression built from:

Anything else -- a variable, a FUNCTION of your own, or a built-in whose answer can change from run to run such as TIMER, NOW, RND or DIR$ -- is a compile error ("Constant expression required"). An expression that fails, such as a division by zero or a result too big for its type, is also reported when the program is compiled. Text comparisons in a constant follow the OPTION COMPARE setting in effect where the constant is declared. A string constant can be at most 255 characters long.

Without an AS clause the constant takes the type of its value: a whole number makes a Long constant, a number with a fraction a Double constant, and strings, Booleans and dates keep their type. With an AS clause the value is converted to that type: Integer and Long values are rounded and must fit the type, and a string for a numeric type (or a number for String) is a compile error.

Constants declared at module level are visible to all procedures. A CONST declared inside a SUB or FUNCTION is local to that procedure; it may reuse the name of a module constant without changing it.

PUBLIC CONST and PRIVATE CONST work as in Visual Basic. A Private constant, and any constant of a form or class module, belongs to the file it is declared in: another module, form or class of the project can declare its own constant of the same name, and does not see this one. A Public constant, or a plain CONST in a module, is seen by the whole program. A class module or form cannot have a Public constant ("Constants are not allowed as Public members of a class module or form").

Public Const APP_VERSION = "2.1"   ' every file of the project
Private Const BUFFER_SIZE = 512    ' this file only

TYPE...END TYPE

Defines a user-defined type (record/structure).

TYPE TypeName
    fieldName AS type
    fieldName AS STRING * n
    ...
END TYPE
Type PersonType
    firstName As String
    lastName  As String * 20
    age       As Integer
End Type

Dim p As PersonType
p.firstName = "Scott"
p.age = 30

UDT fields can themselves be UDTs (nested types), and field access chains through array elements too: shapes(i).origin.x = 5. A new instance starts with numeric fields at 0, Boolean fields False, variable strings empty and STRING * n fields padded to n spaces. TYPE variables can be written to and read from RANDOM and BINARY files with PUT and GET (see GET / PUT).

ENUM...END ENUM

Defines a set of named whole-number constants, and a type name for variables that hold one of them.

ENUM EnumName
    member
    member = expression
    ...
END ENUM
Enum Direction
    North           ' 0
    East            ' 1
    South = 10
    West            ' 11
End Enum

Enum Style
    Bold = 1
    Italic = Bold * 2
    Underline = Style.Italic * 2
    AllStyles = Bold Or Italic Or Underline
End Enum

Dim heading As Direction
heading = West
If heading = Direction.West Then Print "Going west"

The first member is 0 and each member without a value is one more than the member before it. A value may be any constant expression (see CONST), including members declared earlier in the same ENUM or in another one. Members are Long constants and can be used on their own (West) or with the ENUM name in front (Direction.West). If two ENUMs have a member with the same name, that name must be written with its ENUM name.

The ENUM name can be used as a type wherever a type is allowed: DIM, parameters, FUNCTION results and TYPE fields. Such a variable is a Long, so it can hold any whole number, not only the members. ENUMs are declared at module level (not inside a SUB or FUNCTION) and are visible everywhere in the program; declare an ENUM before the code that uses its members. PRIVATE ENUM keeps the ENUM and its members to the file it is declared in, like PRIVATE CONST; PUBLIC ENUM (the same as a plain ENUM) is seen everywhere. Members are constants: Direction.West = 3 is a compile error ("Cannot assign to a constant").

DECLARE

Forward-declares a SUB or FUNCTION. This is rarely required because the compiler supports forward references within a module, but it is still accepted for compatibility:

DECLARE SUB name ([BYVAL] [OPTIONAL] param AS type, ...)
DECLARE FUNCTION name ([BYVAL] [OPTIONAL] param AS type, ...) AS returnType

A DECLARE must match the SUB or FUNCTION it declares: the same parameter types, BYVAL and OPTIONAL flags, and return type.

DECLARE LIBRARY

Declares external functions from a native library bundled with DVX. This is how BASIC programs reach operating-system services, serial ports, databases, and other native facilities. Rather than writing DECLARE LIBRARY blocks yourself, add one of the shipped include files (such as commdlg.bas or sql.bas) to your project; the include file contains the proper declarations.

DECLARE LIBRARY "libraryName"
    DECLARE SUB name ([BYVAL] param AS type, ...)
    DECLARE FUNCTION name ([BYVAL] param AS type, ...) AS returnType
END DECLARE
Declare Library "basrt"
    Declare Function SQLOpen(ByVal path As String) As Long
    Declare Sub SQLClose(ByVal db As Long)
End Declare

Arguments are always passed by value. Each argument is converted to the type its parameter is declared with before the call, so a Double passed to a Long parameter arrives as a whole number and a Single parameter receives a Single. Declare Integer only for native values that fit in 16 bits; use Long for 32-bit values, or large results are cut down to 16 bits. A Byte parameter or result is 8 bits. A Currency parameter receives the amount as a 64-bit whole number of ten-thousandths; a DECLARE FUNCTION cannot return a Currency.

See also: BASIC Runtime Libraries

STATIC

Declares a local variable that retains its value between calls.

STATIC variable AS type
Sub Counter()
    Static count As Integer
    count = count + 1
    Print count
End Sub

Several variables can be declared in one STATIC statement, separated by commas, each with its own AS clause; STRING * n works as in DIM. Arrays and TYPE variables can be STATIC too and keep their contents between calls: a fixed-size array (Static hits(1 To 10) As Long) or a dynamic one sized later with REDIM (Static names() As String). In a class module each object has its own copy of a procedure's STATIC variables, arrays and TYPE variables, as in Visual Basic: two objects counting calls count separately. A STATIC AS NEW object or WithEvents variable is not supported (a compile error); use a module-level or member variable for those.

Sub Remember(ByVal word As String)
    Static seen(1 To 3) As String
    Static count As Integer
    count = count + 1
    seen((count - 1) Mod 3 + 1) = word
    Print seen(1); " "; seen(2); " "; seen(3)
End Sub

Writing STATIC after a SUB or FUNCTION header makes every local variable of the procedure static, the ones declared with DIM and the ones used without a declaration (QBasic and Visual Basic):

Sub Tally(points As Integer) Static
    total = total + points      ' keeps its value between calls
    Dim calls As Integer        ' a STATIC variable too
    calls = calls + 1
    Print calls; total
End Sub

OPTION

Sets compiler options. Must appear before any executable code.

OPTION BASE 0          ' Arrays start at index 0 (default)
OPTION BASE 1          ' Arrays start at index 1
OPTION COMPARE BINARY  ' Case-sensitive string comparisons (default)
OPTION COMPARE TEXT    ' Case-insensitive string comparisons
OPTION EXPLICIT        ' All variables must be declared with DIM

DEFtype Statements

Set the default type for variables based on their first letter.

DEFINT letterRange
DEFLNG letterRange
DEFSNG letterRange
DEFDBL letterRange
DEFSTR letterRange
DEFBYTE letterRange
DEFCUR letterRange
DefInt I-N     ' Variables starting with I through N default to Integer
DefStr S       ' Variables starting with S default to String

Assignment

Assigns a value to a variable, array element, or UDT field.

variable = expression
array(index) = expression
udt.field = expression
LET variable = expression

The LET keyword is optional and supported for compatibility.

Assigning a whole TYPE value to a TYPE variable, array element or field copies the value's fields into the record that is already there, as in Visual Basic: the two stay separate records (changing one later does not change the other), and a SUB that was passed one of the target's fields by reference sees the new value.

SWAP

Exchanges the values of two variables or array elements. The two operands should be the same type.

SWAP variable1, variable2
SWAP array(index), variable
Swap a, b
Swap names(i), names(j)

LSET / RSET

Stores a string into a string variable without changing the variable's length: LSET places the value at the left and RSET at the right, filling the rest with spaces. A value longer than the variable is cut off at the right.

LSET variable = expression
RSET variable = expression
Dim field As String
field = Space$(8)
LSet field = "Name"          ' "Name    "
RSet field = "42"            ' "      42"

The target may be an array element or a TYPE field. It must hold a string; any other value raises error 13 (Type mismatch).

LSET also copies a whole record: when the target is a TYPE variable, the value must be another TYPE variable, and its bytes -- laid out as PUT writes the record to a file -- are copied into the target, even when the two are of different TYPEs. When the source is shorter the rest of the target is filled with spaces; when it is longer the extra bytes are dropped. This is meant for records of numbers and fixed-length strings (STRING * n), as used with random-access files; a variable-length string field does not copy meaningfully between different TYPEs. RSET cannot copy records.

Type Header
    kind As String * 2
    size As Integer
End Type
Type Raw
    bytes As String * 4
End Type
Dim h As Header, r As Raw
r.bytes = "AB" + Chr$(10) + Chr$(0)
LSet h = r              ' h.kind = "AB", h.size = 10

SET

Stores an object reference -- a form, a control, an instance of a class module, a Collection, or Nothing -- in a variable, array element, TYPE field or property. After SET both names refer to the same object; nothing is copied.

SET variable = objectExpression
SET variable = NEW ClassName
SET variable = Nothing
Dim frm As Form
Set frm = CreateForm("MyForm", 320, 240)
frm.Caption = "Built in code"

Dim c As Control
Set c = Text1                  ' a control on the form
c.Text = "Hello"

Dim list As Collection
Set list = New Collection      ' a new, empty Collection
Set list = Nothing             ' let it go

The value must be an object or Nothing; anything else raises error 424 (Object required). SET is not used for ordinary numeric or string assignment.

ERASE

Frees the memory of a dynamic array (declared with DIM name(), created by REDIM, or an array parameter) and resets it to the undimensioned state; using it again before a REDIM raises error 13. A fixed array (declared with bounds) keeps its bounds and has every element reset to zero, an empty string, False or a fresh TYPE instance.

ERASE arrayName
ERASE array1, array2, ...

One ERASE can name several arrays, separated by commas.

Conditional Statements

IF...THEN...ELSE...END IF

Conditional execution. Supports single-line and multi-line forms.

Single-line form

IF condition THEN statement
IF condition THEN statement ELSE statement

Multi-line form

IF condition THEN
    statements
ELSEIF condition THEN
    statements
ELSE
    statements
END IF
If x > 10 Then
    Print "Large"
ElseIf x > 5 Then
    Print "Medium"
Else
    Print "Small"
End If

If ready Then Print "Go!"

SELECT CASE

Multi-way branch based on an expression value.

SELECT CASE expression
    CASE value
        statements
    CASE value1, value2
        statements
    CASE low TO high
        statements
    CASE IS operator value
        statements
    CASE ELSE
        statements
END SELECT
Select Case grade
    Case 90 To 100
        Print "A"
    Case 80 To 89
        Print "B"
    Case Is >= 70
        Print "C"
    Case 60, 65
        Print "D (borderline)"
    Case Else
        Print "F"
End Select

CASE items can be combined with commas. The IS keyword allows comparison operators: <, >, <=, >=, =, <>.

Loop Statements

FOR...NEXT

Counted loop with an optional step value.

FOR variable = start TO limit [STEP step]
    statements
NEXT [variable]
For i = 1 To 10
    Print i
Next i

For x = 10 To 0 Step -2
    Print x
Next

The variable name after NEXT is optional. Use EXIT FOR to break out early.

With an Integer or Long counter a constant STEP must be a whole number (STEP 0.5 is a compile error); a STEP computed at run time is rounded to the counter's type. A Single or Double counter takes any step.

FOR EACH...NEXT

Runs the loop once for every item in a Collection or every element of an array, without counting.

FOR EACH item IN group
    statements
NEXT [item]
Dim names As New Collection
names.Add "Ann"
names.Add "Bob"

Dim person As Variant
For Each person In names
    Print "Hello, "; person
Next person

Dim scores(1 To 3) As Integer
Dim s As Variant
For Each s In scores
    total = total + s
Next

group can be a Collection, an array (of any number of dimensions; elements are visited in row order, the last subscript changing fastest), a Variant holding an array, or a ParamArray. On each pass item receives a copy of the next item: for a Collection of objects it refers to the object itself, but assigning a new value to item does not change the array or Collection. Declare item AS VARIANT, or as an object type for a Collection of objects. The number of items is checked on every pass, so items added or removed inside the loop are taken into account.

EXIT FOR leaves the loop early. Looping over something that is not an array or Collection raises error 13 (Type mismatch), or error 451 (Object not a collection) for an object that is not a Collection. EACH and IN are not reserved words.

DO...LOOP

General-purpose loop with pre-test, post-test, or infinite forms.

DO [WHILE condition | UNTIL condition]
    statements
LOOP [WHILE condition | UNTIL condition]
' Pre-test
Do While count < 10
    count = count + 1
Loop

' Post-test
Do
    line$ = ReadLine()
Loop Until line$ = "quit"

' Infinite loop (exit with EXIT DO)
Do
    DoEvents
    If done Then Exit Do
Loop

WHILE...WEND

Simple pre-test loop (legacy form; prefer DO...LOOP).

WHILE condition
    statements
WEND
While Not EOF(1)
    Line Input #1, line$
    Print line$
Wend

Procedures

SUB...END SUB

Defines a subroutine (no return value).

SUB name ([BYVAL | BYREF] [OPTIONAL] param AS type, ...) [STATIC]
SUB name (arrayParam() AS type, ...)
    statements
END SUB
Sub Greet(ByVal name As String)
    Print "Hello, " & name
End Sub

Parameters are passed by reference by default (nested calls pass the same variable on, so a SUB called from a SUB can still change the original); BYREF may be written out to say so, and BYVAL selects value semantics. A by-reference parameter is the caller's variable itself, as in Visual Basic: a write to it changes the variable at once (the caller's code, or another parameter naming the same variable, sees the new value straight away, even if the procedure later stops with an error), and what is stored is converted to the variable's own type (a STRING * n keeps its length). This holds for a plain variable, an array element (`bump a(3)` changes `a(3)` in place), a TYPE field (`bump rec.count`, `bump recs(2).count`, `bump rec.inner.count`) and, inside a class, one of the class's own member variables. While an array element (or a field of one) is passed by reference, its array cannot be given a new size or erased: REDIM of that array, or ERASE of it when it is a dynamic array, raises error 10 (This array is fixed or temporarily locked), as in Visual Basic (ERASE of a fixed-size array only clears its elements and is allowed). The array is free again as soon as the call returns. Assigning a whole TYPE value to the variable (or element) whose field is being passed copies the value into the same record, so the parameter sees the new value (as in Visual Basic). A parameter written as name() receives a whole array by reference; the caller passes `arr()` (or just `arr`), and the SUB may index, REDIM or ERASE it. Use EXIT SUB to return early. A SUB is called either with or without parentheses; when used as a statement, parentheses are optional:

Greet "World"
Greet("World")
Call Greet("World")

As in Visual Basic and QBasic, a single argument in parentheses after the name of a SUB called without CALL (Bump (n), or Bump(n)) is an expression in parentheses, so it is passed by value: the SUB gets a copy and n is not changed. Write Bump n, or Call Bump(n), to pass n by reference.

An argument is converted to the type of a typed parameter (one declared with AS, a type suffix or a DEFtype rule). A value -- a literal, an expression, a variable in its own parentheses, or anything given to a BYVAL parameter -- is converted the way an assignment would convert it (Report 3.7 gives an Integer parameter 4). A variable, array element or TYPE field given to a by-reference parameter must have the parameter's own type, as in Visual Basic: an Integer parameter cannot be the caller's Double variable ("ByRef argument type mismatch" when the program is compiled); pass CINT(d), or (d) in its own parentheses, to pass a converted copy. A variable declared without a type (a Variant) holds any value and is passed as it is. Through an object variable declared As Object the procedure is only found when the program runs, so a variable of another type is passed as a converted copy instead.

Sub Fill(v() As Integer, ByRef count As Integer)
    ReDim v(9) As Integer
    v(9) = 7
    count = count + 1
End Sub

Dim a(3) As Integer
Dim n As Integer
Fill a(), n

Optional Parameters

Mark a parameter OPTIONAL to allow callers to omit it. An optional parameter must be positioned after all required parameters. A caller can leave out the optional parameters at the end, or any optional parameter in the middle by writing nothing between the commas: Report a, , c. A left-out parameter of a type receives that type's empty value (0, "", False, a date of 0, Nothing); a left-out Variant parameter is Missing, which ISMISSING detects. Leaving out a parameter that is not OPTIONAL is a compile error (Argument not optional).

Sub Announce(ByVal msg As String, Optional ByVal loud As Integer)
    If loud Then
        Print UCase$(msg)
    Else
        Print msg
    End If
End Sub

Announce "hello"            ' loud defaults to 0
Announce "hello", True      ' loud is -1

An OPTIONAL parameter can also name the value it takes when it is left out, after an equals sign: Optional count As Integer = 10. The default is a constant expression, like the value of a CONST: numbers, strings, dates, other constants and the built-in functions CONST allows, converted to the parameter's type (a value that does not fit is a compile error). A parameter with a default is never Missing -- ISMISSING is False for it -- whether it is left out at the end, skipped between commas, or the procedure is reached through an object. Defaults work for SUB and FUNCTION procedures and for the procedures and Property procedures of class modules, including calls written before the procedure itself. As in Visual Basic the default is the one the declaration being called gives: a call through an interface (a variable declared As the interface class) passes the interface's default, even when the implementing class declares another. An object parameter (As Object, As Control, As Form or As a class) can only have the default Nothing, as in Visual Basic: Optional target As Object = Nothing; a Variant parameter may have Nothing too. A default cannot be given to a required parameter, an array or a TYPE, or in DEF FN and DECLARE LIBRARY. A DECLARE SUB / FUNCTION line must say whether each parameter has a default, as its definition does.

Const SIDE = 10

Function Area(Optional w As Integer = SIDE, Optional h As Integer = SIDE * 2) As Long
    Area = w * h
End Function

Print Area()        ' 200
Print Area(2)       ' 40
Print Area(, 3)     ' 30

ISMISSING works as in Visual Basic: only an OPTIONAL Variant parameter without a default can be Missing, and a Missing value passed on to another procedure's OPTIONAL Variant parameter is still Missing there. ISMISSING of anything else is False. Using a Missing value in any other way -- in arithmetic, in text, or storing it in a typed variable -- raises error 448.

Sub Greet(ByVal name As String, Optional title As Variant)
    If IsMissing(title) Then
        Print "Hello, "; name
    Else
        Print "Hello, "; title; " "; name
    End If
End Sub

Greet "Ada"                 ' Hello, Ada
Greet "Ada", "Countess"     ' Hello, Countess Ada

Named Arguments

An argument can be given by the name of its parameter, followed by := and the value, as in Visual Basic. Named arguments come after any positional ones, in any order; the parameters left out must be OPTIONAL.

Sub Report(ByVal title As String, Optional ByVal width As Integer = 40, Optional ByVal footer As String = "")
    Print title; width; footer
End Sub

Report "Sales", footer:="(end)"          ' width is 40
Report width:=60, title:="Stock"
Print Mid$(String:="hello", Start:=2)    ' ello
MsgBox Prompt:="Saved", Title:="Notes"

Named arguments work for SUB and FUNCTION procedures, DEF FN functions, DECLARE LIBRARY procedures and the procedures of class modules (through a variable of the class, or through an Object or Variant variable), and for the built-in functions that Visual Basic gives argument names to: MsgBox (Prompt, Buttons, Title), InputBox (Prompt, Title, Default), Mid (String, Start, Length), Left and Right (String, Length), InStr (Start, String1, String2), InStrRev (StringCheck, StringMatch, Start, Compare), Replace (Expression, Find, Replace, Start, Count, Compare), Split (Expression, Delimiter, Limit, Compare), Join (SourceArray, Delimiter), Filter (SourceArray, Match, Include, Compare), StrComp (String1, String2, Compare), String (Number, Character), Format (Expression, Format), IIf (Expression, TruePart, FalsePart), DateAdd (Interval, Number, Date), DateDiff and DatePart (Interval, Date1 and Date2 or Date, FirstDayOfWeek, FirstWeekOfYear), DateSerial (Year, Month, Day), TimeSerial (Hour, Minute, Second), Weekday (Date, FirstDayOfWeek), WeekdayName (Weekday, Abbreviate, FirstDayOfWeek), MonthName (Month, Abbreviate), and a Collection's Add (Item, Key, Before, After), Item and Remove (Index).

A name the procedure does not have is a compile error (Named argument not found), and so is a parameter given twice. When the procedure is only found as the program runs (a method called through an Object or Variant variable) the same mistakes raise error 448 (Named argument not found) and error 450 (Wrong number of arguments). The methods of forms and controls do not take named arguments (error 446, Object doesn't support named arguments), and neither does a ParamArray parameter.

ParamArray

The last parameter of a SUB or FUNCTION can be marked PARAMARRAY to accept any number of extra arguments. It is written as an array, name(), and receives every remaining argument as an array numbered from 0. With no extra arguments the array is empty: UBOUND returns -1.

Sub PrintAll(ByVal title As String, ParamArray items())
    Dim i As Integer
    Print title;
    For i = 0 To UBound(items)
        Print " "; items(i);
    Next
    Print
End Sub

PrintAll "Totals:", 1, "two", 3.5    ' three items: 0 To 2
PrintAll "Nothing:"                  ' UBound(items) is -1

Function Sum(ParamArray n() As Double) As Double
    Dim i As Integer
    Dim total As Double
    For i = 0 To UBound(n)
        total = total + n(i)
    Next
    Sum = total
End Function

Without an AS clause (and no type suffix or DEFtype rule for the name) the ParamArray is an array of Variants (TYPENAME gives "Variant()"): each element holds the argument that was passed with its own type, so numbers, strings and objects can be mixed, and FOR EACH can walk it. With an AS clause every argument is converted to that type. An argument that is a variable, a whole array, an array element (a(i), m(i, j)), a TYPE field (rec.f, arr(i).f, rec.inner.f) or, inside a class, one of the class's own member variables is passed by reference, as in Visual Basic: the element of the ParamArray is that variable, so a write to it changes the variable at once, converted to the variable's type (a value that cannot be converted raises its error at the assignment), and passing the element on (Bump v(0)) passes the variable. With an AS clause an argument is passed by reference only when its own type is that type; others are converted and passed by value. The same holds for a class's methods, whether the object variable is declared as the class or As Object / As Variant. While the call runs, the arrays whose elements were given are locked: REDIM of one of them (or ERASE of a dynamic one) raises error 10, as for any array element passed by reference. Copying the ParamArray (keep = v) copies the values, not the variables. Expressions and object properties are passed by value. Leaving an argument out (Sum 1, , 3) gives a Missing element. A PARAMARRAY cannot be combined with OPTIONAL parameters, cannot be BYVAL or BYREF, cannot hold a TYPE, and takes at most 31 arguments. It is not available in DEF FN or DECLARE LIBRARY.

FUNCTION...END FUNCTION

Defines a function with a return value.

FUNCTION name ([BYVAL] [OPTIONAL] param AS type, ...) AS returnType [STATIC]
    statements
    name = returnValue
END FUNCTION

STATIC after the header keeps every local variable of the SUB or FUNCTION between calls (see STATIC).

Function Square(ByVal n As Double) As Double
    Square = n * n
End Function

Assign to the function name to set the return value. The value is converted to the function's type (AS clause, type suffix or DEFtype), so FUNCTION F AS INTEGER with F = 2.5 returns 2. Use EXIT FUNCTION to return early.

A FUNCTION can also be called as a statement, with or without parentheses; its result is discarded:

Function Beep2(ByVal n As Integer) As Integer
    Beep2 = n * 2
End Function

Beep2 3              ' result discarded

name(...) in an expression calls a FUNCTION; using a SUB there is a compile error.

Labels, GOSUB and Variables in Procedures

Labels belong to the SUB or FUNCTION they are written in (or to the module level). GOTO, GOSUB, ON ... GOTO/GOSUB and ON ERROR GOTO can only reach a label of the same procedure, and different procedures can reuse the same label name. GOSUB and RETURN work inside a procedure; see GOTO / GOSUB / RETURN. A procedure sees module variables only when they are SHARED; see Variable Scope and SHARED.

DEF FN

Defines a single-expression function. The function name begins with FN and is invoked just like a normal function. DEF FN functions cannot span multiple statements. A DEF FN must be defined before it is used, and only at module level (not inside a SUB or FUNCTION). Names in the expression other than the parameters are module variables, SHARED or not; the parameters are always passed by value.

DEF FNname(params) = expression
Def FnSquare(x) = x * x
Print FnSquare(5)     ' prints 25

Def FnCelsius(f As Double) = (f - 32) * 5 / 9
Print FnCelsius(212)  ' prints 100

Flow Control

EXIT

Exits the current block early.

EXIT FOR
EXIT DO
EXIT SUB
EXIT FUNCTION
EXIT PROPERTY

EXIT PROPERTY leaves a Property Get, Let or Set procedure of a class module (see Objects and Class Modules).

CALL

Explicitly calls a subroutine or function. The return value (if any) is discarded.

CALL name
CALL name(args)

Normally you can omit CALL and just use the name directly.

GOTO / GOSUB / RETURN

GOTO label
GOSUB label
RETURN

A label is a name followed by a colon at the start of a line, or a line number at the start of a line (see Line Numbers below). Labels belong to the SUB or FUNCTION they are in (module-level labels to the module level): a jump can only reach a label of the same procedure, the same label name can be used in several procedures, and a label may have the same name as a variable. A jump to a label that is not defined in the procedure, or to a SUB or variable name, is a compile error.

GOSUB records where it was called from, runs the code at the label, and RETURN goes back to the statement after the GOSUB. This works at module level and inside a SUB or FUNCTION alike. Each procedure call has its own set of pending GOSUBs: RETURN only returns from a GOSUB made in the same procedure call, and leaving the procedure (END SUB, EXIT SUB, EXIT FUNCTION or an error handled in a caller) discards the ones still pending. RETURN with no pending GOSUB raises error 3 (RETURN without GOSUB). To leave a SUB or FUNCTION, use EXIT SUB / EXIT FUNCTION.

GoSub Initialize
Print "Done"
End

Initialize:
    count = 0
    name$ = ""
Return
Sub Report(n As Integer)
    GoSub Heading
    Print "value"; n
    Exit Sub
Heading:
    Print "--- report ---"
    Return
End Sub

ON...GOTO / ON...GOSUB

Computed branch based on an integer expression.

ON expression GOTO label1, label2, ...
ON expression GOSUB label1, label2, ...

If the expression evaluates to 1, control goes to the first label; 2, the second; and so on. If out of range, execution falls through. The labels follow the same rules as GOTO and GOSUB (same procedure only).

Line Numbers

As in QBasic, a line can start with a line number, a whole number from 0 to 65529. A line number is a label: GOTO, GOSUB, ON ... GOTO / GOSUB, ON ERROR GOTO, RESUME and RESTORE can name it, it belongs to its procedure like any other label, and the same number cannot start two lines of a procedure. Numbers need not be in order, lines without a number are fine, and the number is read as a value, so 010 and 10 name the same line. IF can branch to a line number directly: IF x THEN 100 ELSE 200 is IF x THEN GOTO 100 ELSE GOTO 200, and IF x GOTO 100 works too.

10 INPUT "Guess"; g
20 IF g = 7 THEN 50
30 PRINT "No"
40 GOTO 10
50 PRINT "Yes"

In a program with line numbers, ERL gives the number of the last numbered line at or before the statement where the error happened (0 when there is none); in a program without them it gives the source line.

Input/Output Statements

PRINT

Writes expressions to the output window, or to a file channel. Once the program has used a console or graphics statement (see Console and Graphics), PRINT writes on the program's screen instead, at the cursor, in the current COLOR.

PRINT [expression [{; | ,} expression] ...]
PRINT #channel, expression [; expression] ...
PRINT USING format$; expression [; expression] ...

PRINT # writes numbers exactly as PRINT shows them, with the space after each number, so PRINT #1, 1; 2 writes "1 2 ". PRINT #n, with nothing after the comma writes an empty line.

Special functions inside PRINT:

Print "Name:"; Tab(20); name$
Print "X="; x, "Y="; y        ' comma = next 14-column zone
Print #1, "Written to file"

LPRINT

Prints on the printer instead of the screen. Everything PRINT accepts works the same way: ; and , between items, SPC, TAB and LPRINT USING. The printer keeps its own column for TAB and the 14-column zones.

LPRINT [expression [{; | ,} expression] ...]
LPRINT USING format$; expression [; expression] ...

The output goes to the printer chosen in the Control Panel (a printer port, or a file). Each LPRINT is sent at once, and lines end the way printers expect. Nothing starts a new page by itself: LPRINT CHR$(12) ejects the page. If the printer has a problem (out of paper, off line), the user is asked to fix it and choose Retry, or Cancel; after Cancel the LPRINT raises error 57. With no printer to print on, LPRINT raises error 68.

LPrint "Invoice"; Tab(40); Date$
LPrint Using "Total: $$####.##"; total
LPrint Chr$(12)                 ' eject the page

For a whole document with margins, a header, a footer and page numbers, and for the Print dialog, use the Printing Library (print.bas, see Include Libraries).

PRINT USING

PRINT USING formats each following expression according to a format string and prints the result. The expressions after the format are separated by ; or , (both work the same here). The format string is a mix of fields and literal text: each expression consumes the next field, the literal text before it is printed as it is, and the literal text after the last field is printed at the end. If more expressions are supplied than there are fields, the format string is reused from the start.

  Format character   Meaning
  ----------------   -------
  #                  Digit position; unused positions on the left become spaces
  0                  Digit position that is always printed (zero padded); the first 0 sets the minimum number of digits
  .                  Decimal-point position
  ,                  Insert thousands separator
  +                  At start or end: always show a sign character
  -                  At end: show a trailing minus sign only when negative
  **                 At start: fill leading spaces with asterisks
  $$                 At start: floating dollar sign
  ^^^^               Anywhere: format the value in scientific notation
  !                  First character of a string only
  &                  Entire string (variable length)
  \ ... \            Fixed-length string field (width = 2 + number of spaces between backslashes)
  _                  The next character is printed literally

A numeric field is as wide as its format characters; the value is right-aligned in it and a negative sign (or a leading +) floats directly in front of the first digit. A value that does not fit is printed in full with a leading %; a value too long to print in full is shown in scientific notation behind the %. A trailing + in a format with no digit positions is printed as literal text. A string expression must meet a string field and a numeric expression a numeric field, otherwise error 13 (Type mismatch) is raised.

Print Using "###.##"; -3.14159            ' " -3.14"
Print Using "+###"; 42                    ' " +42"
Print Using "$$#,##0.00"; 1234.5          ' " $1,234.50"
Print Using "**#,##0.00"; 42.5            ' "*****42.50"
Print Using "###"; 12345                  ' "%12345"
Print Using "####.####^^^^"; 0.000123     ' scientific notation
Print Using "\  \"; "Hello"               ' fixed-width 4-char: "Hell"
Print Using "& likes &"; name$; food$     ' "Scott likes pizza"
Print Using "Total: ###.## units"; 7.5    ' "Total:   7.50 units"
Print Using "## and ##"; 1; 2; 3          ' " 1 and  2 3 and "

INPUT

Reads a line of text from the user or from a file channel. The user types it in a dialog box, or on the program's screen once it has one (see Console and Graphics).

INPUT variable
INPUT "prompt"; variable
INPUT #channel, variable
Input "Enter your name: "; name$
Input #1, line$

The target may be a variable, an array element or a TYPE field (INPUT, INPUT #, LINE INPUT # and READ alike). INPUT and INPUT # read a number into a numeric target the way VAL does (12abc gives 12).

DATA / READ / RESTORE

Inline data pool for constants.

DATA value1, value2, "string", ...
READ variable1, variable2, ...
RESTORE [label]

DATA statements define a pool of values. READ reads the next value from the pool into a variable, array element or TYPE field. RESTORE resets the read pointer to the beginning; RESTORE label (or a line number) makes the next READ take the first DATA item at or after that label. An item in quotes is a string; an unquoted item is taken as raw text up to the next comma, colon, comment or end of line (so keywords, several words and text such as 12abc are read as they are written) and converted when READ into a numeric variable, which raises error 13 (Type mismatch) when the item is not a number. The most negative Integer and Long values (-32768, -2147483648) are accepted.

Data 10, 20, 30, "Hello"
Read a, b, c, msg$
Print a; b; c; msg$
Restore

Miscellaneous Statements

Error Handling

ON ERROR GOTO label     ' Enable error handler
ON ERROR GOTO 0         ' Disable error handler
ON ERROR RESUME NEXT    ' Go on at the next statement after any error
RESUME                  ' Retry the statement that caused the error
RESUME NEXT             ' Continue at the next statement after the error
RESUME label            ' Continue at a label or line number (RESUME 0 is RESUME)
ERROR n                 ' Raise a runtime error with error number n

The ERR keyword returns the current error number (a Long) in expressions and ERL the source line the error was raised on, or in a program with line numbers the last line number at or before it (both are 0 when no error is active, and both reset after RESUME). RESUME or RESUME NEXT executed while no error is active raises error 20 (RESUME without error). ERROR n raises error n with its standard message (ERROR 11 reports "Division by zero"); numbers without a standard message report "User-defined error".

Each SUB and FUNCTION has its own ON ERROR handler:

ON ERROR RESUME NEXT, as in Visual Basic, needs no handler: a statement that fails is abandoned and the program goes on at the next one, with ERR (Err.Number) and Err.Description telling what went wrong. An error in a procedure that has no handler of its own leaves that procedure, and the program goes on after the statement that called it. The statement clears ERR, and so does the end of the procedure that used it; check ERR right after the statements that may fail:

On Error Resume Next
Kill "old.tmp"
If Err.Number <> 0 Then Print "Not deleted: "; Err.Description
Err.Clear
On Error GoTo 0

The Err Object

Err holds the current error the way ERR and ERROR do:

  Member                                    Meaning
  ------                                    -------
  Err or Err.Number                         The error number (0 when there is none); Err.Number = n sets it without raising it
  Err.Description                           The error's message ("" when there is none)
  Err.Source                                The source text the last Err.Raise gave ("" otherwise)
  Err.Raise number [, source [, desc]]      Raises error number (1 to 65535) with that source and description; without a description the number's standard message
  Err.Clear                                 Clears the error: ERR becomes 0, the description and source ""

ERROR$(n) (or ERROR(n)) gives the standard message of error number n, "User-defined error" for a number without one and "" for 0; without an argument, the current error's message.

On Error GoTo Failed
Err.Raise 1001, "Loader", "The file has no header"
Exit Sub
Failed:
    Print Err.Number; Err.Description; " ("; Err.Source; ")"
    Resume Next

RESUME NEXT continues after the failing statement. When the error happened in the condition of an IF, ELSEIF, WHILE, DO or LOOP, the condition counts as false (the block is skipped, the loop is left); after an error in a FOR statement the loop is skipped; after an error in the SELECT CASE expression the whole SELECT CASE block is skipped; after an error in a CASE test that test counts as false (the next value or CASE is tried); after an error in an ON ... GOTO/GOSUB selector no branch is taken and execution continues with the next statement.

On Error GoTo ErrorHandler
Open "missing.txt" For Input As #1
Exit Sub

ErrorHandler:
    Print "Error number:"; Err; "on line"; Erl
    Resume Next

Common Error Numbers

  Number   Meaning
  ------   -------
  1        FOR loop error (NEXT without FOR, NEXT variable mismatch, FOR stack underflow)
  3        RETURN without GOSUB
  4        Out of DATA
  5        Illegal function call (bad argument to a built-in function; an undefined math result such as a negative number to a fractional power)
  6        Overflow (value does not fit the target type; EXP, ^ or other math leaving the numeric range)
  7        Out of memory
  9        Subscript out of range / invalid variable or field index
  10       This array is fixed or temporarily locked (REDIM, or ERASE of a dynamic array, while one of its elements, or a field of one, is passed by reference to a procedure that is still running)
  11       Division by zero
  13       Type mismatch (text that is not a number where a number is needed) / not an array / not a TYPE instance
  14       Out of string space (no memory to build a string)
  20       RESUME without error
  26       FOR loop nesting too deep
  28       Out of stack space (calls or expressions nested too deeply)
  51       Internal error (bad opcode)
  52       Bad file number or file not open
  53       File not found (OPEN for INPUT, KILL, FILELEN, ...)
  54       Bad file mode (also: a printer opened for anything but OUTPUT or APPEND)
  57       Device I/O error (printing failed or was cancelled)
  58       File already exists or rename failed
  59       Bad record length (OPEN ... LEN must be 1 to 32767; GET/PUT data longer than LEN)
  63       Bad record number (SEEK, GET or PUT position below 1)
  64       Bad file name (WIDTH of a device DVX does not have)
  67       Too many files open
  68       Device unavailable (no printer to print on)
  75       Path/file access error
  76       Path not found
  91       Object variable not set (property, method, Show/Hide/Unload on a value that is not a form or control, or on Nothing)
  93       Invalid pattern string (a LIKE pattern with a [ that has no ])
  94       Invalid use of Null (Null where a real number or text is needed; see Variants)
  424      Object required (SET, Is or TypeOf with a value that is not an object)
  438      Object doesn't support this property or method (the object has no member of that name, or it is Private)
  446      Object doesn't support named arguments (a form or control method called with Name:=value)
  448      Named argument not found (a Name:= the method does not have; a left-out OPTIONAL Variant argument, Missing, used as a value)
  449      Argument not optional (a method call through an object left out a parameter that is not OPTIONAL)
  450      Wrong number of arguments or invalid property assignment
  451      Object not a collection (FOR EACH over an object that is not a Collection)
  457      This key is already associated with an element of this collection (Collection.Add with a key in use)
  481      Invalid picture (LOADPICTURE of a file that is not a picture DVX can show)
  1000     No form runtime (a form or control statement ran without the form runtime, e.g. under a headless runner)

SHELL

Executes an operating-system command.

SHELL "command"

When used as a function, SHELL returns the exit code of the command.

Shell "DIR /B"
exitCode = Shell("COPY A.TXT B.TXT")

SLEEP

Pauses execution for the given number of seconds. With no argument, sleeps for 1 second. The desktop and the program's own forms keep running while it sleeps, SLEEP 0 just lets pending events run, and closing the program ends the sleep.

SLEEP [seconds]

RANDOMIZE

Seeds the random number generator. Without an argument (not shown here) and without a prior RANDOMIZE, the sequence is the same on every run. Use RANDOMIZE TIMER to get a different sequence each run.

RANDOMIZE seed
RANDOMIZE TIMER          ' Seed from system clock

END

Terminates program execution immediately. Any form that is loaded is unloaded before the program exits.

END

Sound, Joysticks and Frames

These statements work as they do in QBasic, on whatever sound hardware the computer has: a sound card, the PC speaker, or none at all, in which case the program runs the same but silently. Several programs can make sound at once. For sound files, tones of any shape and music files, see the sound.bas and music.bas include libraries; for more joystick detail, joystick.bas.

BEEP

Sounds a short beep (800 hertz for a quarter of a second).

BEEP

SOUND

Plays a tone of frequency hertz (37 to 32767) for duration clock ticks; there are 18.2 ticks in a second, and fractions are allowed. A duration of 0 stops every sound the program has queued. Frequencies too high to hear (above 20000) are silent. Anything out of range is error 5 (Illegal function call).

SOUND frequency, duration
SOUND 440, 18.2       ' A for one second
SOUND 440, 0          ' stop

PLAY

Plays a tune written in the music macro language. Letters may be upper or lower case and spaces are ignored. The settings (octave, length, tempo, style, instrument, foreground or background) stay from one PLAY to the next.

PLAY commands$
PLAY "T160 O3 L8 E D C D E E E4"
  Command     Meaning
  -------     -------
  A to G      Play the note in the current octave. Follow it with # or + for sharp, - for flat, then optionally a length (1 to 64, as for L) and dots.
  N n         Play note n (1 to 84, seven octaves from the lowest C); N0 is a rest.
  O n         Octave 0 to 6 (default 4). Octave 3 starts at middle C.
  > and <     Go up or down one octave.
  L n         Length of the notes that follow: 1 a whole note, 2 a half, 4 a quarter (the default) ... 64.
  P n         Pause (rest) of length n (1 to 64).
  .           A dot after a note or pause makes it half as long again; each further dot adds half again.
  T n         Tempo in quarter notes a minute (32 to 255, default 120).
  MN          Music normal: each note sounds for 7/8 of its length (the default).
  ML          Music legato: notes sound for their whole length.
  MS          Music staccato: notes sound for 3/4 of their length.
  MF          Music foreground: PLAY, SOUND and BEEP wait until the sound has finished (the default).
  MB          Music background: the program goes on while the music plays; it only waits when more than 32 notes are waiting.
  I n         DVX's own: play the notes that follow on General MIDI instrument n (1 to 128; 1 is the piano, 41 the violin, 74 the flute) through the music synthesizer. I0 goes back to plain tones (the default).
  X           "X" + VARPTR$(s$) plays the commands in s$ at that point (s$ may use X itself, up to 16 levels deep).
  =           Any number above may be written as "=" + VARPTR$(n), n a numeric expression: "T=" + VARPTR$(tempo).

A string with a mistake in it plays nothing and raises error 5 (Illegal function call). X and "=" work as in QBasic, with VARPTR$ as for DRAW (see the program screen's DRAW): the value is taken when VARPTR$ runs. A whole tune may be at most 32767 characters once X and "=" are filled in.

verse$ = "L8 E D C D E E E4"
tempo = 160
PLAY "T=" + VARPTR$(tempo) + "O3 X" + VARPTR$(verse$) + "X" + VARPTR$(verse$)

Building the string with + works too, such as PLAY "O" + STR$(n). Without I, the notes are square-wave tones like the PC speaker's; with it, they play on the same synthesizer as MIDI music.

PLAY "MB T120 L4 CDEF GAB>C"   ' a scale in the background
PLAY "I74 O4 L8 GAB>C"         ' on the flute

PLAY Function

PLAY(n) returns how many notes are still waiting to be played in the background (n is ignored). A game can use it to keep its music going:

If PLAY(0) < 4 Then PLAY "MB " + tune$

STICK and STRIG

STICK(n) returns where a joystick points, from 1 (all the way left or up) to 200 (all the way right or down), about 100 in the middle, or 0 when there is no such joystick. STICK(0) reads joystick A's X and remembers A's Y and joystick B's X and Y, which STICK(1), STICK(2) and STICK(3) then return; so call STICK(0) first.

STRIG(n) returns True (-1) or False (0) for the buttons:

  n     Returns True when
  -     -----------------
  0     joystick A's first button was pressed since the last STRIG(0)
  1     joystick A's first button is down
  2     joystick B's first button was pressed since the last STRIG(2)
  3     joystick B's first button is down
  4     joystick A's second button was pressed since the last STRIG(4)
  5     joystick A's second button is down
  6     joystick B's second button was pressed since the last STRIG(6)
  7     joystick B's second button is down

Joystick A is the first joystick; joystick B the second one, or the second stick of a joystick with four axes. When no joystick is connected the keyboard stands in for joystick A (see the Control Panel's Game Controllers tab). STRIG ON, STRIG OFF and ON STRIG are not supported; test STRIG in a Timer or a loop instead.

x = STICK(0)
y = STICK(1)
If STRIG(0) Then FireShot

FRAMEWAIT

Waits until the next frame of a steady clock of rate frames a second begins, keeping the desktop and the program's forms running meanwhile. A game loop that calls it once a frame runs at the same speed on every computer. Frames the program was too busy for are skipped, not caught up. rate must be at least 1; rates above 1000 count as 1000. Changing the rate starts the clock over.

FRAMEWAIT rate

Do
    MoveEverything
    DrawEverything
    FRAMEWAIT 30
Loop Until quitting

Console and Graphics

These statements work as they do in QBasic. The first one a program uses gives it a screen of its own: a window, titled with the program's name, the size of the screen mode. From then on PRINT and INPUT use that screen too (before it, PRINT writes to the output window and INPUT asks in a dialog box, as always). Keys typed in the window go to INKEY$ and INPUT. The window stays open when the program's code has finished, so its output can be read; closing it ends the program.

The names are not reserved: a program that has its own variable, SUB or constant called Color, Cls, Draw and so on keeps using it.

Screen Modes

  Mode       Size and colours                     Text (WIDTH choices)     Pages
  ----       ----------------                     --------------------     -----
  SCREEN 0   Text only, 16 colours                80 or 40 x 25, 43 or 50  8 (4 at 80 x 43, 80 x 50)
  SCREEN 1   320 x 200, 4 colours (two palettes)  40 x 25                  1
  SCREEN 2   640 x 200, 2 colours                 80 x 25                  1
  SCREEN 7   320 x 200, 16 colours                40 x 25                  8
  SCREEN 8   640 x 200, 16 colours                80 x 25                  4
  SCREEN 9   640 x 350, 16 of 64 colours          80 x 25 or 80 x 43       2
  SCREEN 10  640 x 350, 4 shades (some blinking)  80 x 25 or 80 x 43       2
  SCREEN 11  640 x 480, 2 colours                 80 x 30 or 80 x 60       1
  SCREEN 12  640 x 480, 16 colours                80 x 30 or 80 x 60       1
  SCREEN 13  320 x 200, 256 colours               40 x 25                  1

A program starts in SCREEN 0. SCREEN with a new mode (and WIDTH) clears the screen and restores the mode's colours: the 16 standard colours, and in SCREEN 13 the standard 256-colour palette. SCREEN with the mode the program is already in only changes the pages, so a program can flip pages in a loop. Other mode numbers, and graphics statements in SCREEN 0, are error 5 (Illegal function call). The colour switch argument is accepted and ignored.

Text uses 16-pixel-high characters in SCREEN 0 (25 rows), 11 and 12 (30 rows), 14-pixel ones in SCREEN 9 and 10 (25 rows) and 8-pixel ones everywhere else. The window shows each mode in the shape it has on a monitor: the 640 x 200 modes with every line doubled, 40-column text with every column doubled; SCREEN 9 and 10 show at 640 x 350 as they are. On the whole screen the 320 x 200 modes use the computer's 320 x 200 mode and the others the nearest mode, centred.

SCREEN mode [, [colorswitch] [, [activepage] [, visualpage]]]
WIDTH [columns] [, rows]

Screen Pages and PCOPY

The pages of a mode (see the table) are separate screens. Drawing and PRINT go to the active page; the window shows the visual page. Drawing on a page that is not shown and then showing it (or copying it to the shown page) gives smooth animation. A visual page left out follows the active page. In SCREEN 0 each page has its own text. Each page also keeps its own text cursor, as in QBasic: LOCATE and PRINT move the active page's cursor, and switching pages brings back the cursor where it was on that page.

SCREEN 7, , 1, 0            ' draw on page 1, show page 0
Do
    CLS
    CIRCLE (x, 100), 20, 14
    PCOPY 1, 0              ' show the finished picture
    x = (x + 2) MOD 320
    FRAMEWAIT 30
Loop

PCOPY source, destination copies one page (text and pixels) onto another. A page number the mode does not have is error 5.

FULLSCREEN

Shows the program's screen on the whole screen, or back in its window. Alt+Enter in the window does the same. While the program has the whole screen, Alt+Tab brings the desktop back (the program keeps running in its window) and switching back to the program returns it to the whole screen. Other programs keep running either way. When the computer has no suitable video mode, the screen stays in its window.

FULLSCREEN [ON | OFF]
FULLSCREEN expression      ' True: whole screen, False: window

Text: CLS, LOCATE, COLOR, CSRLIN, POS, SCREEN( )

CLS [n]
LOCATE [row] [, [column] [, cursor]]
COLOR [foreground] [, background]
row = CSRLIN
column = POS(0)
code = SCREEN(row, column [, colorflag])

VIEW PRINT

Makes rows top to bottom the text viewport: PRINT scrolls only those rows, so the rows around them stay as they are (a title, a status line). The cursor goes to the viewport's first row. VIEW PRINT alone makes the whole screen the viewport again. LOCATE can still reach every row.

VIEW PRINT [top TO bottom]

INKEY$

Returns the next key typed in the program's window without waiting: "" when there is none, one character for a character key, and CHR$(0) + CHR$(scan code) for other keys (arrows, function keys). Keys held with Alt, and function keys held with Shift, Ctrl or Alt, give the codes QBasic gives: Alt+A is CHR$(0) + CHR$(30), Alt+1 CHR$(0) + CHR$(120), Shift+F1 CHR$(0) + CHR$(84), Ctrl+F1 CHR$(0) + CHR$(94) and Alt+F1 CHR$(0) + CHR$(104). Keys wait for INKEY$ in a queue of 64.

Do
    k$ = INKEY$
Loop While k$ = ""
If k$ = Chr$(0) + Chr$(72) Then Print "Up arrow"

PEN

QBasic's light pen; the mouse on the program's screen stands in for it, as the mouse drivers of the time did. PEN ON lets the program read it, PEN OFF stops that (PEN STOP is accepted too). PEN(n) then tells:

  n      PEN(n)
  -      ------
  0      True (-1) if the left button went down since PEN(0) was last read, else 0
  1, 2   x and y (pixels) where it last went down
  3      True (-1) while the left button is down, else 0
  4, 5   x and y where the mouse last was over the screen
  6, 7   text row and column where it last went down
  8, 9   text row and column where it last was

PEN(n) before PEN ON, after PEN OFF, or with another n raises error 5.

Screen 12
Pen On
Do
    If Pen(0) Then PSet (Pen(1), Pen(2)), 14
Loop While InKey$ = ""

INPUT and LINE INPUT on the Screen

On the program's screen INPUT shows its prompt at the cursor and reads what is typed there: Backspace takes back a character, Esc clears the line and Enter ends it. LINE INPUT reads a whole line, commas included, without adding "? " to the prompt. Without the program's screen LINE INPUT asks in a dialog box, like INPUT.

LINE INPUT ["prompt";] variable$

Graphics Coordinates

Points are (x, y) in pixels from the top-left corner. STEP(x, y) is relative to the last point drawn (the centre of the screen at first). VIEW makes a smaller part of the screen the drawing area (coordinates start at its corner, and drawing stays inside it); WINDOW gives it coordinates of your own. Colour numbers are attributes: 0 to 3 in SCREEN 1 and 10, 0 and 1 in SCREEN 2 and 11, 0 to 15 in SCREEN 7, 8, 9 and 12, 0 to 255 in SCREEN 13; anything else is error 5.

VIEW [[SCREEN] (x1, y1)-(x2, y2) [, [fill] [, border]]]
WINDOW [[SCREEN] (x1, y1)-(x2, y2)]
value = PMAP(coordinate, n)

PSET, PRESET, POINT

PSET [STEP](x, y) [, color]
PRESET [STEP](x, y) [, color]
c = POINT(x, y)
v = POINT(n)

PSET draws a point in the given colour or the COLOR foreground, PRESET in the given colour or colour 0. POINT(x, y) is the colour at a point, or -1 outside the view. POINT(0) and POINT(1) are the last point in pixels, POINT(2) and POINT(3) in WINDOW coordinates.

LINE

LINE [[STEP](x1, y1)]-[STEP](x2, y2) [, [color] [, [B | BF] [, style]]]

Draws a line, a box (B) or a filled box (BF). Without a start point the line starts at the last point. style is a 16-bit pattern: each set bit (from the top) draws a pixel, each clear one skips it.

LINE (10, 10)-(100, 50), 4, BF
LINE -STEP(20, 0), 15
LINE (0, 100)-(319, 100), 7, , &HF0F0

CIRCLE

CIRCLE [STEP](x, y), radius [, [color] [, [start] [, [end] [, aspect]]]]

Draws a circle, an ellipse or an arc. start and end are angles in radians (0 to 2 * pi, counterclockwise from the right); a negative angle also draws the radius to that end, so CIRCLE can draw pie slices. aspect is the height divided by the width; the default makes circles round on a 4:3 monitor (0.83 in SCREEN 13, 1 in SCREEN 12), so in SCREEN 13 a circle in the window looks slightly flat and a round one needs aspect 1.

CIRCLE (160, 100), 50, 14
CIRCLE (160, 100), 50, 4, -0.0001, -1.5708    ' a quarter pie slice
CIRCLE (160, 100), 80, 2, , , 0.5              ' an ellipse

PAINT

PAINT [STEP](x, y) [, [color] [, border]]
PAINT [STEP](x, y), tile$ [, [border] [, background$]]

Fills the area around the point with color, up to pixels of the border colour (by default the fill colour itself).

With a string instead of a colour, PAINT fills the area with a pattern, as in QBasic. Each row of the pattern is one byte for each colour plane of the mode, and each bit is a pixel (the first bit is the left pixel): in SCREEN 2 and 11 one byte is eight pixels, colour 0 or 1; in SCREEN 7, 8, 9 and 12 four bytes (the blue, green, red and bright planes) make eight pixels of 16 colours; in SCREEN 10 two bytes. In SCREEN 1 each byte is four pixels of two bits, and in SCREEN 13 each byte is one pixel. A pattern has up to 64 rows and repeats over the screen. The fill stops at the border colour (by default the COLOR foreground) and covers the whole area once, even where it already has the pattern's colours. background$ is accepted as in QBasic: a pattern with more than two rows in a row equal to it is error 5.

SCREEN 12
LINE (0, 0)-(100, 100), 15, B
PAINT (50, 50), CHR$(&HAA) + CHR$(&H55) + CHR$(0) + CHR$(0), 15      ' blue and green stripes

DRAW

Draws with a small command language. Letters may be upper or lower case; spaces and semicolons are ignored.

  Command     Meaning
  -------     -------
  U n         Up n (without n: 1).
  D n         Down n.
  L n         Left n.
  R n         Right n.
  E n         Diagonally up and right.
  F n         Diagonally down and right.
  G n         Diagonally down and left.
  H n         Diagonally up and left.
  M x,y       Move to x, y; with a sign (M+10,-5) move by that much.
  B           Before a move: move without drawing.
  N           Before a move: draw, then come back to where the move started.
  C n         Colour of the lines that follow.
  S n         Scale: moves are n/4 pixels a unit (1 to 255, default 4).
  A n         Turn the directions by n * 90 degrees (0 to 3).
  TA n        Turn the directions by n degrees (-360 to 360).
  P c,b       PAINT at the current point with colour c up to border colour b.

The pen starts at the last point and stays where it ends. The colour, scale and turn stay from one DRAW to the next. A mistake in the string is error 5.

As in QBasic, X runs another DRAW string and "=" takes a number, both given with VARPTR$: DRAW "X" + VARPTR$(shape$) and DRAW "C=" + VARPTR$(c) + "R=" + VARPTR$(n). DVX BASIC has no memory addresses, so VARPTR$ packs the value itself into its result (taken when VARPTR$ runs), and it takes any expression. Building the string with + and STR$ works too, such as DRAW "R" + STR$(n).

DRAW "BM100,100 C14 R50 D50 L50 U50"      ' a square
DRAW "BM160,100 TA45 C2 R40"              ' a line at 45 degrees
box$ = "R10 D10 L10 U10"
FOR i = 1 TO 5
    DRAW "BM" + STR$(i * 20) + ",20 X" + VARPTR$(box$)
NEXT i

PALETTE

PALETTE [attribute, color]
PALETTE USING array[(first)]

Changes the colour an attribute shows. In SCREEN 11, 12 and 13, color is blue * 65536 + green * 256 + red with each part 0 to 63; in SCREEN 0 and 9 it is an EGA colour number 0 to 63; in SCREEN 1, 2, 7 and 8 one of the 16 standard colours; in SCREEN 10 a shade 0 to 8 (0 off, 4 grey, 8 bright, and 1 to 3, 5 to 7 blinking between two of them). PALETTE alone restores the mode's colours. PALETTE USING sets every attribute of the mode (256 in SCREEN 13) from a one-dimensional LONG array starting at element first (or its first element); -1 leaves that attribute as it is. On the whole screen a palette change shows at once, like on a VGA card; in the window, whatever is already drawn in that attribute changes colour too.

SCREEN 13
PALETTE 1, 63 * 65536        ' attribute 1 becomes bright blue
FOR i = 0 TO 63
    PALETTE 2, i             ' a red that fades in
    FRAMEWAIT 30
NEXT i

Example

SCREEN 13
CLS
COLOR 14
PRINT "Press a key"
CIRCLE (160, 100), 60, 4
PAINT (160, 100), 1, 4
LINE (0, 0)-(319, 199), 15, B
DRAW "BM150,90 C15 R20 D20 L20 U20"
Do
Loop While INKEY$ = ""
FULLSCREEN
Do
Loop While INKEY$ = ""

File I/O

OPEN

Opens a file for reading, writing, or appending.

OPEN filename$ FOR INPUT AS #channel
OPEN filename$ FOR OUTPUT AS #channel
OPEN filename$ FOR APPEND AS #channel
OPEN filename$ FOR RANDOM AS #channel [LEN = recordSize]
OPEN filename$ FOR BINARY AS #channel
  Mode      Description
  ----      -----------
  INPUT     Open for sequential reading. File must exist.
  OUTPUT    Open for sequential writing. Creates or truncates.
  APPEND    Open for sequential writing at end of file.
  RANDOM    Open for random-access record I/O. LEN sets the record size in bytes (default 128).
  BINARY    Open for raw binary I/O.

Printing Through OPEN

The names LPT1:, LPT2:, LPT3: (a printer port) and PRN (the printer chosen in the Control Panel) open a printer, in any case and with or without the colon. Only OUTPUT and APPEND work (anything else raises error 54). PRINT # and WRITE # collect the output, and CLOSE sends it to the printer; a printer problem the user cancels makes CLOSE raise error 57, and a printer that cannot be reached makes OPEN raise error 68.

Open "LPT1:" For Output As #1
Print #1, "Line one"
Print #1, "Line two"
Close #1                        ' now it prints

CLOSE

Closes open file channels.

CLOSE #channel
CLOSE #channel, #channel, ...
CLOSE
RESET

CLOSE with a list closes each channel in it (the # is optional); CLOSE alone, and RESET, close every open file. Closing a channel that is not open does nothing; a number outside the channels DVX has raises error 52.

PRINT #

Writes text to a file, formatted exactly as PRINT shows it: numbers are followed by a space, a comma moves to the next 14-column zone, a semicolon keeps the line going, and TAB(n), SPC(n) and PRINT #channel, USING work as they do for PRINT. See PRINT.

PRINT #channel, expression [; | , expression ...]
PRINT #channel, USING format$; expression [; expression ...]

WIDTH #

Sets the line width of an open file, the screen or the printer: output longer than the width goes on in a new line, as in QBasic. 255 means no limit (the default).

WIDTH #channel, width
WIDTH "SCRN:", width
WIDTH "LPT1:", width
WIDTH LPRINT width

WIDTH "SCRN:" is the same as WIDTH width for the program's screen. WIDTH "LPT1:" (LPT2:, LPT3:, PRN) and WIDTH LPRINT set the width of the printer's lines, for LPRINT and for files opened on that printer afterwards. A width outside 1 to 255 raises error 5, a file number that is not open error 52, and a device DVX does not have (such as "COM1:") error 64.

INPUT #

Reads comma-delimited data from a file, one field per variable. Quoted strings written by WRITE # are read back without their quotes; numeric variables receive the converted value.

INPUT #channel, variable [, variable ...]
Open "data.txt" For Input As #1
Input #1, name$, age%, score#
Close #1

LINE INPUT #

Reads an entire line from a file into a string variable.

LINE INPUT #channel, variable$

WRITE #

Writes comma-delimited data to a file. Strings are enclosed in quotes, numbers are undecorated. Each statement writes a newline at the end.

WRITE #channel, expr1, expr2, ...
Write #1, "Scott", 42, 3.14
' Output: "Scott",42,3.14

GET / PUT

Read and write records in RANDOM or BINARY mode files. When recordNum is omitted the transfer starts at the current file position.

GET #channel, [recordNum], variable
PUT #channel, [recordNum], variable

In RANDOM mode recordNum is a 1-based record number and each record is LEN bytes (see OPEN). Numbers are stored in their binary form (Byte 1 byte, Integer and Boolean 2, Long 4, Single 4, Double, Currency and Date 8); a String is stored as a 2-byte length followed by its characters. PUT always writes a whole record, padding the unused part with zero bytes, and GET always advances to the next record; data longer than LEN raises error 59 before anything is written.

In BINARY mode recordNum is a 1-based byte position. Numbers are stored as in RANDOM mode. PUT writes the characters of a String with no length prefix, and GET reads as many bytes as the String variable currently holds, so set its length first (for example with SPACE$ or by declaring it as STRING * n).

The variable may be a TYPE variable. Its fields are packed in declaration order with the sizes above; a STRING * n field takes exactly n bytes (padded with spaces), a variable-length String field is stored with its 2-byte length prefix in both modes, and nested TYPE fields are packed inline. GET fills the fields of the existing variable in place.

The variable may also be an array element, arr(i), of any type including a TYPE: PUT writes that element and GET reads into it. The index expression is evaluated once.

Type RecT
    id    As Integer
    score As Double
    nm    As String * 6
End Type
Dim r As RecT
Open "recs.dat" For Random As #1 Len = 32
r.id = 1
Put #1, 1, r            ' 16 bytes of fields, padded to a 32-byte record
Get #1, 1, r
Close #1
Dim buf As String
Open "raw.bin" For Binary As #1
buf = Space$(16)
Get #1, 1, buf          ' read bytes 1-16
Put #1, 33, "TAG"       ' write 3 bytes at position 33
Close #1

SEEK

Sets the file position. As a function, returns the current position. On a RANDOM file the position is a record number (statement and function); on other files it is a 1-based byte position. A position below 1 raises error 63 (Bad record number).

SEEK #channel, position       ' Statement: set position
pos = SEEK(channel)           ' Function: get current position

File System Statements

DVX BASIC provides statements for working with the file system -- creating, deleting, renaming, and copying files and directories, and reading or setting file attributes.

KILL

Deletes a file.

KILL filename$
Kill "temp.bak"

NAME ... AS

Renames (or moves) a file.

NAME oldName$ AS newName$
Name "draft.txt" As "final.txt"

FILECOPY

Copies a file. If the destination already exists it is overwritten.

FILECOPY source$, destination$
FileCopy "data.db", "data.bak"

MKDIR / RMDIR

Creates or removes a directory.

MKDIR path$
RMDIR path$
MkDir App.Data & "\backups"
RmDir "C:\OLD"

CHDIR / CHDRIVE

Changes the current working directory or drive.

CHDIR path$
CHDRIVE drive$
ChDir "C:\DVX\PROJECTS"
ChDrive "D"

GETATTR / SETATTR

GETATTR returns the attributes of a file (as a function). SETATTR sets them (as a statement). Attributes are a bitmask of the vb file-attribute constants. A missing file raises error 53 (File not found); SETATTR raises error 75 when the attributes cannot be changed.

attrs = GETATTR(filename$)
SETATTR filename$, attrs
  Constant       Value    Attribute
  --------       -----    ---------
  vbNormal       0        Normal file (no attributes set)
  vbReadOnly     1        Read-only
  vbHidden       2        Hidden
  vbSystem       4        System file
  vbDirectory    16       Entry is a directory
  vbArchive      32       File has been modified since last backup
If (GetAttr("readme.txt") And vbReadOnly) <> 0 Then
    Print "File is read-only."
End If

SetAttr "secret.dat", vbHidden + vbReadOnly

CURDIR$ / DIR$

CURDIR$ returns the current directory. DIR$ returns the first file matching a pattern; subsequent calls with no arguments return additional matches (or "" when done). DIR$ returns only files: never ".", ".." or subdirectories.

cwd$ = CURDIR$
first$ = DIR$("*.txt")
WHILE first$ <> ""
    Print first$
    first$ = DIR$        ' next match, no argument
WEND

FILELEN

Returns the length of a file in bytes. A file that does not exist raises error 53 (File not found).

bytes = FILELEN(filename$)

String Functions

  Function                                                     Returns        Description
  --------                                                     -------        -----------
  ASC(s$)                                                      Integer        ASCII code of the first character of s$ (error 5 for an empty string)
  CHR$(n)                                                      String         Character with ASCII code n
  FILTER(arr, match$ [, include [, compare]])                  String array   The elements of arr that contain match$ (or, with include False, that do not)
  FORMAT$(value [, fmt$])                                      String         Formats a number or a date using a format string
  HEX$(n)                                                      String         Hexadecimal representation of n (uppercase, no leading &H)
  INSTR(s$, find$)                                             Long           Position of find$ in s$ (1-based), 0 if not found
  INSTR(start, s$, find$)                                      Long           Search starting at position start (1-based)
  INSTRREV(s$, find$ [, start [, compare]])                    Long           Position of the last find$ in s$ that ends at or before start (default: the end), 0 if not found
  JOIN$(arr [, delim$])                                        String         The elements of a one-dimensional array joined with delim$ between them (default: a space)
  LCASE$(s$)                                                   String         Converts s$ to lowercase
  LEFT$(s$, n)                                                 String         Leftmost n characters of s$
  LEN(s$)                                                      Long           Length of s$ in characters
  LTRIM$(s$)                                                   String         Removes leading spaces from s$
  MID$(s$, start)                                              String         Substring from start (1-based) to end of string
  MID$(s$, start, length)                                      String         Substring of length characters starting at start
  OCT$(n)                                                      String         Octal representation of n (no leading &O)
  REPLACE$(s$, find$, repl$ [, start [, count [, compare]]])   String         s$ from position start (default 1) on, with the first count (default all) occurrences of find$ replaced by repl$
  RIGHT$(s$, n)                                                String         Rightmost n characters of s$
  RTRIM$(s$)                                                   String         Removes trailing spaces from s$
  SPACE$(n)                                                    String         String of n spaces (n up to 65535)
  SPLIT(s$ [, delim$ [, limit [, compare]]])                   String array   The pieces of s$ between occurrences of delim$ (default: a space), at most limit of them (default: all)
  STRCOMP(a$, b$ [, compare])                                  Integer        -1 if a$ sorts before b$, 0 if they are equal, 1 if a$ sorts after b$
  STR$(n)                                                      String         Converts number n to string (leading space for non-negative)
  STRING$(n, char)                                             String         String of n copies of char (char can be an ASCII code or single-character string; n up to 65535)
  STRREVERSE$(s$)                                              String         s$ with its characters in reverse order
  TRIM$(s$)                                                    String         Removes leading and trailing spaces from s$
  UCASE$(s$)                                                   String         Converts s$ to uppercase
  VAL(s$)                                                      Double         Converts string s$ to a numeric value; stops at first non-numeric character

A negative count or position passed to LEFT$, RIGHT$, MID$, SPACE$ or STRING$, or a count above 65535 passed to SPACE$ or STRING$, raises error 5 (Illegal function call). INSTR follows OPTION COMPARE TEXT (a case-insensitive search), and an INSTR start position below 1 raises error 5.

REPLACE$, JOIN$ and STRREVERSE$ may also be written without the $. Items in square brackets may be left out.

Comparing Text

The compare argument of FILTER, INSTRREV, REPLACE$, SPLIT and STRCOMP chooses how text is matched: vbBinaryCompare (0) matches exactly, vbTextCompare (1) ignores upper and lower case, and vbUseCompareOption (-1, the default) follows OPTION COMPARE. Any other value raises error 5.

Print StrComp("apple", "Apple")                  ' 1 ("a" sorts after "A")
Print StrComp("apple", "Apple", vbTextCompare)   ' 0
Print Replace$("Red red RED", "red", "blue", 1, -1, vbTextCompare)   ' blue blue blue
Print InStrRev("C:\DVX\APPS\EDIT.APP", "\")     ' 12

REPLACE$ Details

REPLACE$ returns the text from position start on, so REPLACE$("abcabc", "b", "x", 3) is "caxc" -- the characters before start are left out, as in Visual Basic. A count of -1 replaces every occurrence. An empty find$ returns the text unchanged. A start below 1 or a count below -1 raises error 5.

SPLIT, JOIN$ and FILTER

SPLIT returns a string array numbered from 0. Assign it to a dynamic array (one declared with empty parentheses) and use UBOUND to find the last piece. The last piece keeps the rest of the text when limit stops the split. Splitting an empty string, or a limit of 0, gives an array with no elements: its UBOUND is -1. An empty delim$ gives the whole string as the only piece.

Dim parts() As String
Dim i As Integer
parts = Split("red,green,,blue", ",")
For i = 0 To UBound(parts)
    Print i; "[" & parts(i) & "]"     ' the empty third piece is kept
Next i
Print Join$(parts, " / ")             ' red / green /  / blue

JOIN$ works on any one-dimensional array; numbers are converted as STR$ would, without the leading space. FILTER returns a new string array holding the elements that contain match$ (include True, the default) or that do not contain it (include False), or an array with no elements when nothing matches. Passing JOIN$ or FILTER something that is not a one-dimensional array raises error 13 (Type mismatch).

INSTRREV Details

INSTRREV searches backward: INSTRREV("abcabc", "bc") is 5 and INSTRREV("abcabc", "bc", 4) is 2. A start of -1 (the default) searches from the end. It returns 0 when s$ is empty or start is past the end of s$, and start when find$ is empty. A start of 0 or below -1 raises error 5.

FORMAT$

FORMAT$ formats a numeric value using a BASIC-style format string. The format characters are the same as the ones used by PRINT USING.

s$ = FORMAT$(value, fmt$)
s$ = FORMAT$(value)
Print Format$(3.14159, "###.##")      ' "  3.14"
Print Format$(-7, "+###")             ' "  -7"
Print Format$(42, "00000")            ' "00042"
Print Format$(1234.5, "#,##0.00")     ' "1,234.50"
Print Format$(5, "#,##0.00")          ' "    5.00"
Print Format$(0.5, "PERCENT")         ' "50%"

The whole format string is one numeric field (for a number). The accepted format characters are # (digit or pad space), 0 (digit that is always printed; zero pads up to the first 0), . (decimal point), , (thousands separator), + and - (sign placement), $$ (floating dollar sign), ** (asterisk fill), ^^^^ (scientific notation) and the literal word PERCENT (multiplies by 100 and appends %). Unlike PRINT USING, a value wider than the field is printed in full without a % marker. See PRINT USING for details on each character.

With no format string (or an empty one), FORMAT$ gives the value's plain text, as CSTR does: a number without the leading space STR$ puts before it (Format$(42) is "42"), a date in the usual m/d/yyyy h:mm:ss AM form, text as it is, True / False, and "" for Empty.

FORMAT (without the $) is the same function.

FORMAT$ with Dates

When the format string holds a date or time code, or is one of the named date formats, FORMAT$ formats its value as a date. The value may be a Date, a number (taken as a date's number of days) or a string that holds a date (anything else raises error 13). A Date with an empty format string gives the usual m/d/yyyy h:mm:ss AM form. The codes may be written in upper or lower case.

  Code          Result
  ----          ------
  d / dd        Day of the month (dd: two digits)
  ddd / dddd    Weekday name, abbreviated (Mon) or full (Monday)
  ddddd         Short date (m/d/yyyy)
  dddddd        Long date (dddd, mmmm d, yyyy)
  w             Day of the week (1 = Sunday)
  ww            Week of the year (the week holding January 1 is week 1)
  m / mm        Month number (mm: two digits); the minute when it follows an hour or comes before a second
  mmm / mmmm    Month name, abbreviated (Jan) or full (January)
  q             Quarter (1-4)
  y             Day of the year (1-366)
  yy / yyyy     Year as two or four digits
  h / hh        Hour (hh: two digits); 1-12 when the format has AM/PM, else 0-23
  n / nn        Minute
  s / ss        Second
  ttttt         Long time (h:mm:ss AM/PM)
  c             The usual date and time form
  AM/PM am/pm   AM or PM in the case written; A/P and a/p give one letter; AMPM gives AM or PM
  "text"        Text in double quotes is copied as it is
  \x            The character after a backslash is copied as it is

Any other character, such as / : - , or a space, is copied as it is. These names give whole formats:

  Name           Format                 Example
  ----           ------                 -------
  General Date   (the usual form)       1/5/2000 3:04:05 PM
  Long Date      dddd, mmmm d, yyyy     Wednesday, January 5, 2000
  Medium Date    dd-mmm-yy              05-Jan-00
  Short Date     m/d/yyyy               1/5/2000
  Long Time      h:mm:ss AM/PM          3:04:05 PM
  Medium Time    hh:mm AM/PM            03:04 PM
  Short Time     hh:mm                  15:04
Dim d As Date
d = #1/5/2000 3:04:05 PM#
Print Format$(d, "yyyy-mm-dd hh:nn:ss")   ' 2000-01-05 15:04:05
Print Format$(d, "dddd, mmmm d")          ' Wednesday, January 5
Print Format$(d, "h:mm AM/PM")            ' 3:04 PM
Print Format$(d, "Long Date")             ' Wednesday, January 5, 2000
Print Format$(Now, "Short Time")          ' the time now, e.g. 09:41

MID$ Assignment

MID$ can also be used on the left side of an assignment to replace a portion of a string without changing its length:

Mid$(s$, start [, length]) = replacement$
Dim s$
s$ = "Hello, World!"
Mid$(s$, 8, 5) = "DVX--"
Print s$                   ' Hello, DVX--!

If length is omitted, MID$ replaces up to LEN(replacement$) characters; a length of 0 replaces nothing. The target string's total length never changes -- extra characters in replacement$ are truncated and shorter replacements leave trailing characters in place. A start position below 1 or a negative length raises error 5 (Illegal function call).

Math Functions

  Function   Returns   Description
  --------   -------   -----------
  ABS(n)     Double    Absolute value of n
  ATN(n)     Double    Arctangent of n (result in radians)
  COS(n)     Double    Cosine of n (n in radians)
  EXP(n)     Double    e raised to the power n
  FIX(n)     Integer   Truncates n toward zero (drops the fractional part)
  INT(n)     Integer   Largest integer less than or equal to n (floor)
  LOG(n)     Double    Natural logarithm (base e) of n
  RND[(n)]   Double    Random number in the range 0 <= RND < 1
  SGN(n)     Integer   Sign of n: -1 if negative, 0 if zero, 1 if positive
  SIN(n)     Double    Sine of n (n in radians)
  SQR(n)     Double    Square root of n
  TAN(n)     Double    Tangent of n (n in radians)
  TIMER      Double    Seconds since midnight

RND follows QBasic: RND or RND(n) with n > 0 returns the next number in the sequence, RND(0) repeats the last number, and RND(n) with n < 0 reseeds the generator from n (the same n always gives the same number). The result is a Double, 0 <= RND < 1.

INT, FIX and SGN return an Integer, widening to Long or Double when the value does not fit. EXP, ^ and the other functions raise error 6 (Overflow) when the result leaves the numeric range, and error 5 when it is undefined (for example a negative number to a fractional power).

Note: Use RANDOMIZE or RANDOMIZE TIMER to seed the generator so you don't get the same sequence each run.

Color Functions

The color functions work with 24-bit colors packed into a Long the way Visual Basic packs them, &HBBGGRR: red is the low byte, green the middle byte and blue the high byte. RGB(255, 0, 0) and &HFF are red, RGB(0, 0, 255) and &HFF0000 are blue. ForeColor, BackColor, FillColor, the drawing methods of forms and picture boxes (PSet, Line, Circle, Point), the Canvas control and the color dialog all use this form (the console graphics statements of SCREEN modes use QBasic color numbers instead), as do the color constants vbBlack, vbRed, vbGreen, vbYellow, vbBlue, vbMagenta, vbCyan and vbWhite (see Predefined Constants).

  Function           Returns   Description
  --------           -------   -----------
  RGB(r, g, b)       Long      Combine red, green, and blue components (0-255) into a color: r + g * 256 + b * 65536
  QBCOLOR(n)         Long      The color of QBasic color number n (0 to 15: 0 black, 1 blue, 2 green, 4 red, 7 white, 8 gray, 15 bright white, ...); error 5 for any other number
  GETRED(color)      Integer   Red component (0-255) of a color
  GETGREEN(color)    Integer   Green component (0-255) of a color
  GETBLUE(color)     Integer   Blue component (0-255) of a color
Dim c As Long
c = RGB(255, 128, 0)           ' bright orange, &H0080FF
Print GetRed(c); GetGreen(c); GetBlue(c)    ' 255 128 0
Me.BackColor = RGB(0, 0, 128)  ' dark blue background
Me.ForeColor = QBColor(14)     ' yellow

Conversion Functions

  Function   Returns   Description
  --------   -------   -----------
  CBOOL(n)   Boolean   Returns True (-1) if n is nonzero or a non-empty string; False (0) otherwise
  CBYTE(n)   Byte      Converts n to Byte with the rounding CINT uses; error 6 (Overflow) outside 0 to 255
  CCUR(n)    Currency  Converts n to Currency, rounded to four decimal places (halves to even); error 6 (Overflow) outside the Currency range
  CDATE(v)   Date      Converts a number (days since 12/30/1899) or date text to a Date; error 13 for text that is not a date, error 6 outside 1/1/100 to 12/31/9999
  CDBL(n)    Double    Converts n to Double (a Date gives its number of days)
  CINT(n)    Integer   Converts n to Integer; halves round to the nearest even number (2.5 -> 2, 3.5 -> 4); error 6 (Overflow) outside -32768 to 32767
  CLNG(n)    Long      Converts n to Long with the same rounding; error 6 (Overflow) outside the Long range
  CSNG(n)    Single    Converts n to Single
  CSTR(n)    String    Converts n to its String representation (a Date gives m/d/yyyy h:mm:ss AM)
  CVAR(v)    Variant   Returns v unchanged as a Variant

Passing Null to any of these except CVAR raises error 94 (Invalid use of Null). Text passed to one that gives a number must hold a number (CINT("12") is 12); other text raises error 13 (Type mismatch). VARTYPE, TYPENAME and the IS functions (ISNULL, ISEMPTY, ISNUMERIC, ...) are described under Variants.

See also: Variants

Date and Time Functions

These functions work with Date values (see Data Types). Wherever a date is expected, a Date, a number of days since 12/30/1899 or a string holding a date may be given; text that is not a date raises error 13 (Type mismatch).

  Function                                                 Returns   Description
  --------                                                 -------   -----------
  NOW                                                      Date      The current date and time
  DATE                                                     Date      Today's date (at midnight)
  TIME                                                     Date      The current time of day (on 12/30/1899)
  DATESERIAL(year, month, day)                             Date      The date with those parts
  TIMESERIAL(hour, minute, second)                         Date      The time with those parts
  DATEVALUE(d)                                             Date      The date part of d (its time dropped)
  TIMEVALUE(d)                                             Date      The time part of d (on 12/30/1899)
  YEAR(d)                                                  Integer   Year (100-9999)
  MONTH(d)                                                 Integer   Month (1-12)
  DAY(d)                                                   Integer   Day of the month (1-31)
  WEEKDAY(d [, firstDay])                                  Integer   Day of the week, 1 for firstDay (default vbSunday)
  HOUR(d)                                                  Integer   Hour (0-23)
  MINUTE(d)                                                Integer   Minute (0-59)
  SECOND(d)                                                Integer   Second (0-59)
  DATEADD(interval$, n, d)                                 Date      d moved by n intervals (n may be negative)
  DATEDIFF(interval$, d1, d2 [, firstDay [, firstWeek]])   Long      Intervals from d1 to d2 (negative when d2 is earlier)
  DATEPART(interval$, d [, firstDay [, firstWeek]])        Integer   One part of d
  ISDATE(v)                                                Boolean   True when v is a Date or a string holding a valid date
  MONTHNAME(month [, abbreviate])                          String    January ... December (Jan ... Dec when abbreviate is True)
  WEEKDAYNAME(n [, abbreviate [, firstDay]])               String    Name of day n of the week counted from firstDay (default vbSunday)

NOW, DATE and TIME need no parentheses. DATE$ and TIME$ still return the date and time as text.

Intervals

DATEADD, DATEDIFF and DATEPART take the interval as a string, in upper or lower case:

  Interval   Meaning
  --------   -------
  "yyyy"     Year
  "q"        Quarter
  "m"        Month
  "y"        Day of the year
  "d"        Day
  "w"        Weekday
  "ww"       Week
  "h"        Hour
  "n"        Minute
  "s"        Second

Any other interval raises error 5 (Illegal function call).

DATESERIAL and TIMESERIAL

A year from 0 to 29 means 2000 to 2029 and one from 30 to 99 means 1930 to 1999. Months, days, hours, minutes and seconds outside their usual range carry into the next or previous unit, so DATESERIAL(2000, 13, 1) is 1/1/2001, DATESERIAL(2000, 3, 0) is the last day of February 2000 and TIMESERIAL(0, 90, 0) is 1:30 AM. Fractional arguments are rounded. A result before 1/1/100 or after 12/31/9999 raises error 5.

Dim lastDay As Date
lastDay = DateSerial(Year(Date), Month(Date) + 1, 0)    ' last day of this month
Print Day(lastDay)

DATEADD

Adding months, quarters or years keeps the day of the month where it can; when the new month is shorter the day becomes its last day, so DATEADD("m", 1, #1/31/2000#) is 2/29/2000. The time of day is kept. "y", "d" and "w" all add days and "ww" adds weeks. A fractional n drops its fraction. A result outside the Date range raises error 5.

Print DateAdd("m", 1, #1/31/2001#)      ' 2/28/2001
Print DateAdd("h", -2, #1/1/2000#)      ' 12/31/1999 10:00:00 PM

DATEDIFF

DATEDIFF counts how many interval boundaries lie between d1 and d2: DATEDIFF("yyyy", #12/31/1999#, #1/1/2000#) is 1 although the dates are a day apart, and DATEDIFF("d", ...) counts midnights, whatever the times of day. "w" counts whole weeks (7 days) and "ww" counts calendar weeks -- the number of firstDay days (Sundays by default) after d1 up to and including d2. A result too large for a Long raises error 6 (Overflow).

Print DateDiff("d", #1/1/2000#, #3/1/2000#)     ' 60
Print DateDiff("ww", #1/1/2000#, #1/2/2000#)    ' 1 (1/2/2000 is a Sunday)
Print DateDiff("w", #1/1/2000#, #1/2/2000#)     ' 0

DATEPART and Weeks of the Year

DATEPART returns the part of d the interval names: "w" is the day of the week (1 for firstDay) and "ww" the week of the year. firstDay is one of vbSunday (1, the default) to vbSaturday (7), or vbUseSystemDayOfWeek (0, meaning Sunday). firstWeek chooses which week is week 1:

  Constant          Value   Week 1 is
  --------          -----   ---------
  vbUseSystem       0       Same as vbFirstJan1
  vbFirstJan1       1       The week holding January 1 (the default)
  vbFirstFourDays   2       The first week with at least four days in the new year
  vbFirstFullWeek   3       The first full week of the year

Days before week 1 belong to the last week of the previous year. A firstDay or firstWeek outside these values raises error 5.

Print DatePart("q", #5/15/2000#)                               ' 2
Print DatePart("ww", #1/1/2000#, vbSunday, vbFirstFourDays)    ' 52

ISDATE, MONTHNAME and WEEKDAYNAME

ISDATE is True for a Date and for a string that holds a valid date or time; numbers are not dates to ISDATE. MONTHNAME with a month outside 1 to 12, and WEEKDAYNAME with n outside 1 to 7, raise error 5.

If IsDate(Text1.Text) Then due = CDate(Text1.Text)
Print MonthName(Month(Date)); " "; WeekdayName(Weekday(Date), True)

File I/O Functions

  Function                    Returns   Description
  --------                    -------   -----------
  EOF(channel)                Boolean   True if the file pointer is at end of file
  FREEFILE                    Integer   Next available file channel number (1..16)
  INPUT$(n, #channel)         String    Reads exactly n characters from the file
  LOC(channel)                Long      BINARY: position of the last byte read or written (0 at the start); RANDOM: number of the last record read or written; sequential: number of 128-byte blocks read or written
  LOF(channel)                Long      Length of the file in bytes
  FILEATTR(channel, 1)        Long      How the file is open: 1 INPUT, 2 OUTPUT, 4 RANDOM, 8 APPEND, 32 BINARY (QBasic's numbers)
  FILEATTR(channel, 2)        Long      The operating system's handle for the open file
  SEEK(channel)               Long      RANDOM: number of the next record; other modes: 1-based position of the next byte to be read or written
  FILELEN(path$)              Long      Length of the named file in bytes (no OPEN needed; error 53 when missing)
  GETATTR(path$)              Integer   File attribute bits (see vbReadOnly, vbHidden, etc.)
  CURDIR$                     String    Current working directory
  DIR$(pattern$)              String    First filename matching pattern, or ""
  DIR$                        String    Next match from the last DIR$(pattern$), or "" when done
  LBOUND(array [, dim])       Integer   Lower bound of an array dimension (default dim = 1)
  UBOUND(array [, dim])       Integer   Upper bound of an array dimension (default dim = 1)

The dim argument of LBOUND and UBOUND must be a constant from 1 to 8.

Miscellaneous Functions

  Function               Returns   Description
  --------               -------   -----------
  DATE$                  String    Current date as "MM-DD-YYYY"
  TIME$                  String    Current time as "HH:MM:SS" (24-hour)
  TIMER                  Double    Seconds since midnight
  ENVIRON$(name$)        String    Value of the environment variable; empty string if not set
  COMMAND$               String    The arguments the program was started with; empty string if none
  COMMAND$(n)            String    The nth argument (1 = first) without its quotes; empty string when there are fewer; COMMAND$(0) is the same as COMMAND$
  ERR                    Long      Current runtime error number (0 if no error)
  SHELL(cmd$)            Integer   Exit code of the command (also usable as a statement, discarding the code)
  IIF(cond, a, b)        (any)     a when cond is True, b when it is False
  CHOOSE(n, a, b, ...)   (any)     The nth value of the list (1 = a), or Null when there is no nth value; up to 31 values
  LOADPICTURE([file$ [, size [, colordepth [, x, y]]]])   Object    A Picture object for a picture property (DragIcon, Picture), with Width, Height and Type; no file (or "") gives an empty picture

DATE$ and TIME$ return text; the Date and Time Functions return Date values.

IIF and CHOOSE

IIF and CHOOSE evaluate every argument before picking one, as in Visual Basic, so a function called in an argument runs even when its value is not chosen. A fractional n in CHOOSE drops its fraction (2.9 picks the second value). An n below 1 or past the end of the list gives Null, as in Visual Basic (test it with ISNULL; see Variants).

Print IIf(score >= 50, "Pass", "Fail")
Print Choose(Weekday(Date), "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")

LOADPICTURE

LOADPICTURE(file$) reads a picture file (BMP, PNG, JPEG or GIF) and returns a Picture object (TypeName "Picture") that can be given to a picture property: a control's DragIcon, the Picture of an Image or ImageButton. Use SET, or a plain assignment, as with a file name; file names still work too. LOADPICTURE() or LOADPICTURE("") gives an empty picture, which clears the property. A missing file raises error 53 (File not found), a file that is not a picture error 481 (Invalid picture), so the check happens where the picture is loaded. Loading the same file again gives the same Picture object. Reading a picture property back gives a Picture object too (TypeName "Picture"), as in Visual Basic; used as a value (printed, joined to text, compared) it stands for its file name, so code that treats the property as a file name keeps working.

The optional size and colordepth arguments are Visual Basic's: size is vbLPSmall (0), vbLPLarge (1), vbLPSmallShell (2), vbLPLargeShell (3) or vbLPCustom (4, with x and y giving the size), colordepth vbLPDefault (0), vbLPMonochrome (1), vbLPVGAColor (2) or vbLPColor (3). They choose among the images of an icon file; every DVX picture is a single bitmap, so, as for a bitmap in Visual Basic, they are checked and otherwise make no difference. A value outside these, or a negative x or y, raises error 5.

A Picture object has three properties, which can only be read:

  Property   Type      Description
  --------   ----      -----------
  Width      Long      The picture's width in HiMetric units (hundredths of a millimetre), as in Visual Basic; 0 for an empty picture.
  Height     Long      The picture's height in HiMetric units; 0 for an empty picture.
  Type       Integer   vbPicTypeBitmap (1) for a loaded picture, vbPicTypeNone (0) for an empty one.

The HiMetric sizes assume a standard display of 96 pixels an inch (the same as ScaleMode), so a pixel is about 26.46 HiMetric units. Convert them to pixels or another scale with a form's or PictureBox's ScaleX and ScaleY methods (see Drawing on Forms and PictureBoxes). Visual Basic's Handle property and Render method are not available: DVX pictures have no system handle.

Set Label1.DragIcon = LoadPicture("drag.bmp")
Image1.Picture = LoadPicture("logo.bmp")
Set Label1.DragIcon = LoadPicture()     ' back to the dotted outline

Dim pic As Object
Set pic = LoadPicture("logo.bmp")
Print Me.ScaleX(pic.Width, vbHimetric, vbPixels); "x"; Me.ScaleY(pic.Height, vbHimetric, vbPixels)

COMMAND$

COMMAND$ returns the program's arguments exactly as they were given, as in Visual Basic (QBasic turned them into capitals; DVX keeps them as they are). Arguments are separated by blanks; an argument with blanks in it is written in double quotes. COMMAND$(n) picks out one argument with its quotes removed, so a program that opens the document it was started with only needs:

IF COMMAND$(1) <> "" THEN
    OpenFile COMMAND$(1)
END IF

A program gets arguments when a document of a type associated with it is opened (the document is the argument), from a Program Manager item's Arguments, or from a command typed in a Run box. When the program runs in the IDE, COMMAND$ returns the Arguments set in Project Properties. A negative n is error 5 (Illegal function call).

Form and Control Statements

DVX BASIC supports Visual Basic-style forms and controls for building graphical user interfaces. A form is normally designed visually in the IDE and saved as a .frm file, but forms and their controls can also be built entirely in code.

Loading and Unloading Forms

LOAD FormName
UNLOAD FormName
UNLOAD Me

LOAD creates the form and its controls in memory. It fires Form_Load when the form is first loaded. UNLOAD destroys the form, firing Form_QueryUnload (which can cancel the close) and then Form_Unload. The form name here is the literal name of the form as it appears in its .frm file; UNLOAD Me unloads the form whose event handler is running.

Showing and Hiding Forms

FormName.Show [mode]
FormName.Hide
Me.Show [mode]
Me.Hide

Pass vbModal (1) to Show for a modal dialog that blocks until the user closes it. Omit the mode for a modeless (non-blocking) window.

Form2.Show vbModal
Me.Hide

Property Access

Read and write control properties using dot notation:

ControlName.Property = value
value = ControlName.Property
Text1.Text = "Hello"
Label1.Caption = "Name: " & name$
x = Text1.Left

A control on another form is reached through that form's name, or through a variable holding a form reference: FormName.ControlName.Property works in both assignments and expressions, and so does FormName.ControlName.Method. Me.ControlName.Property does the same for the current form.

Using a property or method (or Show, Hide, Unload) on a variable that does not hold a form or control raises error 91 (Object variable not set). In the IDE, a property or method name that the control's type does not have is reported when the program is compiled.

Form2.Label1.Caption = "From Form1"
total = Form2.List1.ListCount
Form2.List1.Clear

Method Calls

ControlName.Method [args]
List1.AddItem "New entry"
List1.Clear

Me Keyword

Me refers to the current form -- that is, the form whose event handler is running. Use it to access the form's own properties, controls, and methods from within event handlers, especially when the form's name may change or when the same code runs from multiple forms. In the code of a class module, Me is instead the object whose procedure is running (see Objects and Class Modules).

Me.Caption = "Updated Title"
Me.Text1.Text = ""
Me.Hide

Nothing

Nothing is a null object reference. Assign it with SET to an object variable to indicate "no object", and test for it with Is. An object variable that has not been Set holds Nothing, and using a property or method of Nothing raises error 91 (Object variable not set).

Set myCtrl = Nothing
If myCtrl Is Nothing Then Print "No control chosen"

Setting the last variable that refers to a class instance or Collection to Nothing frees the object; see Objects and Class Modules.

Control Arrays

Multiple controls can share a name with unique indices. Access individual controls with parenthesized indices:

Option1(0).Value = True
Label1(idx).Caption = "Item " & Str$(idx)
Me.Label1(i).Visible = True

WITH

The WITH block provides a shorthand for setting several properties on the same control or for making several method calls. Inside the block, begin each property or method with a dot and omit the control name.

WITH ControlName
    .Property1 = value1
    .Property2 = value2
    .Method arg1, arg2
END WITH
With Label1
    .Caption = "Status: Ready"
    .ForeColor = RGB(0, 128, 0)
    .Visible   = True
End With

Building Forms in Code

In addition to loading forms from .frm files, you can build a form entirely from code with CreateForm, CreateControl, SetEvent, and RemoveControl. The returned reference should be stored with SET.

CreateForm

SET formVar = CreateForm(name$, width%, height%)

Creates a new form with the given name and initial size. Returns a form reference.

CreateControl

SET ctrlVar = CreateControl(formRef, typeName$, ctrlName$ [, parentCtrlRef])

Creates a control on the given form. typeName$ is the control type (e.g. "CommandButton", "Label", "TextBox"). ctrlName$ is the unique name for the new control. If a parentCtrlRef is supplied, the new control is nested inside it (useful for placing controls inside containers like HBox or Frame); the parent must be a container on the same form, otherwise a runtime error (CreateControl: invalid parent) is raised.

SetEvent

SETEVENT ctrlRef, eventName$, handlerName$

Wires an arbitrary SUB as the handler for an event of a control, a form (Me or a form reference) or a menu item. The default event-handler convention (ControlName_EventName) is used automatically for controls defined in a .frm file; SetEvent is for controls you create dynamically or for reusing a single handler across multiple controls. A handler declared without parameters is called without the event's arguments.

RemoveControl

REMOVECONTROL formRef, ctrlName$

Removes a control from a form. A later reference to the removed control raises a runtime error (unknown control), as does a reference to a control of a form that has been unloaded.

Dim frm As Form
Dim lbl As Control

Set frm = CreateForm("MyDlg", 300, 200)
frm.Caption = "Built in code"

Set lbl = CreateControl(frm, "Label", "StatusLabel")
StatusLabel.Caption = "Hello, world!"

Dim btn As Control
Set btn = CreateControl(frm, "CommandButton", "BtnClose")
BtnClose.Caption = "Close"
SetEvent btn, "Click", "OnCloseClick"

frm.Show

Sub OnCloseClick
    Unload Me
End Sub

DoEvents

Yields control to DVX so the GUI can process pending events. Call this in long-running loops to keep the UI responsive (otherwise the window will appear frozen).

DOEVENTS
For i = 1 To 10000
    ' process data
    If i Mod 100 = 0 Then DoEvents
Next

MsgBox

Displays a message-box dialog. Can be used as a statement (discards the result) or as a function (returns the button clicked).

MSGBOX message$ [, flags [, title$]]
result = MSGBOX(message$ [, flags [, title$]])

flags is the sum of a button-style constant and an icon constant. See Predefined Constants for the complete list. The message box plays the desktop sound chosen for its icon on the Control Panel's Sounds tab (the default beep without an icon).

MsgBox "Operation complete"
answer = MsgBox("Continue?", vbYesNo + vbQuestion, "Confirm")
If answer = vbYes Then
    ' proceed
End If

InputBox$

Displays an input dialog and returns the user's text entry. Returns an empty string if the user cancels.

result$ = INPUTBOX$(prompt$ [, title$ [, default$]])
name$ = InputBox$("Enter your name:", "Name Entry", "")
If name$ <> "" Then
    Print "Hello, "; name$
End If

Event Handler Convention

Event handlers are named ControlName_EventName and defined as SUBs:

Sub Command1_Click()
    MsgBox "Button clicked!"
End Sub

Sub Form_Load()
    Me.Caption = "My App"
End Sub

Sub Text1_Change()
    Label1.Caption = "You typed: " & Text1.Text
End Sub

Common Events

  Event                Description
  -----                -----------
  Click                Control was clicked
  DblClick             Control was double-clicked
  Change               Control value or text changed
  KeyPress             Printable key was pressed (receives ASCII code)
  KeyDown              Any key was pressed (receives key code and shift state)
  KeyUp                Key was released
  MouseDown            Mouse button pressed (receives button, X, Y)
  MouseUp              Mouse button released
  MouseMove            Mouse moved over the control
  Scroll               Control was scrolled (mouse wheel or scrollbar)
  GotFocus             Control received input focus
  LostFocus            Control lost input focus
  Form_Load            Form is being loaded (fires once, after controls are created)
  Form_QueryUnload     Form is about to close; set Cancel = 1 to abort
  Form_Unload          Form is being unloaded
  Form_Resize          Form was resized
  Form_Activate        Form gained focus
  Form_Deactivate      Form lost focus
  Timer1_Timer         Timer control interval elapsed (Timer control's default event)

Objects and Class Modules

A class module lets you define your own kind of object. The class describes what every object of that kind knows (its member variables and properties) and what it can do (its methods). Each object made from the class -- an instance -- has its own copy of the member variables, so you can have as many independent objects as you need, much as you can put several TextBoxes on a form.

A First Class

This class module, saved as Account.cls, describes a bank account:

VERSION DVX 1.00 CLASS
Attribute VB_Name = "Account"

Option Explicit

Public Owner As String
Private mBalance As Double

Public Sub Deposit(ByVal amount As Double)
    mBalance = mBalance + amount
End Sub

Public Property Get Balance() As Double
    Balance = mBalance
End Property

Private Sub Class_Initialize()
    Print "Account created"
End Sub

Private Sub Class_Terminate()
    Print "Account for "; Owner; " closed"
End Sub

Any other code in the project can then make and use Account objects:

Dim acct As Account
Set acct = New Account          ' prints "Account created"
acct.Owner = "Scott"
acct.Deposit 100
acct.Deposit 50
Print acct.Owner & ": " & acct.Balance   ' Scott: 150
Set acct = Nothing              ' prints "Account for Scott closed"

Owner is Public, so code outside the class can read and change it. mBalance is Private: only the class's own code can touch it, and the outside world reads it through the Balance property, which has no way to change it.

Class Module Files (.cls)

Each class module is kept in its own .cls file, listed in the project's Classes group (see the IDE Guide). The file can begin with a few header lines, as a Visual Basic class file does; the IDE writes them for a new class module:

VERSION DVX 1.00 CLASS
Attribute VB_Name = "Account"

Option Explicit

The header is everything before the first line of code: blank lines, a VERSION line, a BEGIN ... END block and Attribute VB_... lines, in that order. All of it is optional, and a Visual Basic .cls file can be added as it is. The class's name comes from the Attribute VB_Name line; without one, the name is the file's name without .cls (ACCOUNT.CLS makes a class named ACCOUNT). The class name is the type name used in DIM ... AS, NEW, TypeOf and TYPENAME.

What a Class Contains

Outside its procedures, a class module may hold only declarations: member variables, CONSTs, OPTION and DEFtype statements, and Attribute lines. Statements that do something belong in a procedure, usually Class_Initialize. The members are:

  Member                             Written as                                 Used from outside as
  ------                             ----------                                 --------------------
  Public member variable             Public name As type                        obj.name (read and assign)
  Private member variable            Private name As type, or Dim name As type  not visible outside
  Method                             Sub or Function (Public unless Private)    obj.Method args, x = obj.Func(args)
  Read property                      Property Get name(...) As type             x = obj.name
  Write property                     Property Let name(..., value)              obj.name = x
  Object property                    Property Set name(..., value)              Set obj.name = someObject
  Friend procedure                   Friend Sub / Function / Property ...       obj.name, by the program's own code

A Sub, Function or Property is Public unless it is marked Private; Private procedures can be called only by the class's own code. A Friend one, as in Visual Basic, can be called by the rest of the program through a variable declared as the class, but it is not part of the object's late-bound interface: through As Object or As Variant it raises error 438, and an Implements interface does not include it. Inside the class's procedures the member variables are used by name, with no SHARED needed, and each call works with the variables of the object it was called for. The class's code can also use the program's DIM SHARED (or PUBLIC) module variables, procedures and constants.

Properties

A property looks like a variable from outside, but reading or assigning it runs a procedure, so the class can check or calculate the value:

Private mC As Double

Public Property Get Celsius() As Double
    Celsius = mC
End Property

Public Property Let Celsius(ByVal v As Double)
    mC = v
End Property

Public Property Get Fahrenheit() As Double
    Fahrenheit = mC * 9 / 5 + 32
End Property

Public Property Let Fahrenheit(ByVal v As Double)
    mC = (v - 32) * 5 / 9
End Property
Dim t As New Thermometer
t.Celsius = 100
Print t.Fahrenheit      ' 212

Property Get returns the value: assign it to the property name, as in a FUNCTION. Property Let receives the value being assigned as its last parameter; Property Set does the same for an object assigned with SET. A property can take arguments of its own before the value, such as Property Get Cell(r, c) and Property Let Cell(r, c, v), used as obj.Cell(1, 2) = 7. A property with only a Property Get is read-only: assigning it is a compile error through a variable of the class (error 438 through As Object). EXIT PROPERTY leaves a property procedure early.

Property procedures can also be written in an ordinary module, as in Visual Basic. The property is then used by its name like a variable, anywhere in the program: Size = 4 runs Property Let Size, Print Size runs Property Get Size, and Item(2) = "two" passes 2 and the value to Property Let Item.

Creating and Releasing Objects

An object variable starts as Nothing. NEW makes an object:

Dim a As Account               ' Nothing so far
Set a = New Account            ' now an Account

Dim b As New Account           ' an Account is made right here, at the DIM

When an object is made, its Class_Initialize runs; when it is freed, its Class_Terminate runs. Both are Subs without parameters, usually Private, and both are optional.

An object stays alive as long as something refers to it: a variable, an array element, a TYPE field, a Collection, a Variant, or a member variable of another object. Each SET to another variable adds a reference; nothing is copied. When the last reference goes away -- SET to Nothing or to another object, a local variable at the end of its SUB or FUNCTION, removal from a Collection, ERASE -- the object is freed and its Class_Terminate runs right then, just after the statement that let go of it:

Dim a As New Account
Dim b As Account
Set b = a                ' two references to one account
Set a = Nothing          ' still alive: b refers to it
Set b = Nothing          ' last reference gone: Class_Terminate runs now

Objects that refer to each other, directly or around a longer loop, keep each other alive even after the program's own variables let them go. DVX BASIC finds such groups while the program runs: after every thousand or so new objects (more when the program keeps many objects), and when the program's code runs to its end, it looks for objects that only the group itself still refers to. Each of those whose class has a Class_Terminate gets it called once, oldest object first, with every object of the group still intact; afterwards the group is freed. An object that a Class_Terminate stores somewhere (Set saved = Me) stays alive, and its Class_Terminate does not run again. Breaking the loop yourself (for example Set a.Partner = Nothing) still frees the objects at once instead of at the next check.

When the program ends normally -- its code runs to the end, and with forms the last form is unloaded -- the module variables are released as in Visual Basic, so the objects only they still hold get their Class_Terminate then. When the program ends with END (or is stopped), every object still alive is freed without running Class_Terminate, as with END in Visual Basic. Work that must always happen, such as saving a file, belongs in a method the program calls itself, not only in Class_Terminate.

Me

Inside a class's procedures, Me is the object the procedure was called for. Use it to pass the object to other code, or to go through the object's own properties (Me.Balance runs Property Get Balance):

Public Sub Move(ByVal dx As Double)
    Me.X = Me.X + dx     ' uses Property Get X and Property Let X
End Sub

Using Objects

When the compiler knows an object's class -- a variable, array, parameter, member variable or FUNCTION declared As the class name or As Collection, New ClassName, or Me in a class module -- its members are found when the program is compiled (early binding), as in Visual Basic. A misspelled member, a Private one, a Sub used where a value is needed, a property used as a statement, assigning a property that has no Property Let or Set, reading one that has no Property Get, and the wrong number of arguments are then compile errors that point at the member. Calls made this way are also faster. A class's own members can be used anywhere in the class, also above the line that declares them, and through Me a class reaches its Private members as well (Me.mTotal).

Through a variable declared As Object or As Variant the member is found by name when the program runs (late binding): obj.Deposit 5 looks for a Public member named Deposit in whatever object obj holds at that moment. A misspelled or Private member then raises error 438 when the line runs, and the wrong number of arguments raises error 450. Using a member of Nothing raises error 91 either way. An object of another class that reaches a variable of a class anyway (for example through a ByRef As Object argument) has its members found by name, as late binding would.

An argument that can never fit an object parameter of a SUB, FUNCTION or method is a compile error too: a number or text, or an object of another class than the parameter's (unless that class Implements it).

An object can be kept in a variable declared as its class name, As Object, or As Variant, in an array, in a TYPE field, in a Collection, or in another object's member variable. It can be passed to a SUB or FUNCTION and returned from a FUNCTION (assign the result with SET inside the function, Set MakeAccount = acct). TYPENAME gives an object's class name, and TypeOf obj Is ClassName tests it; Is tells whether two variables refer to the same object.

Arguments of a class's procedures follow the rules of SUB and FUNCTION calls when the object variable is declared as the class name: a parameter without BYVAL gets the caller's variable, so the procedure can change it, an omitted OPTIONAL argument gets its default, and a ParamArray collects the rest. When the object is reached through a variable declared As Object or As Variant, a variable or array element given as an argument is passed by reference too if the procedure's parameter is not BYVAL (Visual Basic's rule; other expressions go by value). What the procedure stores in such a parameter is converted to the type of the caller's variable (an Integer stays an Integer, as in Visual Basic). A TYPE field given as an argument (obj.Move rec.x, obj.Move pts(1).x) is passed by reference as well (a BYVAL parameter gets its value). The methods of forms and controls always take their arguments by value. An argument left out in the middle of a call (obj.Report a, , c) or at the end is an OPTIONAL parameter's default value, else its empty value: 0, "" and so on for a typed parameter, Missing for a Variant (ISMISSING is True). Leaving out a parameter that is not OPTIONAL raises error 449 (Argument not optional).

An object parameter is itself passed like any other parameter: without BYVAL, SET on the parameter changes the caller's variable (a SUB can make a new object for the caller); with BYVAL, the procedure gets its own reference to the same object, and SET on it does not affect the caller.

Default Member

A class can name one property or method as its default member, used when the object is written with parentheses directly after it. Put this line in the class, inside the procedure (as Visual Basic writes it) or on its own at the top of the class:

Attribute Item.VB_UserMemId = 0

With Item as the default member, obj(3) means obj.Item(3), and obj(3) = x calls Property Let Item. Collection's default member is Item, which is why c(1) and c("key") work. A call's result can be indexed directly, too: c(1)(0) is element 0 of the array item 1 holds, and Split(s, ",")(2) the third part.

Where a value is needed -- in arithmetic, a comparison, text, PRINT, a typed variable or a typed parameter -- an object stands for its default member's value, as in Visual Basic: with Value as the default member, total = obj + 1 reads obj.Value, and obj = 9 (without SET) stores 9 through it. A member variable can be the default member too (Attribute Label.VB_UserMemId = 0). An object without a default member used as a value raises error 13. The object name on its own still means the object itself wherever an object is expected: SET, Is, passing it to an object parameter, adding it to a Collection. Controls have default properties as well (Text1 means Text1.Text); see the control overview.

WITH...END WITH

WITH names an object or a TYPE record once for a block of statements; inside it, a name starting with a dot (.Value, .Add 3) is that object's member or that record's field:

With acct
    .Owner = "Ada"
    .Deposit 100
    Print .Balance
End With

With shapes(i).origin       ' a TYPE record: its fields
    .x = 5
    .y = .x * 2
End With

The expression after WITH is worked out once, when the block starts: With New Account makes one object that lives until End With, and With list(i) keeps the element it named even if i changes inside. WITH blocks can be nested; a dot then means the innermost one. A word after a space that starts with a dot is a new argument of its own (Bump .Count passes the member to Bump). Me works too (With Me). Leaving the block by GOTO or EXIT is allowed.

Errors in a Class

A class reports a problem with ERROR, normally numbered from vbObjectError so that its numbers cannot be mistaken for the built-in ones. The error is handled by the ON ERROR handler of the code that called the class, as with any procedure:

' in the class
Public Sub Withdraw(ByVal amount As Double)
    If amount > mBalance Then Error vbObjectError + 1
    mBalance = mBalance - amount
End Sub

' in the program
On Error GoTo NoMoney
acct.Withdraw 500
Exit Sub
NoMoney:
    If Err = vbObjectError + 1 Then MsgBox "Not enough money"
    Resume Next

Rules and Limits

See also: Events

See also: Interfaces (Implements)

See also: Collection Object

See also: Variants

See also: SET and PUBLIC / PRIVATE

Events

A class module can announce that something happened -- a download finished, a value changed, a step of a long job was done -- and let the code that uses its objects react, the way a form reacts to a button's Click. The class declares the event and raises it; the program declares a variable WithEvents and writes a SUB for each event it wants to handle.

Declaring and Raising an Event

In the class module, declare each event at the top with EVENT, then raise it from any of the class's procedures with RAISEEVENT:

' class module Downloader
Public Event Progress(ByVal percent As Integer, cancel As Boolean)
Public Event Done()

Public Sub Start()
    Dim stopNow As Boolean
    Dim p As Integer
    For p = 10 To 100 Step 10
        RaiseEvent Progress(p, stopNow)
        If stopNow Then Exit Sub
    Next
    RaiseEvent Done
End Sub

An event may have parameters but no return value. Its parameters cannot be OPTIONAL or a PARAMARRAY, and an event is always public (Public Event and Event mean the same; Private Event is an error). RAISEEVENT can only be used inside the class's own procedures, with exactly the arguments the event declares. A parameter without BYVAL is passed by reference, so a handler can change the variable given for it -- the cancel flag above is how a handler asks the class to stop. This holds for a variable, an array element (a(i)) and a TYPE field (rec.f, arr(i).f), as in Visual Basic. When several handlers get the event they all get the same variable, so each sees what the one before it stored; every store is converted to the variable's or field's type at once, as an assignment would be. While the handlers run, the arrays whose elements (or elements' fields) were given are locked: REDIM of one of them (or ERASE of a dynamic one) raises error 10. An expression, or a variable in its own parentheses, given for a by-reference parameter is passed as one temporary value that every handler shares, as in Visual Basic: the variable itself does not change, but a handler sees what the one before it stored. An argument is converted to the type of a typed event parameter, with the rules of SUB calls (a variable of another type given by reference is a compile error).

Handling Events

In a module, a form or another class module, declare a variable of the class WithEvents, outside any procedure, and write a SUB named variable_EventName with the same parameters as the event:

Dim WithEvents dl As Downloader

Sub StartDownload()
    Set dl = New Downloader
    dl.Start
End Sub

Sub dl_Progress(ByVal percent As Integer, cancel As Boolean)
    Label1.Caption = percent & "%"
    If percent >= 50 And StopWanted Then cancel = True
End Sub

Sub dl_Done()
    MsgBox "Finished"
End Sub

The handler's parameters must match the event's: the same number, the same types, and the same BYVAL / BYREF choice, or the program does not compile. A handler is optional: an event nobody handles does nothing. RAISEEVENT calls the handler of every WithEvents variable that holds the raising object at that moment -- two variables holding the same object both get the event, in the order they were declared -- and waits for them to finish before the class's code continues. Setting the variable to another object (or to Nothing) moves the handlers to the new object at once.

A WithEvents variable in a form belongs to that form: its handlers run with the form's own variables and controls, even when the event is raised while another form's code is running, and a form that is loaded twice gets its own variable each time. Unloading the form stops its handlers.

Events in a Class Module

A class can handle the events of objects it holds. The variable is a member variable (usually Private) and the handlers are the class's own procedures; each object of the class handles the events of the object in its own variable, and the handler runs for that object (Me):

' Class module Logger
Private WithEvents source As Downloader
Private lines As Integer

Public Sub Watch(d As Downloader)
    Set source = d
End Sub

Private Sub source_Progress(ByVal percent As Integer, cancel As Boolean)
    lines = lines + 1
    Print "log"; lines; percent
End Sub

Lifetime rule: listening never keeps an object alive. The object that raises an event does not hold a reference to its listeners; only the listener's own variable refers to the source. So:

Rules

See also: Objects and Class Modules

See also: Interfaces (Implements)

Interfaces (Implements)

An interface is a set of properties and methods that several classes promise to provide, so that code can work with any of them through one variable type. In DVX BASIC, as in Visual Basic, the interface is an ordinary class module -- its procedures are usually left empty -- and a class that provides it says IMPLEMENTS:

' class module IShape
Public Function Area() As Double
End Function
Public Sub Scale(ByVal factor As Double)
End Sub

' class module Circle
Implements IShape
Private r As Double

Private Function IShape_Area() As Double
    IShape_Area = 3.14159 * r * r
End Function

Private Sub IShape_Scale(ByVal factor As Double)
    r = r * factor
End Sub

For every public member of the interface, the implementing class writes a procedure named Interface_Member of the same kind (Sub, Function, Property Get / Let / Set) with the same number of parameters, ending in a ParamArray exactly when the interface's does; they are usually Private, so they are only reached through the interface. A call through the interface reaches the implementation directly (the compiler records which procedure implements each member), and an implementation's BYVAL parameter gets a value even where the interface's parameter is ByRef. A public variable of the interface is implemented as a Property Get and a Property Let (Property Set for an object variable). A class that leaves one out does not compile.

Code then uses the objects through a variable declared as the interface:

Dim s As IShape
Set s = New Circle
s.Scale 2
Print s.Area                ' runs Circle's IShape_Area
Print TypeOf s Is IShape    ' True
Print TypeName(s)           ' Circle

Through a variable declared as the interface, a member always means the interface's member, even when the class has a public member of the same name of its own. Through the class's own type, As Object or As Variant, the class's own public members are used. SET into a variable of the interface type accepts an object of any class that Implements it (and of the interface class itself); TypeOf obj Is Interface is True for them. A class can implement several interfaces with one IMPLEMENTS line for each. An argument left out of a call through the interface takes the default the interface's procedure declares, as in Visual Basic, even if the implementing procedure declares another. Friend procedures are not part of an interface.

See also: Objects and Class Modules

See also: Events

Collection Object

A Collection is a ready-made object that holds a list of items of any kind -- numbers, text, objects -- in order. Items can be looked up by position or by a text key, added anywhere in the list and removed, and FOR EACH walks through them. The list grows as needed; there is no size to declare.

Dim fruit As New Collection
fruit.Add "Apple", "a"
fruit.Add "Cherry", "c"
fruit.Add "Banana", "b", "c"    ' before the item with key "c"

Print fruit.Count               ' 3
Print fruit(1)                  ' Apple
Print fruit("B")                ' Banana (keys ignore case)

Dim f As Variant
For Each f In fruit
    Print f                     ' Apple, Banana, Cherry
Next

fruit.Remove "a"
fruit.Remove 1                  ' removes Banana, now the first item

Members

  Member                                  Description
  ------                                  -----------
  Add item [, key] [, before] [, after]   Adds item at the end of the list, or before or after the item given by position or key. key, when given, is text that names the item.
  Remove indexOrKey                       Removes the item at that position (1 = first) or with that key.
  Item(indexOrKey)                        The item at that position or with that key. Item is the default member: c(2) is c.Item(2) and c("key") is c.Item("key").
  Count                                   The number of items.

Positions start at 1 and change as items are added and removed. A key must be text, is compared without regard to upper and lower case, and must be unique in the Collection. Give either before or after, not both; leave out the arguments you do not use with commas (c.Add item, , 1 puts item first). Items are stored as they are: an object added to a Collection stays alive while the Collection holds it.

Make a Collection with DIM c AS NEW COLLECTION or SET c = NEW COLLECTION. Like any object, it is freed when the last reference to it goes.

Through a variable declared As Collection the members are checked when the program is compiled: another member name, the wrong number of arguments, using Add or Remove as a value, Count or Item as a statement, and assigning any of them are compile errors. Keyed lookups compare a hash of the key first, so finding an item by key stays fast in large Collections.

Errors

  Error   When
  -----   ----
  5       A key that is not in the Collection (Item, Remove, before or after), or Add given both before and after
  9       A position that is not in the Collection
  13      A key that is not text
  438     A member other than Add, Remove, Item and Count, or assigning one, through As Object or As Variant
  450     The wrong number of arguments, through As Object or As Variant
  457     Add with a key that is already in use

See also: Objects and Class Modules

See also: FOR EACH...NEXT

SQL Functions

DVX BASIC includes SQLite database support through the sql.bas include library. Add sql.bas to your project to gain access to these functions. All functions use database handles and result-set handles (Long integers) returned by SQLOpen and SQLQuery. Numeric parameters and results are Long, so row counts and integer column values keep their full 32-bit range.

Opening and Closing Databases

SQLOpen

Opens a SQLite database file and returns a database handle (> 0) or 0 on failure. The file is created if it does not exist. A file that cannot be changed (for example one marked read-only) still opens, but only for reading. When SQLOpen returns 0, SQLError$(0) tells you why.

db = SQLOpen(path$)
db = SQLOpen(App.Data & "\mydata.db")

SQLClose

Closes an open database.

SQLClose db

Executing SQL

SQLExec

Executes a SQL statement that does not return data (INSERT, UPDATE, DELETE, CREATE TABLE, etc.). Returns True on success.

ok = SQLExec(db, sql$)
SQLExec db, "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)"
SQLExec db, "INSERT INTO users (name) VALUES ('Scott')"
ok = SQLExec(db, "DELETE FROM users WHERE id = 5")

Put text values in single quotes, as in the examples. Text in double quotes is read as a column name, so "Scott" in place of 'Scott' gives the error "no such column: Scott".

SQLAffected

Returns the number of rows affected by the last INSERT, UPDATE, or DELETE.

count = SQLAffected(db)

Querying Data

SQLQuery

Executes a SELECT query and returns a result-set cursor.

rs = SQLQuery(db, sql$)
rs = SQLQuery(db, "SELECT id, name FROM users ORDER BY name")

SQLNext

Advances the cursor to the next row. Returns True if a row is available, False when there are no more rows.

hasRow = SQLNext(rs)

SQLEof

Returns True if the cursor is past the last row.

done = SQLEof(rs)

Reading Fields

SQLField$ / SQLFieldText$

Returns a field value as a string. Use SQLField$ to look up by column name; use SQLFieldText$ to look up by 0-based column index.

value$ = SQLField$(rs, columnName$)
value$ = SQLFieldText$(rs, columnIndex)
name$  = SQLField$(rs, "name")
first$ = SQLFieldText$(rs, 0)

SQLFieldName$

Returns the column name for a given 0-based column index.

colName$ = SQLFieldName$(rs, columnIndex)

SQLFieldInt

Returns a field value as a Long integer.

value = SQLFIELDINT(rs, columnIndex)

SQLFieldDbl

Returns a field value as a double.

value# = SQLFIELDDBL(rs, columnIndex)

SQLFieldCount

Returns the number of columns in the result set.

count = SQLFieldCount(rs)

Result Set Cleanup

SQLFreeResult

Frees a result-set cursor. Always call this when finished iterating a query.

SQLFreeResult rs

Error Information

SQLError$

Returns the last error message for the database.

msg$ = SQLError$(db)

When a database file could not be opened, read or written, the message ends with the reason in parentheses, for example "unable to open database file (No such file or directory)". If another program, or another handle in your own program, is changing the same database at that moment, the message is "database is locked": try again once the other change is finished, and free result sets with SQLFreeResult as soon as you are done with them, because an open result set stops other handles from saving changes.

Complete SQL Example

Dim db As Long
Dim rs As Long

db = SQLOpen(App.Data & "\contacts.db")
SQLExec db, "CREATE TABLE IF NOT EXISTS contacts (name TEXT, phone TEXT)"
SQLExec db, "INSERT INTO contacts VALUES ('Alice', '555-1234')"

rs = SQLQuery(db, "SELECT name, phone FROM contacts")
Do While SQLNext(rs)
    Print SQLField$(rs, "name"); Tab(20); SQLField$(rs, "phone")
Loop
SQLFreeResult rs
SQLClose db

App Object

The App object provides read-only properties for the application's directory paths.

  Property      Returns   Description
  --------      -------   -----------
  App.Path      String    Directory containing the application's executable
  App.Config    String    Directory for application configuration files
  App.Data      String    Directory for application data files (databases, etc.)
configFile$ = App.Config & "\settings.ini"
dbPath$ = App.Data & "\myapp.db"
Print "Running from: " & App.Path

Clipboard Object

The Clipboard object shares text with other programs and with the copy and paste of text boxes, as in Visual Basic. The DVX clipboard holds text only, so the format arguments accept vbCFText (1): any other format is never present and GetText returns "" for it.

  Method                            Returns   Description
  ------                            -------   -----------
  Clipboard.Clear                   (none)    Empty the clipboard.
  Clipboard.GetFormat(format)       Boolean   True when the clipboard holds data of that format (text for vbCFText).
  Clipboard.GetText([format])       String    The clipboard text, or "" when it is empty.
  Clipboard.SetText text [, format] (none)    Put text on the clipboard, replacing what was there. A format other than vbCFText is an error.
Clipboard.SetText Text1.Text
If Clipboard.GetFormat(vbCFText) Then Text2.Text = Clipboard.GetText()

A control or form of your own named Clipboard takes the name's place.

INI Functions

DVX BASIC provides built-in functions for reading and writing standard INI configuration files (the same text format used by DVX system configuration).

IniRead

Reads a value from an INI file. Returns the default value if the file, section, or key is not found. All four arguments are required. Section and key names match without regard to case, and blanks around them are ignored ([ User ] is section User). If a name appears twice, the first one counts. Keys above the first section header belong to section "" (an empty section name). Lines starting with ; or # are comments.

value$ = IniRead(file$, section$, key$, default$)
name$ = IniRead(App.Config & "\app.ini", "User", "Name", "Unknown")
fontSize = Val(IniRead(App.Config & "\app.ini", "Display", "FontSize", "12"))

IniWrite

Writes a value to an INI file. Creates the file, section, or key if they do not exist. A new key goes after the last key of its section and a new section at the end of the file. Every other line -- comments, blank lines, other keys, lines of any length -- is kept exactly as it is. The changed key is written as key = value. Every line of the saved file ends in a carriage return and line feed (CR LF). The file is saved through a temporary file, so a failed write leaves the old file intact. If the file exists but cannot be read, or the new file cannot be written, IniWrite raises error 75 (Path/file access error) and leaves the file alone.

INIWRITE file$, section$, key$, value$
IniWrite App.Config & "\app.ini", "User", "Name", "Scott"
IniWrite App.Config & "\app.ini", "Display", "FontSize", Str$(fontSize)

Predefined Constants

The following constants are predefined by the compiler and available in all programs. No DIM or CONST declaration is required to use them.

MsgBox Button Style Flags

  Constant        Value   Description
  --------        -----   -----------
  vbOKOnly        0       OK button only (default)
  vbOKCancel      1       OK and Cancel buttons
  vbYesNo         2       Yes and No buttons
  vbYesNoCancel   3       Yes, No, and Cancel buttons
  vbRetryCancel   4       Retry and Cancel buttons

MsgBox Icon Flags

Add an icon flag to the button style (with + or OR) to display an icon in the message box.

  Constant        Value   Description
  --------        -----   -----------
  vbInformation   &H10    Information icon (i)
  vbExclamation   &H20    Warning icon (!)
  vbCritical      &H30    Error/critical icon (X)
  vbQuestion      &H40    Question icon (?)

MsgBox Return Values

  Constant   Value   Description
  --------   -----   -----------
  vbOK       1       User clicked OK
  vbCancel   2       User clicked Cancel
  vbYes      3       User clicked Yes
  vbNo       4       User clicked No
  vbRetry    5       User clicked Retry

Show Mode Flags

  Constant   Value   Description
  --------   -----   -----------
  vbModal    1       Show form as modal dialog

File Attribute Flags

Bit values used with GETATTR and SETATTR.

  Constant      Value   Description
  --------      -----   -----------
  vbNormal      0       Normal file (no attributes)
  vbReadOnly    1       Read-only
  vbHidden      2       Hidden
  vbSystem      4       System file
  vbDirectory   16      Entry is a directory
  vbArchive     32      File has been modified since last backup

Compare Constants

The compare argument of FILTER, INSTRREV, REPLACE$, SPLIT and STRCOMP.

  Constant             Value   Description
  --------             -----   -----------
  vbUseCompareOption   -1      Follow OPTION COMPARE (the default)
  vbBinaryCompare      0       Exact match
  vbTextCompare        1       Ignore upper and lower case

Day and Week Constants

The firstDay and firstWeek arguments of the date functions, and WEEKDAY results.

  Constant               Value   Description
  --------               -----   -----------
  vbUseSystemDayOfWeek   0       Weeks start on Sunday
  vbSunday               1       Sunday
  vbMonday               2       Monday
  vbTuesday              3       Tuesday
  vbWednesday            4       Wednesday
  vbThursday             5       Thursday
  vbFriday               6       Friday
  vbSaturday             7       Saturday
  vbUseSystem            0       Week 1 holds January 1
  vbFirstJan1            1       Week 1 holds January 1
  vbFirstFourDays        2       Week 1 is the first with four days in the new year
  vbFirstFullWeek        3       Week 1 is the first full week

Drag and Drop Constants

The DragMode property, the Drag method and the State argument of DragOver.

  Constant      Value   Description
  --------      -----   -----------
  vbManual      0       DragMode: the program starts drags with Drag
  vbAutomatic   1       DragMode: pressing the control starts a drag
  vbBeginDrag   1       Drag: start dragging (the default)
  vbEndDrag     2       Drag: drop where the mouse is (Drag 0 cancels)
  vbEnter       0       DragOver: the drag came onto the object
  vbLeave       1       DragOver: the drag went off the object
  vbOver        2       DragOver: the drag moved over the object

Clipboard Constants

  Constant   Value   Description
  --------   -----   -----------
  vbCFText   1       Text, the format the DVX clipboard holds

Scale and Picture Constants

The scale units of ScaleMode and of the ScaleX / ScaleY methods, and the values of a Picture object's Type (see Drawing on Forms and PictureBoxes, and LOADPICTURE).

  Constant          Value   Description
  --------          -----   -----------
  vbUser            0       The object's own scale (Scale, ScaleWidth ...)
  vbTwips           1       Twips (1440 an inch, 15 a pixel)
  vbPoints          2       Points (72 an inch)
  vbPixels          3       Pixels (the DVX default ScaleMode)
  vbCharacters      4       Characters (120 twips across, 240 down)
  vbInches          5       Inches
  vbMillimeters     6       Millimetres
  vbCentimeters     7       Centimetres
  vbHimetric        8       Hundredths of a millimetre (ScaleX / ScaleY only; a Picture's Width and Height)
  vbPicTypeNone     0       Picture.Type of an empty picture
  vbPicTypeBitmap   1       Picture.Type of a loaded picture

VarType Constants

The values VARTYPE returns (see Variants). For an array, VARTYPE adds vbArray to the type of its elements.

  Constant            Value   Kind of value
  --------            -----   -------------
  vbEmpty             0       Empty (nothing stored yet)
  vbNull              1       Null
  vbInteger           2       Integer
  vbLong              3       Long
  vbSingle            4       Single
  vbDouble            5       Double
  vbCurrency          6       Currency
  vbDate              7       Date
  vbString            8       String
  vbObject            9       An object or Nothing
  vbError             10      Error value (Visual Basic only; no DVX value has this type)
  vbBoolean           11      Boolean
  vbVariant           12      Variant (only in vbArray + vbVariant, an array of Variants)
  vbDataObject        13      Data object (Visual Basic only; no DVX value has this type)
  vbByte              17      Byte
  vbUserDefinedType   36      A TYPE variable
  vbArray             8192    Added to the element type for an array

Error Constants

  Constant        Value         Description
  --------        -----         -----------
  vbObjectError   -2147221504   Base for your own error numbers, as in Visual Basic: a class module raises ERROR vbObjectError + n, and the handler recovers n with ERR - vbObjectError

Color Constants

Colors in the form RGB makes (&HBBGGRR, see Color Functions), as in Visual Basic.

  Constant    Value       Color
  --------    -----       -----
  vbBlack     &H0         Black
  vbRed       &HFF        Red
  vbGreen     &HFF00      Green
  vbYellow    &HFFFF      Yellow
  vbBlue      &HFF0000    Blue
  vbMagenta   &HFF00FF    Magenta
  vbCyan      &HFFFF00    Cyan
  vbWhite     &HFFFFFF    White

Boolean Constants

  Constant   Value   Description
  --------   -----   -----------
  True       -1      Boolean true
  False      0       Boolean false

Include Libraries

DVX ships a set of BASIC include files (.bas) in the sdk/include/basic directory. Each file is a small library of DECLARE LIBRARY wrappers around native DVX runtime functions. Add an include file to your project (the IDE's Add File command, or editing the .dbp with another tool) and the declared functions become available to your code.

  File           Provides
  ----           --------
  commdlg.bas    File Open/Save dialogs, input dialogs, choice dialogs, save-prompt dialogs, the color dialog
  sql.bas        SQLite database access (SQLOpen, SQLQuery, SQLNext, SQLField$, etc.)
  comm.bas       Serial-port I/O (raw and packet) and optional encrypted links
  resource.bas   Read and write DVX resource blocks (icons, text, binary data) in bundled files
  help.bas       Compile help source files and open the DVX help viewer
  net.bas        Network connections: TCP (TcpConnect, TcpListen, TcpSend, TcpRecv$, ...), UDP messages and name lookups
  print.bas      Printing: text with the page setup and pictures, with or without the Print dialog; the Page Setup dialog
  game.bas       Games: whether a key is being held down right now (GameKeyDown)
  joystick.bas   Joysticks: how many there are, their names, where each stick points and which buttons are pressed (JoyCount, JoyX, JoyY, JoyButton, ...)
  sound.bas      Sound: play WAV and VOC files, tones and noise, set the volume (PlayWave, PlayTone, StopWave, SoundInfo$, ...)
  music.bas      Music: play MOD, S3M, XM, IT and MIDI files, and play notes yourself (MusicLoad, MusicPlay, MusicStop, MusicNoteOn, ...)

Using an Include Library

' With commdlg.bas added to the project
Dim path As String
path = DlgFileOpen$("Open a file", "Text Files (*.txt)|All Files (*.*)")

If path <> "" Then
    Print "Selected: " & path
End If

Color Dialog

With commdlg.bas in the project, DlgColor(title, defaultColor) shows the color dialog: a palette of basic colors, Red, Green and Blue sliders with number boxes, and a preview. It starts at defaultColor and returns the color chosen, in the form RGB makes and ForeColor and BackColor use, or -1 when the user cancels.

Dim c As Long
c = DlgColor("Text Color", Label1.ForeColor)

If c <> -1 Then
    Label1.ForeColor = c
End If
Note: DVX BASIC does not have an $INCLUDE directive. Libraries are added to the project so that the compiler sees their DECLARE LIBRARY blocks.

Encrypted Serial Links

With comm.bas in the project, CommOpen opens a packet link and CommHandshake sets up encryption. Give both ends the same passphrase to authenticate the connection. Without a passphrase the link is still encrypted and tamper-checked, but it cannot tell who is on the other end. CommHandshake returns False if the passphrases differ, if only one side gives one, or if the link fails.

Dim link As Long
link = CommOpen(1, 115200, 8, "N", 1, SER_HANDSHAKE_NONE)

If CommHandshake(link, "shared secret") Then
    CommSend link, "hello", 0, True
Else
    Print "Handshake failed"
End If

After the handshake, data that arrives unencrypted is ignored unless that channel is opened for it with CommSetPlain link, channel, True.

Printing

With print.bas in the project, a program prints like the programs that come with DVX. PrintTextDialog shows the Print dialog (printer, copies, pages) and prints the text on pages laid out by the page setup: margins, a header and a footer with the document name, date and page number. PrintPageSetup shows the Page Setup dialog, which the user's choices are saved from for every program. PrintPictureDialog prints a picture file scaled to the page, on printer models that print pictures (PrintCanPrintPictures says whether the chosen one does). PrintText and PrintPicture print without asking first. Each returns True when it printed.

Sub mnuPrint_Click ()
    PrintTextDialog txtNotes.Text, "Notes"
End Sub

Sub mnuPageSetup_Click ()
    PrintPageSetup
End Sub

For printer output a line at a time, see LPRINT and OPEN "LPT1:".

Held Keys for Games

With game.bas in the project, GameKeyDown(keyCode) tells whether a key is being held down right now, so a game can move something for as long as a key is held instead of waiting for key presses. It returns True only while one of the program's own windows is active. Name the key with one of the GAMEKEY_ constants (the arrow keys, Shift, Ctrl, Alt, Space, Enter, Esc and a few letters) or with its PC keyboard scan code (add &H80 for the grey keys between the typing keys and the number pad). A Timer polls it:

Sub Timer1_Timer ()
    If GameKeyDown(GAMEKEY_LEFT) Then shipX = shipX - 2
    If GameKeyDown(GAMEKEY_RIGHT) Then shipX = shipX + 2
End Sub

Joysticks

With joystick.bas in the project, a program reads joysticks and game pads. JoyCount() says how many there are; they are numbered from 1, and so are their axes, buttons and hats. JoyX(joy) and JoyY(joy) say where the stick points, from -32768 (all the way left or up) to 32767 (all the way right or down), 0 in the middle; JoyAxis(joy, axis) reads any axis (3 and 4 are a throttle or rudder). JoyButton(joy, button) is True while the button is held down, and also once after a quick press that happened since the program last asked about that button, so a Timer never misses a shot. JoyHat(joy, hat) gives the direction a hat switch is pushed in degrees (0 is up, 90 right) or JOY_HAT_CENTERED. JoyName$(joy), JoyAxes(joy) and JoyButtons(joy) describe the joystick.

Sub Timer1_Timer ()
    If JoyCount() = 0 Then Exit Sub

    shipX = shipX + JoyX(1) \ 8192
    If JoyButton(1, 1) Then FireShot
End Sub

When no joystick is connected the keyboard stands in for one (the arrow keys, with Left Ctrl, Space, Left Shift and Z as buttons), and it only answers while one of the program's windows is active. Joysticks are calibrated, and the keyboard joystick's keys chosen, on the Control Panel's Game Controllers tab. QBasic's STICK and STRIG work too, without joystick.bas.

See: STICK and STRIG

Sound

With sound.bas in the project, a program plays sound files and tones through whatever sound hardware the computer has: a Sound Blaster, the PC speaker (tones only, unless sampled sound on the speaker is switched on) or nothing at all, in which case the program works the same but is silent. Several programs can play at once, and everything a program plays stops when it ends.

PlayWave(fileName) plays a WAV or VOC file once and PlayWaveLoop(fileName) over and over; PlayTone(frequency, milliseconds, volume) plays a tone of frequency hertz (20 to 20000) and PlayNoise(frequency, milliseconds, volume) noise, which sounds brighter the higher the frequency; a length of 0 plays until stopped. Each returns a voice number, or SOUND_FAILED (0) when the sound could not be played, and then SoundError$() says why. StopWave(voice) stops one sound, StopAllSounds() all of the program's sounds, and SoundPlaying(voice) is True while a sound is still playing. SoundVolume(volume) sets the volume of everything the program plays. Volumes are percent (0 to 100). SoundInfo$() describes the sound device, like "Sound Blaster 16 (DSP 4.05) at 220h, 22050 Hz, 16-bit stereo".

Dim Shared boom As Long

Sub cmdFire_Click ()
    boom = PlayWave("BOOM.WAV")

    If boom = SOUND_FAILED Then
        lblStatus.Caption = SoundError$()
    End If
End Sub

WAV files must be uncompressed (8 or 16 bits, mono or stereo); VOC files may be 8- or 16-bit. QBasic's BEEP, SOUND and PLAY work too, without sound.bas.

See: BEEP, SOUND and PLAY

Music

With music.bas in the project, a program plays music files: tracker modules (MOD, S3M, XM and IT files, made of recorded instrument sounds) wherever the computer can play sampled sound, and MIDI files (.MID, types 0 and 1) on the computer's music synthesizer, or on a built-in synthesizer that sounds much the same when there is none. Several programs can play music at once, and everything a program plays stops when it ends.

MusicLoad(fileName) loads a music file and returns its music number, or MUSIC_FAILED (0) when it could not be loaded; MusicError$() then says why. MusicPlay(music, loopIt) plays it from where it is (the start after loading or stopping); with loopIt True it starts over at the end until it is stopped. MusicStop(music) stops and goes back to the start, MusicPause(music) and MusicResume(music) pause and go on, and MusicPlaying(music) is True while it plays. MusicVolume(music, volume) sets its volume in percent (0 to 100). MusicPosition(music) and MusicLength(music) give the place and the length in milliseconds, and MusicSeek(music, milliseconds) goes to a place (a module goes to the start of the part that holds it). MusicFree(music) stops a music and forgets it.

Dim Shared tune As Long

Sub Form_Load ()
    tune = MusicLoad("THEME.MOD")

    If tune = MUSIC_FAILED Then
        lblStatus.Caption = MusicError$()
    Else
        MusicPlay tune, True
    End If
End Sub

A program can also play notes itself, like a keyboard. MusicMidiOpen() returns a live music that is already playing. MusicNoteOn(music, channel, note, velocity) starts a note and MusicNoteOff(music, channel, note) ends it; MusicProgram(music, channel, program) chooses a channel's instrument, MusicControl(music, channel, controller, value) sets a controller (7 volume, 10 pan, 11 expression, 64 the sustain pedal, 123 all notes off) and MusicPitchBend(music, channel, bend) bends the channel's notes (-8192 to 8191, two semitones either way at the ends). Channels are 1 to 16, and channel 10 (MUSIC_DRUMS) plays drums, one per note. Notes, velocities, instruments and controller values are 0 to 127; middle C is note 60, and instruments are numbered as in General MIDI (0 piano, 24 guitar, 40 violin, 56 trumpet, 73 flute). The same calls work on a MIDI file that is playing.

Dim Shared keys As Long

Sub Form_Load ()
    keys = MusicMidiOpen()
    MusicProgram keys, 1, 73
End Sub

Sub cmdC_Click ()
    MusicNoteOn keys, 1, 60, 100
    tmrNoteOff.Enabled = True
End Sub

Sub tmrNoteOff_Timer ()
    MusicNoteOff keys, 1, 60
    tmrNoteOff.Enabled = False
End Sub

Network Connections

With net.bas in the project, a program talks to other computers over the network set up in the Control Panel. TcpConnect returns a handle (0 when it failed; NetError$ says why), TcpSend sends text, and TcpRecv$ returns whatever has arrived without waiting, so a Timer keeps the program responsive:

Dim conn As Long

Sub Form_Load ()
    conn = TcpConnect("bbs.example.org", 23)

    If conn = 0 Then
        Print "Could not connect: " & NetError$()
    End If
End Sub

Sub Timer1_Timer ()
    If TcpPending(conn) > 0 Then Print TcpRecv$(conn)
    If TcpConnected(conn) = 0 Then Timer1.Enabled = False
End Sub
  Function                              Description
  --------                              -----------
  HostLookup$(hostName)                 The address of a name, such as "192.0.2.10", or "" when it is not found.
  NetAddress$()                         This computer's address ("" while it has none).
  NetError$()                           Why the last call failed, in plain words.
  TcpConnect(host, port)                Connect; a handle, or 0. Waits up to 20 seconds; other programs keep running.
  TcpListen(port)                       Wait for connections on port; a listening handle, or 0.
  TcpAccept(handle)                     A connection that arrived on a listening handle, or 0 when none is waiting.
  TcpSend(handle, text)                 Send text; the bytes sent, or -1.
  TcpPending(handle)                    Bytes waiting to be read (-1 for a bad handle).
  TcpRecv$(handle)                      What has arrived (up to 4096 bytes), or "".
  TcpConnected(handle)                  1 while the connection is open, 0 once the other side closed it.
  TcpClose handle                       Close a connection or a listening handle.
  UdpOpen(port)                         A UDP handle on port (0 = any free port), or 0.
  UdpSend(handle, host, port, text)     Send one message; the bytes sent, or -1. "255.255.255.255" reaches every computer nearby.
  UdpRecv$(handle)                      The next message that arrived, or "".
  UdpFrom$()                            "address:port" of the sender of the last UdpRecv$ message.
  UdpClose handle                       Close a UDP handle.

The functions work with text: a string stops at a zero byte. Every connection a program opens is closed for it when the program ends.

CommRecvEncrypted(handle, channel) tells whether the data the last CommRecv$ on that channel returned can be trusted. It returns True when every byte of it arrived encrypted and authenticated, and also when that CommRecv$ returned nothing or CommRecv$ has not been called on the channel yet. It returns False when any byte arrived unencrypted, which can only happen before CommHandshake or on a channel opened with CommSetPlain, and for an invalid handle or a channel outside 0-127.

Dim msg As String
msg = CommRecv$(link, 1)

If msg <> "" And Not CommRecvEncrypted(link, 1) Then
    Print "Unencrypted: " & msg
End If

See also: DECLARE LIBRARY

Common Properties, Events, and Methods

Every control in DVX BASIC inherits a set of common properties, events, and methods. These are handled by the form runtime before dispatching to widget-specific interface descriptors.

Common Properties

  Property     Type      R/W   Description
  ----------   -------   ---   -------------------------------------------
  Name         String    R     The control's name (e.g. "Command1"). Read-only at runtime.
  Left         Integer   R/W   X position in pixels relative to the parent container.
  Top          Integer   R/W   Y position in pixels relative to the parent container.
  Width        Integer   R/W   Current width in pixels. Setting this changes the minimum width constraint.
  Height       Integer   R/W   Current height in pixels. Setting this changes the minimum height constraint.
  MinWidth     Integer   R/W   Minimum width for layout. Setting it works like setting Width; reading it returns the minimum that was set.
  MinHeight    Integer   R/W   Minimum height for layout. Setting it works like setting Height; reading it returns the minimum that was set.
  MaxWidth     Integer   R/W   Maximum width cap (0 = no limit, stretch to fill).
  MaxHeight    Integer   R/W   Maximum height cap (0 = no limit, stretch to fill).
  Weight       Integer   R/W   Layout weight. 0 = fixed size, >0 = share extra space proportionally.
  Visible      Boolean   R/W   Whether the control is visible.
  Enabled      Boolean   R/W   Whether the control accepts user input. Disabling a container (Frame, VBox, HBox...) also blocks mouse and keyboard input to every control inside it.
  BackColor    Long      R/W   Background color as a 24-bit RGB value packed in a Long (use the RGB function to construct).
  ForeColor    Long      R/W   Foreground (text) color as a 24-bit RGB value packed in a Long (use the RGB function to construct).
  TabIndex     Integer   R     Accepted for VB compatibility but ignored. DVX has no tab order.
  ToolTipText  String    R/W   Tooltip text shown after the mouse hovers over the control. Empty string or unset = no tooltip.
  HelpTopic    String    R/W   Help topic opened by F1 while the control has the focus. Empty = the form's HelpTopic. F1 uses the project's help file.
  DragMode     Integer   R/W   vbManual (0, the default): the program starts a drag with the Drag method. vbAutomatic (1): pressing the left mouse button on the control starts a drag. See Drag and Drop below.
  DragIcon     Picture   R/W   Picture shown under the mouse while the control is dragged: a picture file name (BMP, PNG, JPEG or GIF) or a Picture object from LOADPICTURE (Set works too). Reading it gives a Picture object, which stands for the file name where a value is needed. Empty = a dotted outline the size of the control.

Size properties (Width, Height and the Min/Max sizes) are limited to 0..32767.

Default Properties

As in Visual Basic, a control's name used where a value is needed means its default property: Text1 = "hi" sets Text1.Text, Print Label1 prints Label1.Caption, and If Check1 Then reads Check1.Value. Where an object is expected -- SET, Is, an object parameter, Collection.Add, TypeOf -- the name still means the control itself.

  Control                                               Default property
  -------                                               ----------------
  TextBox, TextArea, ComboBox, DropDown, ListBox, DBGrid   Text
  Label, Frame, Data                                    Caption
  CheckBox, OptionButton, CommandButton                 Value
  HScrollBar, SpinButton, ProgressBar                   Value
  Image, ImageButton, PictureBox                        Picture
  Timer                                                 Enabled

Other controls, forms and menu items have no default property: using one as a value raises error 13.

Common Events

These events are wired on every control loaded from a .frm file. Controls created dynamically at runtime via code only receive Click, DblClick, Change, GotFocus, and LostFocus; the keyboard, mouse, and scroll events below require the control to be defined in the .frm file.

  Event       Parameters                                    Description
  ---------   -------------------------------------------   -------------------------------------------
  Click       (none)                                        Fires when the control is clicked.
  DblClick    (none)                                        Fires when the control is double-clicked.
  Change      (none)                                        Fires when the control's value or text changes.
  GotFocus    (none)                                        Fires when the control receives keyboard focus.
  LostFocus   (none)                                        Fires when the control loses keyboard focus.
  KeyPress    KeyAscii As Integer                           Fires when a printable key is pressed. KeyAscii is the ASCII code.
  KeyDown     KeyCode As Integer, Shift As Integer          Fires when any key is pressed down. KeyCode is the scan code; Shift indicates modifier keys.
  KeyUp       KeyCode As Integer, Shift As Integer          Fires when a key is released.
  MouseDown   Button As Integer, X As Integer, Y As Integer Fires when a mouse button is pressed over the control.
  MouseUp     Button As Integer, X As Integer, Y As Integer Fires when a mouse button is released over the control.
  MouseMove   Button As Integer, X As Integer, Y As Integer Fires when the mouse moves over the control.
  Scroll      Delta As Integer                              Fires when the control is scrolled (mouse wheel or scrollbar).
  DragDrop    Source As Control, X As Integer, Y As Integer Fires when a dragged control is dropped on this control. Source is the dragged control; X and Y are where, in this control.
  DragOver    Source As Control, X As Integer, Y As Integer, State As Integer   Fires while a dragged control moves over this control. State is vbEnter (0) when it comes onto the control, vbOver (2) as it moves across, vbLeave (1) when it goes off.

Common Methods

  Method     Parameters   Description
  --------   ----------   -------------------------------------------
  SetFocus   (none)       Gives keyboard focus to this control.
  Refresh    (none)       Forces the control to repaint.
  Drag       [Action]     Starts or ends dragging this control: vbBeginDrag (1, the default) starts, vbEndDrag (2) drops it where the mouse is, 0 cancels the drag without a drop.

Drag and Drop

Any control can be dragged onto another control or onto a form, as in Visual Basic. While a control is dragged, a dotted outline of it (or its DragIcon picture) follows the mouse, and the controls and forms it passes over get DragOver events. Releasing the mouse button drops it: the control or form under the mouse gets a DragDrop event, with the dragged control as Source. Pressing Esc cancels the drag.

The mouse pointer shows where a drop can land: over a control or form that has a DragDrop event procedure it is the usual arrow; over one without, and outside the program's forms, it is the "no drop" sign (a circle with a line through it). The outline or DragIcon picture still follows the mouse either way.

With DragMode set to vbAutomatic, pressing the left mouse button on the control starts the drag, and the control gets no Click, MouseDown or MouseUp from the left button. With DragMode vbManual, start the drag yourself, usually in MouseDown. A drag started while the mouse button is up ends at the next click. During a drag no mouse events other than DragOver and DragDrop are raised.

Drop targets only react: nothing is moved or copied for you. Use Source in DragDrop to decide what to do, for example read its Name or Caption, or check what kind of control it is with TypeOf Source Is TextBox (see Operators).

Note that vbCancel is the MsgBox Cancel value (2), which as a Drag action means vbEndDrag; cancel a drag with Drag 0.

DragIcon takes a file name or a picture loaded with LOADPICTURE: Set Label1.DragIcon = LoadPicture("drag.bmp"). A missing file or one that is not a picture raises its error at LOADPICTURE; a file name that cannot be read when the drag starts shows the outline instead.

' Label1 has DragMode = 1 (vbAutomatic) in the form designer.
Sub List1_DragOver(Source As Control, X As Integer, Y As Integer, State As Integer)
    If State = vbEnter Then Label2.Caption = "Drop to add " & Source.Caption
End Sub

Sub List1_DragDrop(Source As Control, X As Integer, Y As Integer)
    List1.AddItem Source.Caption
End Sub

' DragMode vbManual: the button starts its own drag, left button only.
Sub Command1_MouseDown(Button As Integer, X As Integer, Y As Integer)
    If Button = 1 Then Command1.Drag vbBeginDrag
End Sub

Form

Data Binding

FRM File Format

Drawing on Forms and PictureBoxes

Forms and PictureBoxes have Visual Basic's drawing methods. They draw with the same code as the QBasic graphics statements (see Console and Graphics in the language reference), in pixels unless ScaleMode or Scale says otherwise, with colours as Visual Basic RGB values, &HBBGGRR (RGB(255, 0, 0) or &HFF is red). A PictureBox draws on its picture; a form gets a drawing area the size of its window the first time it draws, placed with its controls like a PictureBox (so draw on a form that has no controls, or use a PictureBox beside them).

Drawings stay until they are drawn over or cleared. In a form's own code, write Me.Line, Me.Circle and so on: Line, Circle and PSet without an object are the QBasic graphics statements (they draw on the program's screen), and Print without an object is the PRINT statement.

Drawing Methods

  Method                                                          Description
  ------                                                          -----------
  Cls                                                             Clears the drawing to BackColor; CurrentX and CurrentY go to 0.
  PSet [Step](x, y) [, color]                                     Draws a point (DrawWidth wide).
  Line [[Step](x1, y1)]-[Step](x2, y2) [, color] [, B | BF]         Draws a line, a box (B) or a filled box (BF). A box without F is filled with FillColor when FillStyle is 0.
  Circle [Step](x, y), radius [, color [, start [, end [, aspect]]]]  Draws a circle, ellipse or arc, filled with FillColor when FillStyle is 0 (full circles).
  Point(x, y)                                                     The colour of a pixel, -1 outside the picture.
  Print items                                                     Writes text at CurrentX, CurrentY in ForeColor, with PRINT's ; , SPC and TAB; ends by moving to the next line unless the last item is followed by ; or ,.
  PaintPicture picture, x, y [, width, height [, srcX, srcY, srcWidth, srcHeight [, opcode]]]   Copies a picture, stretched to width x height: an image file (BMP, PNG, JPEG or GIF), a picture from LOADPICTURE, or a PictureBox given by its name as a string or by a Control variable. opcode combines each pixel with the one already there (see Raster Operations).
  Scale [(x1, y1)-(x2, y2)]                                        Gives the drawing coordinates of its own: (x1, y1) is the top-left corner and (x2, y2) the bottom-right one (y2 below y1 makes y go up). Scale alone goes back to pixels.
  ScaleX(width [, fromScale [, toScale]])                         A width in fromScale converted to toScale (see Scales).
  ScaleY(height [, fromScale [, toScale]])                        A height in fromScale converted to toScale.
  TextWidth(text)                                                 Width of the text in the scale's units.
  TextHeight(text)                                                Height of a line of text in the scale's units.

Without a colour, drawing uses ForeColor. Step makes a point relative to CurrentX, CurrentY, which every drawing method leaves at its last point. Coordinates, radii, CurrentX and CurrentY and PaintPicture's rectangles are in the scale's units (a radius in its horizontal units); DrawWidth is always in pixels. A colour or angle out of range stops the program with an error.

Raster Operations

PaintPicture's opcode says how each copied pixel is combined with the pixel already there (the destination) and with the FillColor (the pattern), as in Visual Basic. Leaving it out copies the picture (vbSrcCopy).

  Constant        Value       Result
  --------        -----       ------
  vbSrcCopy       &HCC0020    The picture
  vbSrcPaint      &HEE0086    Picture OR destination
  vbSrcAnd        &H8800C6    Picture AND destination
  vbSrcInvert     &H660046    Picture XOR destination
  vbSrcErase      &H440328    Picture AND NOT destination
  vbNotSrcCopy    &H330008    NOT picture
  vbNotSrcErase   &H1100A6    NOT (picture OR destination)
  vbMergeCopy     &HC000CA    Picture AND pattern
  vbMergePaint    &HBB0226    NOT picture OR destination
  vbPatCopy       &HF00021    The pattern
  vbPatPaint      &HFB0A09    Pattern OR NOT picture OR destination
  vbPatInvert     &H5A0049    Pattern XOR destination
  vbDstInvert     &H550009    NOT destination

Any of the 256 raster operations of Windows can be given by its number; the bits work on the pixel values, so with fewer than 32 bits a pixel the results follow the display's colour format.

Picture1.PaintPicture Picture2, 0, 0, 32, 32, 0, 0, 32, 32, vbSrcInvert   ' XOR the picture in
Picture1.PaintPicture Picture2, 0, 0, 32, 32, 0, 0, 32, 32, vbSrcInvert   ' and out again

Scales

ScaleMode picks the units: 0 user (set by Scale or the Scale properties), 1 twips (1440 an inch, 15 a pixel), 2 points (72 an inch), 3 pixels, 4 characters (120 twips across, 240 down), 5 inches, 6 millimetres, 7 centimetres. Unlike Visual Basic, whose default is twips, DVX starts every form and PictureBox in pixels (ScaleMode 3), and Scale without arguments goes back to pixels. Setting ScaleLeft, ScaleTop, ScaleWidth or ScaleHeight makes a user scale from the current one; ScaleWidth and ScaleHeight may not be 0. With a user scale the units stay fixed to the picture's edges when it is resized; other scale modes keep their unit size.

The constants vbUser (0), vbTwips (1), vbPoints (2), vbPixels (3), vbCharacters (4), vbInches (5), vbMillimeters (6) and vbCentimeters (7) name the scale modes. The units assume a standard display of 96 pixels an inch (15 twips a pixel), whatever the screen really is, so an inch is always 96 pixels.

ScaleX and ScaleY convert a width or a height from one scale to another, as in Visual Basic: fromScale is the scale the value is in, vbHimetric (8, hundredths of a millimetre, the unit of a Picture's Width and Height) when it is left out; toScale the scale wanted, the object's ScaleMode when left out. vbUser means the object's current scale. Visual Basic's vbContainerPosition and vbContainerSize are not available; any other scale number stops the program with an error.

Picture1.Scale (0, 100)-(100, 0)     ' 0..100 across, y going up
Picture1.Line (0, 0)-(100, 100), RGB(255, 0, 0)
Picture1.ScaleMode = 7               ' centimetres
Picture1.Circle (2, 2), 1

Dim pic As Object
Set pic = LoadPicture("logo.bmp")
w = Me.ScaleX(pic.Width, vbHimetric, vbPixels)   ' the picture's width in pixels

AutoRedraw and the Paint Event

A form or PictureBox fires its Paint event when it is shown, when the form is resized, when a PictureBox changes size (its Width or Height set to a new value, or its Resize method) while its form is showing, and when the program calls its Refresh method, so a program can draw everything in Paint as in Visual Basic. Unlike Visual Basic, DVX keeps what was drawn even with AutoRedraw False (the default), so drawing outside Paint also stays on the screen. With AutoRedraw = True, Paint does not fire. A program that sets AutoRedraw = False itself gets Visual Basic's behaviour exactly: the drawing is cleared to BackColor before each Paint.

Sub Picture1_Paint ()
    Picture1.Circle (50, 50), 40, RGB(0, 128, 0)
End Sub

Drawing Properties

  Property      Type      Default   Description
  --------      ----      -------   -----------
  ForeColor     Long      &H000000  Colour of drawing and printing.
  BackColor     Long      &HFFFFFF  Colour Cls clears to. Setting it clears the drawing to the new colour.
  CurrentX      Single    0         Where the next drawing or printing starts.
  CurrentY      Single    0
  DrawWidth     Integer   1         Pen width in pixels.
  FillStyle     Integer   1         How boxes (B) and circles are filled with FillColor: 0 solid, 1 (the default) not at all, 2 horizontal lines, 3 vertical lines, 4 upward diagonals, 5 downward diagonals, 6 a cross hatch, 7 a diagonal cross hatch (the lines 8 pixels apart, the gaps left as they are). Other values are an error. BF fills solid in the line's colour.
  FillColor     Long      &H000000  Colour boxes and circles are filled with.
  AutoRedraw    Boolean   False     True: no Paint events (see above).
  ScaleMode     Integer   3         Units of the coordinates (see Scales).
  ScaleLeft     Single    0         Coordinate of the left edge.
  ScaleTop      Single    0         Coordinate of the top edge.
  ScaleWidth    Single    (size)    Width of the drawing in the scale's units.
  ScaleHeight   Single    (size)    Height of the drawing in the scale's units.

Example

Sub Command1_Click ()
    Picture1.Resize 200, 150
    Picture1.BackColor = RGB(255, 255, 255)
    Picture1.DrawWidth = 2
    Picture1.Line (10, 10)-(190, 140), RGB(0, 0, 255), B
    Picture1.FillStyle = 0
    Picture1.FillColor = RGB(255, 255, 0)
    Picture1.Circle (100, 75), 40, RGB(255, 0, 0)
    Picture1.CurrentX = 70
    Picture1.CurrentY = 120
    Picture1.Print "Hello!"
End Sub

PictureBox

Form

Data Binding

DVX BASIC provides VB3-style data binding through three properties that can be set on most controls:

  Property     Set On        Description
  ----------   -----------   -------------------------------------------
  DataSource   Any control   Name of the Data control to bind to (e.g. "Data1").
  DataField    Any control   Column name from the Data control's recordset to display.

How It Works

Master-Detail Binding

For hierarchical data (e.g. orders and order items), use two Data controls:

When the master record changes, the detail Data control automatically re-queries using the master's current value for filtering. All controls bound to the detail are refreshed.

DBGrid Binding

Set the DBGrid's DataSource to a Data control name. The grid auto-populates columns from the query results and refreshes whenever the Data control refreshes.

Example

VERSION DVX 1.00
Begin Form frmData
    Caption      = "Data Binding Example"
    AutoSize     = False
    Width        = 400
    Height       = 280
    Begin Data Data1
        DatabaseName = "myapp.db"
        RecordSource = "customers"
    End
    Begin Label lblName
        Caption = "Name:"
    End
    Begin TextBox txtName
        DataSource = "Data1"
        DataField  = "name"
    End
    Begin Label lblEmail
        Caption = "Email:"
    End
    Begin TextBox txtEmail
        DataSource = "Data1"
        DataField  = "email"
    End
End

Sub Data1_Reposition ()
    Print "Current record changed"
End Sub

Sub Data1_Validate (Cancel As Integer)
    If txtName.Text = "" Then
        MsgBox "Name cannot be empty!"
        Cancel = 1
    End If
End Sub

Data

DBGrid

Menu System

Menus are defined in the .frm file using Begin Menu blocks. Each menu item has a name, caption, and nesting level. Menu items fire Click events dispatched as MenuName_Click.

FRM Syntax

Begin Form Form1
    Caption = "Menu Demo"

    Begin Menu mnuFile
        Caption = "&File"
        Begin Menu mnuOpen
            Caption = "&Open"
        End
        Begin Menu mnuSave
            Caption = "&Save"
        End
        Begin Menu mnuSep1
            Caption = "-"
        End
        Begin Menu mnuExit
            Caption = "E&xit"
        End
    End

    Begin Menu mnuEdit
        Caption = "&Edit"
        Begin Menu mnuCopy
            Caption = "&Copy"
        End
        Begin Menu mnuPaste
            Caption = "&Paste"
        End
    End
End

Menu Item Properties

In the .frm file a menu item takes these keys:

  Key          Type      Description
  ----------   -------   -------------------------------------------
  Caption      String    The text displayed. Use & for accelerator key. Set to "-" for a separator.
  Checked      Boolean   Whether the menu item shows a checkmark.
  RadioCheck   Boolean   Show the check as a radio dot instead of a checkmark.
  Enabled      Boolean   Whether the menu item is enabled (default True).
  Visible      Boolean   On a top-level menu only: False makes it a popup menu (for ContextMenu) instead of a menu bar entry.

At run time code can use only these properties of a menu item:

  Property   Type      R/W   Description
  --------   -------   ---   -------------------------------------------
  Name       String    R     The menu item's name.
  Checked    Boolean   R/W   Whether the menu item shows a checkmark.
  Enabled    Boolean   R/W   Whether the menu item is enabled.

Caption, RadioCheck and Visible are design-time only: using them on a menu item in code is a compile error in the IDE and a runtime error (Unknown menu property) otherwise.

Nesting

Menu items are nested by placing Begin Menu blocks inside other Begin Menu blocks:

A level-0 menu that contains children becomes a top-level menu header. A non-level-0 menu that contains children becomes a submenu.

Event Dispatch

Each clickable menu item (not headers, not separators) receives a unique numeric ID at load time. When clicked, the form's onMenu handler maps the ID to the menu item's name and fires MenuName_Click.

Sub mnuOpen_Click ()
    MsgBox "Open was clicked"
End Sub

Sub mnuExit_Click ()
    Unload Form1
End Sub

Form

FRM File Format

Control Arrays

DVX BASIC supports VB-style control arrays. Multiple controls can share the same name, differentiated by an Index property. When an event fires on a control array element, the element's index is passed as the first parameter.

Defining Control Arrays in FRM

Begin CommandButton Command1
    Caption = "Button A"
    Index   = 0
End
Begin CommandButton Command1
    Caption = "Button B"
    Index   = 1
End
Begin CommandButton Command1
    Caption = "Button C"
    Index   = 2
End

Event Handler Convention

When a control has an Index property (>= 0), the event handler receives Index As Integer as the first parameter, before any event-specific parameters.

Sub Command1_Click (Index As Integer)
    Select Case Index
        Case 0
            MsgBox "Button A clicked"
        Case 1
            MsgBox "Button B clicked"
        Case 2
            MsgBox "Button C clicked"
    End Select
End Sub

Accessing Array Elements in Code

Use the indexed form ControlName(Index) to access a specific element:

Command1(0).Caption = "New Text"
Command1(1).Enabled = False
Note: Control array elements share the same event handler Sub. The runtime prepends the Index argument automatically. If you define parameters on the Sub, Index comes first, followed by the event's own parameters (e.g. KeyPress would be Sub Ctrl1_KeyPress (Index As Integer, KeyAscii As Integer)).

Common Properties, Events, and Methods

FRM File Format

FRM File Format

The .frm file is a text file that describes a form's layout, controls, menus, and code. It follows a format compatible with VB3 .frm files, with DVX-specific extensions.

Structure

VERSION DVX 1.00
Begin Form FormName
    form-level properties...

    Begin Menu mnuFile
        Caption = "&File"
        Begin Menu mnuOpen
            Caption = "&Open"
        End
    End

    Begin TypeName ControlName
        property = value
        ...
    End

    Begin Frame Frame1
        Caption = "Group"
        Begin TypeName ChildName
            ...
        End
    End
End

BASIC code follows...

Sub FormName_Load ()
    ...
End Sub

Rules

Common FRM Properties

  Property                  Applies To        Description
  -----------------------   ---------------   -------------------------------------------
  Caption                   Form, controls    Display text or window title.
  Text                      TextBox, ComboBox Initial text content.
  MinWidth / Width          Controls          Minimum width. Both names are accepted.
  MinHeight / Height        Controls          Minimum height. Both names are accepted.
  MaxWidth                  Controls          Maximum width (0 = no cap).
  MaxHeight                 Controls          Maximum height (0 = no cap).
  Weight                    Controls          Layout weight for flexible sizing.
  Left                      Form, controls    X position (used by Form when Centered=False; informational for controls).
  Top                       Form, controls    Y position.
  Index                     Controls          Control array index (-1 or absent = not in array).
  Visible                   Controls          Initial visibility.
  Enabled                   Controls          Initial enabled state.
  Layout                    Form              "VBox" or "HBox".
  AutoSize                  Form              Auto-fit window to content.
  Resizable                 Form              Allow runtime resizing.
  Centered                  Form              Center window on screen.
  DatabaseName              Data              SQLite database file path.
  RecordSource              Data              Table name or SQL query.
  DataSource                Bound controls    Name of the Data control.
  DataField                 Bound controls    Column name in the recordset.

Form

Common Properties, Events, and Methods

Menu System

Control Arrays

Form

VB Equivalent: Form -- DVX Widget: Window + VBox/HBox root

The Form is the top-level container representing a DVX window. It is declared in the .frm file with Begin Form FormName. All controls are children of the form's content box, which uses either VBox (default) or HBox layout.

Form Properties

  Property    Type      Default          Description
  ----------  -------   --------------   -------------------------------------------
  Name        String    "Form1"          The form's name, used for event dispatch and Load statement.
  Caption     String    (same as Name)   Window title bar text.
  Width       Integer   400              Window width in pixels. In the .frm file it is ignored when AutoSize is True.
  Height      Integer   300              Window height in pixels. In the .frm file it is ignored when AutoSize is True.
  Left        Integer   0                Initial X position. Used when Centered is False.
  Top         Integer   0                Initial Y position. Used when Centered is False.
  Layout      String    "VBox"           Content box layout: "VBox" (vertical) or "HBox" (horizontal).
  AutoSize    Boolean   False            When True, the window shrink-wraps to fit its content.
  Resizable   Boolean   True             Whether the user can resize the window at runtime.
  Centered    Boolean   True             When True, the window is centered on screen. When False, Left/Top are used.
  Visible     Boolean   False            True shows the form and False hides it, exactly like Show and Hide (the first show fires Activate).
  ContextMenu String    ""               Name of a popup menu shown when the form is right-clicked.
  HelpTopic   String    ""               Help topic opened by F1 while the form is active and the focused control has no HelpTopic of its own. Empty opens the project's help file at its default page.

Form Events

  Event         Parameters              Description
  -----------   ---------------------   -------------------------------------------
  Load          (none)                  Fires after the form and all controls are created. This is the default event.
  Unload        (none)                  Fires when the form is being closed or unloaded.
  QueryUnload   Cancel As Integer       Fires before Unload. Set Cancel = 1 to abort the close.
  Resize        (none)                  Fires when the window is resized by the user.
  Activate      (none)                  Fires when the window gains focus.
  Deactivate    (none)                  Fires when the window loses focus.
  Paint         (none)                  Fires when the form is shown or resized and on Refresh, unless AutoRedraw is True (see Drawing on Forms and PictureBoxes).
  DragDrop      Source As Control, X As Integer, Y As Integer                     Fires when a dragged control is dropped on an empty part of the form. X and Y are where, in the form.
  DragOver      Source As Control, X As Integer, Y As Integer, State As Integer   Fires while a dragged control moves over an empty part of the form. State is vbEnter, vbLeave or vbOver.

See Drag and Drop under Common Properties, Events, and Methods. While a control is dragged over a form with no DragDrop event procedure, the mouse pointer shows the "no drop" sign.

Form Methods

  Statement           Description
  ------------------  -------------------------------------------
  Load FormName       Load the form (creates the window and controls, fires Load event).
  Unload FormName     Unload the form (fires Unload, destroys window).
  FormName.Show       Make the form visible.
  FormName.Show 1     Show as modal dialog (blocks until closed).
  FormName.Hide       Hide the form without unloading it.

Drawing

Forms have Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, FillColor, FillStyle, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight): see Drawing on Forms and PictureBoxes. In the form's own code use Me.Line, Me.Circle and so on.

Example

Sub Form_Load ()
    Form1.Caption = "Hello World"
    Print "Form loaded!"
End Sub

Sub Form_QueryUnload (Cancel As Integer)
    If MsgBox("Really quit?", 4) <> 6 Then
        Cancel = 1
    End If
End Sub

Sub Form_Resize ()
    Print "Window resized"
End Sub

Common Properties, Events, and Methods

Drawing on Forms and PictureBoxes

FRM File Format

Terminal

DVX Extension -- DVX Widget: ansiterm

A VT100/ANSI terminal emulator with a text-mode cell buffer, 16-color CGA palette, and scrollback history. Processes standard ANSI escape sequences (cursor control, erase, scroll, SGR colors, DEC private modes) typically used by DOS BBS software. Default size is 80 columns by 25 rows. Supports text selection with the mouse, Ctrl+C to copy, and Ctrl+V to send clipboard text as input. Shift+PgUp and Shift+PgDn page through the scrollback history and the mouse wheel scrolls it; any other key is sent to the host and returns the view to the live screen.

Type-Specific Properties

  Property     Type      Description
  ----------   -------   -------------------------------------------
  Cols         Integer   Number of character columns (read-only).
  Rows         Integer   Number of character rows (read-only).
  Scrollback   Integer   Maximum number of scrollback lines. Older lines are dropped (default 500). Setting it discards the existing history.

Type-Specific Methods

  Method             Description
  ------             -----------
  Clear              Clear the terminal screen and reset the cursor to the home position.
  Poll               Poll the attached communication channel for incoming bytes and feed them into the ANSI parser.
  Write text$        Write a string to the terminal with full ANSI escape processing.

No default event. Uses common events only.

Serial Communication

Use the comm.bas library to connect a Terminal to a serial link:

Dim link As Long
link = CommOpen(1, 115200, 8, "N", 1, SER_HANDSHAKE_NONE)
If link <> 0 Then
    If CommHandshake(link, "secret") Then
        CommAttach link, "Terminal1", 0, True
    Else
        MsgBox "Handshake failed"
    End If
End If

The passphrase is optional. Both ends must give the same passphrase, or both give none; otherwise CommHandshake returns False. See comm.bas for the full communications API.

Example

Begin Terminal Terminal1
    MinWidth  = 640
    MinHeight = 400
End

Sub Form_Load ()
    Terminal1.Write "Welcome!" & Chr$(13) & Chr$(10)
End Sub

Common Properties, Events, and Methods

Frame

VB Equivalent: Frame -- DVX Widget: frame (titled container)

A container with a titled border. Child controls are placed inside the frame using VBox layout. In the .frm file, nest Begin/End blocks inside the Frame block.

Type-Specific Properties

  Property   Type     Description
  --------   ------   -------------------------------------------
  Caption    String   The title displayed in the frame border.

No type-specific methods or events.

Setting Enabled = False on a Frame disables every control inside it for mouse and keyboard input.

Container: Yes

Default Event: Click

Example

Begin Frame Frame1
    Caption = "Options"
    Begin CheckBox Check1
        Caption = "Option A"
    End
    Begin CheckBox Check2
        Caption = "Option B"
    End
End

Common Properties, Events, and Methods

HBox

DVX Extension -- DVX Widget: hbox (horizontal layout container)

A container that arranges its children horizontally, left to right. No visible border. Use Weight on children to distribute extra space proportionally.

No type-specific properties, methods, or events.

Container: Yes

Default Event: Click

Example

Begin HBox ButtonRow
    Spacing = 4
    Begin CommandButton Command1
        Caption = "OK"
    End
    Begin CommandButton Command2
        Caption = "Cancel"
    End
End

Common Properties, Events, and Methods

VBox

VBox

DVX Extension -- DVX Widget: vbox (vertical layout container)

A container that arranges its children vertically, top to bottom. No title or border. Use Weight on children to distribute extra space proportionally.

No type-specific properties, methods, or events.

Container: Yes

Default Event: Click

Example

Begin VBox Column1
    Spacing = 4
    Begin Label Label1
        Caption = "Name:"
    End
    Begin TextBox Text1
    End
End

Common Properties, Events, and Methods

HBox

CommandButton

VB Equivalent: CommandButton -- DVX Widget: button | Name Prefix: Command

A push button that triggers an action when clicked. The Caption may include a '&' before a character to mark an accelerator key (e.g. "&OK" underlines 'O', and Alt+O activates the button).

Type-Specific Properties

  Property   Type     Description
  --------   ------   -------------------------------------------
  Caption    String   The text displayed on the button. Use '&' for an accelerator key.

No type-specific methods or events.

Default Event: Click

Example

Begin Form Form1
    Caption = "Button Demo"
    Begin CommandButton Command1
        Caption = "&Click Me!"
    End
End

Sub Command1_Click ()
    MsgBox "Button was clicked!"
End Sub

Common Properties, Events, and Methods

PictureBox

VB Equivalent: PictureBox -- DVX Widget: canvas | Name Prefix: Picture

A drawing surface (canvas). Supports drawing lines, rectangles, circles, text, and individual pixels. Can load BMP, PNG, JPEG and GIF images and save BMP or PNG images. The default canvas size is 64x64 pixels.

Colors are Visual Basic RGB values, &HBBGGRR, as RGB() makes them (RGB(255, 0, 0) or &HFF is red).

Type-Specific Properties

  Property      Type      Description
  --------      ----      -----------
  ImageHeight   Integer   Height of the drawing in pixels (read-only). After Load it is the loaded image's height.
  ImageWidth    Integer   Width of the drawing in pixels (read-only). After Load it is the loaded image's width.

Load and Save return 0 on success and -1 on failure (missing or unreadable file, unsupported format, path that cannot be written). Call them as functions to check the result, or as statements to ignore it. A failed Load leaves the drawing unchanged.

Type-Specific Methods

  Method                                        Description
  ------                                        -----------
  Clear color%                                  Fill the entire canvas with the specified color.
  DrawLine x0%, y0%, x1%, y1%, color%           Draw a line between two points.
  DrawRect x%, y%, w%, h%, color%               Draw a rectangle outline.
  DrawText x%, y%, text$                        Draw text at the given position.
  FillCircle cx%, cy%, radius%, color%          Draw a filled circle.
  FillRect x%, y%, w%, h%, color%               Draw a filled rectangle.
  GetPixel(x%, y%)                              Returns the color at a pixel.
  Load(path$)                                   Load a BMP, PNG, JPEG or GIF image; the canvas takes the image's size. Returns 0 on success, -1 on failure.
  Resize w%, h%                                 Resize the canvas to new dimensions. The drawing is cleared to white.
  Save(path$)                                   Save the canvas: BMP when path$ ends in .bmp, PNG otherwise. Returns 0 on success, -1 on failure.
  SetPenColor color%                            Set the drawing color for subsequent operations.
  SetPenSize size%                              Set the pen/brush size in pixels (1 to 255; larger values use 255).
  SetPixel x%, y%, color%                       Set the color of a single pixel.

Default Event: Click

Example

Picture1.Resize 200, 150
Picture1.Clear &HFFFFFF
Picture1.SetPenSize 2
Picture1.DrawRect 10, 10, 180, 130, &H000000
Picture1.FillCircle 100, 75, 40, RGB(255, 0, 0)
Picture1.DrawText 60, 130, "Hello!"
If Picture1.Save("output.bmp") <> 0 Then
    MsgBox "Could not save output.bmp"
End If

A PictureBox also has Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, FillColor, FillStyle, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight) and a Paint event: see Drawing on Forms and PictureBoxes.

Common Properties, Events, and Methods

Drawing on Forms and PictureBoxes

CheckBox

VB Equivalent: CheckBox -- DVX Widget: checkbox

A toggle control with a label. The checked state is exposed as a Boolean. Supports accelerator keys (put '&' before a character in the Caption). Press Space or Enter to toggle when focused.

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  Caption    String    The text displayed next to the checkbox.
  Value      Boolean   True if checked, False if unchecked.

No type-specific methods or events.

Default Event: Click

Example

Begin CheckBox Check1
    Caption = "Enable feature"
End

Sub Check1_Click ()
    If Check1.Value Then
        Label1.Caption = "Feature ON"
    Else
        Label1.Caption = "Feature OFF"
    End If
End Sub

Common Properties, Events, and Methods

ComboBox

VB Equivalent: ComboBox -- DVX Widget: combobox (editable text field + drop-down list, default maxLen 256)

A combination of a single-line text input and a drop-down list. The user can either type a value or pick one from the list. Selecting a list item copies its text into the edit field. Supports the same AddItem / RemoveItem / Clear / List methods as ListBox.

Type-Specific Properties

  Property    Type      Description
  ---------   -------   -------------------------------------------
  Text        String    The text in the editable field.
  ListIndex   Integer   Index of the currently selected list item (-1 = user typed something not in the list).

Type-Specific Methods

  Method              Description
  ------              -----------
  AddItem text$       Append an item to the drop-down list.
  Clear               Remove all items.
  List(index%)        Return the text of the item at the given index.
  ListCount()         Return the number of items in the list.
  RemoveItem index%   Remove the item at the given index. The selection stays on the same item; removing the selected item leaves no selection (the text is kept).

Default Event: Click

Example

Begin ComboBox Combo1
End

Sub Form_Load ()
    Combo1.AddItem "Small"
    Combo1.AddItem "Medium"
    Combo1.AddItem "Large"
End Sub

Sub Combo1_Change ()
    Label1.Caption = "Selected: " & Combo1.Text
End Sub

Common Properties, Events, and Methods

See ListBox for details

Data

VB Equivalent: Data -- DVX Widget: data | Name Prefix: Data

A data access control that connects to a SQLite database and provides record navigation. Other controls bind to a Data control via their DataSource and DataField properties. The Data control cache is populated by calling Refresh. Move operations and Refresh auto-save the current row if dirty; a move is refused while the save fails, and Refresh discards an edit that cannot be saved. Updates find the record by the key value it was loaded with, so the key column itself can be edited; a key stored as a number in a column without a declared type, or a missing (NULL) key, is still found as long as it identifies exactly one record. Writing a field back with the value it already has is not an edit and does not fire Validate. While a Validate handler runs, MoveFirst, MoveLast, MoveNext, MovePrevious, AddNew, Refresh and Update on the same Data control are ignored (they would save, and validate, the same record again); Delete is allowed. A RecordSource that is a SELECT query is read-only, and edits made to its records are dropped when the current record changes.

See Data Binding for details

Type-Specific Properties

  Property       Type      Description
  ------------   -------   -------------------------------------------
  DatabaseName   String    Path to the SQLite database file.
  RecordSource   String    Table name or SQL SELECT query for the recordset.
  KeyColumn      String    Primary key column name (used for UPDATE/DELETE operations).
  Caption        String    Text displayed on the navigator bar.
  BOF            Boolean   True if the current position is the first record or there are no records (read-only).
  EOF            Boolean   True if the current position is past the last record or there are no records (read-only).
  MasterSource   String    Name of a master Data control (for master-detail binding).
  MasterField    String    Column in the master recordset to read for the filter value.
  DetailField    String    Column in this recordset that matches the master field.

Type-Specific Methods

  Method         Parameters   Description
  ------------   ----------   -------------------------------------------
  MoveFirst      (none)       Navigate to the first record.
  MoveLast       (none)       Navigate to the last record.
  MoveNext       (none)       Navigate to the next record.
  MovePrevious   (none)       Navigate to the previous record.
  AddNew         (none)       Append a blank record and move to it.
  Delete         (none)       Delete the current record.
  Refresh        (none)       Re-query the database and reload records.
  Update         (none)       Write pending changes to the database.

Type-Specific Events

  Event        Parameters          Description
  ----------   -----------------   -------------------------------------------
  Reposition   (none)              Fires after the current record changes. Default event.
  Validate     Cancel As Integer   Fires before writing. Set Cancel = 1 to abort.

Default Event: Reposition

Example

Begin Data Data1
    DatabaseName = "books.db"
    RecordSource = "titles"
    KeyColumn    = "id"
End

Begin TextBox Text1
    DataSource = "Data1"
    DataField  = "title"
End

Sub Form_Load ()
    Data1.Refresh
End Sub

Common Properties, Events, and Methods

Data Binding

DBGrid

DBGrid

VB Equivalent: DBGrid -- DVX Widget: dbgrid | Name Prefix: DBGrid

A data-bound grid that displays records from a Data control in a tabular format. Columns auto-populate from the query results. Bind the grid using the DataSource property. Click a column header to sort; drag a column border to resize. The highlighted row is always the bound Data control's current record: selecting a row moves the Data control's cursor, and navigating the Data control moves the highlight. Re-binding keeps the sort order and column settings, and a column width set by dragging a border is kept. Text wider than its column is clipped. The mouse wheel scrolls the rows without changing the current record.

Type-Specific Properties

  Property     Type      Description
  ----------   -------   -------------------------------------------
  DataSource   String    Name of the Data control that supplies records.
  GridLines    Boolean   Show or hide grid lines between cells (default: True).
  SelectedRow  Integer   Index of the current record's row (-1 = no records). Setting it moves the Data control's cursor; negative values are ignored.

Type-Specific Methods

  Method             Parameters                        Description
  ----------------   -------------------------------   -------------------------------------------
  Refresh            (none)                            Reload and redraw the grid from the Data control.
  SetColumnHeader    Field As String, Header As String  Set the displayed header text for a column.
  SetColumnVisible   Field As String, Visible As Boolean  Show or hide a column by field name.
  SetColumnWidth     Field As String, Width As Integer  Set the pixel width of a column by field name.

Type-Specific Events

  Event      Parameters   Description
  --------   ----------   -------------------------------------------
  Click      (none)       Fires when a row is clicked.
  DblClick   (none)       Fires when a row is double-clicked. Default event.

Default Event: DblClick

Example

Begin Data Data1
    DatabaseName = "books.db"
    RecordSource = "titles"
End

Begin DBGrid DBGrid1
    DataSource = "Data1"
    GridLines  = True
End

Sub Form_Load ()
    Data1.Refresh
End Sub

Sub DBGrid1_DblClick ()
    MsgBox "Opening row " & Str$(Data1.BOF)
End Sub

Common Properties, Events, and Methods

Data

Data Binding

DropDown

DVX Extension -- DVX Widget: dropdown (non-editable drop-down list)

A read-only drop-down list. Unlike ComboBox, the user cannot type free text; they can only select from the provided items. Supports AddItem / RemoveItem / Clear / List. Use the Up and Down keys to change the choice. F4, Alt+Down, Space or Enter opens the list; in the open list use the arrow keys to move and Enter (or F4, Alt+Down) to pick. Esc closes the list without changing the choice.

Type-Specific Properties

  Property    Type      Description
  ---------   -------   -------------------------------------------
  ListIndex   Integer   Index of the currently selected item (-1 = none).

Type-Specific Methods

  Method              Description
  ------              -----------
  AddItem text$       Append an item to the drop-down list.
  Clear               Remove all items.
  List(index%)        Return the text of the item at the given index.
  ListCount()         Return the number of items in the list.
  RemoveItem index%   Remove the item at the given index. The selection stays on the same item; removing the selected item leaves no selection.

Default Event: Change (fires when the user picks a new item; Click fires only when the arrow opens the popup)

Example

Begin DropDown DropDown1
End

Sub Form_Load ()
    DropDown1.AddItem "Small"
    DropDown1.AddItem "Medium"
    DropDown1.AddItem "Large"
    DropDown1.ListIndex = 1
End Sub

Sub DropDown1_Change ()
    Label1.Caption = "Picked: " & DropDown1.List(DropDown1.ListIndex)
End Sub

Common Properties, Events, and Methods

See ListBox for details

ImageButton

DVX Extension -- DVX Widget: imagebutton

A button that displays an image instead of text. Has the same press/release behavior as CommandButton, but shows a bitmap. Typically used inside a Toolbar.

Type-Specific Properties

  Property      Type      Description
  -----------   -------   -------------------------------------------
  Picture       Picture   Path to an image file to load (or a Picture object from LOADPICTURE). Reads back as a Picture object for the file the image came from, which stands for the file name where a value is needed. Setting it to "" clears the image. A file that cannot be loaded leaves the image and Picture unchanged.
  ImageWidth    Integer   Width of the loaded image in pixels (read-only).
  ImageHeight   Integer   Height of the loaded image in pixels (read-only).

No type-specific methods or events.

Default Event: Click

Example

Begin Toolbar Toolbar1
    Begin ImageButton ImageButton1
        Picture = "icons/save.bmp"
    End
    Begin ImageButton ImageButton2
        Picture = "icons/open.bmp"
    End
End

Sub ImageButton1_Click ()
    MsgBox "Save clicked"
End Sub

Common Properties, Events, and Methods

Image

VB Equivalent: Image -- DVX Widget: image

A static image display control. Loads bitmap images from file. Set the Picture property at design-time (in the .frm file) or at runtime to load a file.

Type-Specific Properties

  Property      Type      Description
  -----------   -------   -------------------------------------------
  Picture       Picture   Path to an image file to load (or a Picture object from LOADPICTURE). Reads back as a Picture object for the file the image came from, which stands for the file name where a value is needed. Setting it to "" clears the image. A file that cannot be loaded leaves the image and Picture unchanged. A disabled Image is drawn grayed (its transparent color stays transparent).
  Stretch       Boolean   When True, an image larger than the control is scaled down to fit, keeping its proportions; a smaller image stays at natural size. When False, the image is shown at natural size.
  ImageWidth    Integer   Width of the loaded image in pixels (read-only).
  ImageHeight   Integer   Height of the loaded image in pixels (read-only).

No type-specific methods or events.

Default Event: Click

Example

Begin Image Image1
    Picture = "assets/logo.bmp"
    Stretch = True
End

Sub Image1_Click ()
    MsgBox "Size: " & Str$(Image1.ImageWidth) & "x" & Str$(Image1.ImageHeight)
End Sub

Common Properties, Events, and Methods

Label

VB Equivalent: Label -- DVX Widget: label

A static text label. Supports left, center, and right alignment. Put '&' before a character in the Caption to define an accelerator that moves focus to the next focusable control.

Type-Specific Properties

  Property    Type   Description
  ---------   ----   -------------------------------------------
  Caption     String The text displayed by the label.
  Alignment   Enum   Text alignment: Left (default), Center, or Right.

No type-specific methods or events.

Default Event: Click

Example

Begin Label Label1
    Caption   = "Hello, World!"
    Alignment = "Center"
End

Common Properties, Events, and Methods

ListBox

VB Equivalent: ListBox -- DVX Widget: listbox

A scrollable list of selectable items. Items are managed via methods (AddItem, RemoveItem, Clear). Supports single and multi-select modes, drag-to-reorder, and keyboard navigation with type-ahead search.

Type-Specific Properties

  Property    Type      Description
  ---------   -------   -------------------------------------------
  ListIndex   Integer   Index of the currently selected item (-1 = no selection).

Type-Specific Methods

  Method            Parameters                                Description
  ---------------   ---------------------------------------   -------------------------------------------
  AddItem           Text As String                            Add an item to the end of the list.
  Clear             (none)                                    Remove all items from the list.
  ClearSelection    (none)                                    Deselect all items.
  IsItemSelected    Index As Integer                          Returns True if the item at Index is selected.
  List              Index As Integer                          Return the text of the item at the given index.
  ListCount         (none)                                    Return the number of items in the list.
  RemoveItem        Index As Integer                          Remove the item at the given index. Items after it keep their selection; removing the selected item leaves no selection.
  SelectAll         (none)                                    Select all items (multi-select mode).
  SetItemSelected   Index As Integer, Selected As Boolean     Select or deselect a specific item.
  SetItems          Items As String                           Bulk-load items from a pipe-delimited string (e.g. "Red|Green|Blue"). Replaces existing items. Every "|" separates two items ("a|" is "a" and an empty item); "" empties the list.
  SetMultiSelect    Multi As Boolean                          Enable or disable multi-select mode.
  SetReorderable    Reorderable As Boolean                    Enable or disable drag-to-reorder.

Default Event: Click

Example

Sub Form_Load ()
    List1.AddItem "Apple"
    List1.AddItem "Banana"
    List1.AddItem "Cherry"
End Sub

Sub List1_Click ()
    Dim idx As Integer
    idx = List1.ListIndex
    If idx >= 0 Then
        Label1.Caption = "Selected: " & List1.List(idx)
    End If
End Sub

Common Properties, Events, and Methods

ComboBox

DropDown

ListView

VB Equivalent: ListView -- DVX Widget: listview

A multi-column list with column headers. Supports sorting, multi-select, and drag-to-reorder.

Type-Specific Properties

  Property    Type      R/W   Description
  ---------   -------   ---   -------------------------------------------
  ListIndex   Integer   R/W   Index of the currently selected row (-1 = none).

Type-Specific Methods

  Method                                        Description
  ------                                        -----------
  AddItem text$                                 Add a row (sets first column text).
  Clear                                         Remove all rows.
  ClearSelection                                Deselect all rows.
  GetCell$(row%, col%)                          Returns the text of a cell.
  IsItemSelected(index%)                        Returns True if the row is selected.
  RemoveItem index%                             Remove a row by index. Rows after it keep their selection; removing the selected row leaves no selection.
  RowCount()                                    Returns the number of rows.
  SelectAll                                     Select all rows.
  SetCell row%, col%, text$                     Set the text of a cell.
  SetColumns spec$                              Define columns. Pipe-delimited "Name,Width|Name,Width" (width in characters).
  SetItemSelected index%, selected              Select or deselect a row.
  SetMultiSelect multi                          Enable or disable multi-select.
  SetReorderable reorderable                    Enable or disable row reordering.
  SetSort col%, dir%                            Sort by column. dir: 0=none, 1=ascending, 2=descending. An invalid column or direction clears the sort. Has no effect while reordering is enabled.

Default Event: Click

Example

ListView1.SetColumns "Name,20|Size,10|Type,15"
ListView1.AddItem "readme.txt"
ListView1.SetCell 0, 1, "1024"
ListView1.SetCell 0, 2, "Text"
ListView1.SetSort 0, 1

Common Properties, Events, and Methods

ProgressBar

VB Equivalent: ProgressBar -- DVX Widget: progressbar

A horizontal progress indicator bar.

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  Value      Integer   Current progress value (0-100).

No type-specific events or methods. No default event.

Common Properties, Events, and Methods

OptionButton

VB Equivalent: OptionButton -- DVX Widget: radio (radio group + radio button) | Name Prefix: Option

A radio button for mutually exclusive choices. OptionButtons placed in the same container form a group: selecting one clears the others. The Value property is True for the selected button.

Type-Specific Properties

  Property     Type      Description
  --------     -------   -------------------------------------------
  Caption      String    The text displayed next to the radio button.
  Value        Boolean   True when this button is selected. Setting it to True selects this button and clears the others in its container; setting it to False deselects it. Setting Value does not raise Click.
  OptionIndex  Integer   The index of this button among the OptionButtons of its container (read-only).

Type-Specific Methods

  Method        Parameters          Description
  -----------   -----------------   -------------------------------------------
  SetSelected   Index As Integer    Select the OptionButton at the given index within this button's container.

Default Event: Click

Common Properties, Events, and Methods

ScrollPane

DVX Extension -- DVX Widget: scrollpane | Name Prefix: Scroll

A scrollable container. Place child controls inside and the ScrollPane automatically provides scrollbars when the content exceeds the visible area. Clicking on content that does not respond to the mouse (a Label, an Image or empty space) gives the ScrollPane the focus, so the arrow and page keys scroll it.

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  NoBorder   Boolean   When True, suppresses the border around the scroll pane.

Container: Yes

No default event.

Common Properties, Events, and Methods

Line

VB Equivalent: Line -- DVX Widget: separator

A visual separator line. The underlying widget supports both horizontal and vertical orientations. A Line placed in a horizontal container (HBox, Toolbar) is vertical; anywhere else it is horizontal.

No type-specific properties, events, or methods.

Common Properties, Events, and Methods

HScrollBar

VB Equivalent: HScrollBar -- DVX Widget: slider | Name Prefix: HScroll

A horizontal slider/scrollbar control. The value ranges between Min and Max (default 0 to 100). Arrow keys move the value by 1, Page Up/Page Down by a tenth of the range, Home/End to the limits. The Change event fires only when the value actually changes.

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  Value      Integer   The current slider position (clamped to the Min..Max range).
  Min        Integer   Lowest value (default 0). Setting Min above Max raises Max to match.
  Max        Integer   Highest value (default 100). Setting Max below Min lowers Min to match.

Default Event: Change

Example

Begin HScrollBar HScroll1
    MinWidth = 200
End

Sub HScroll1_Change ()
    Label1.Caption = "Value: " & Str$(HScroll1.Value)
End Sub

Common Properties, Events, and Methods

Spacer

DVX Extension -- DVX Widget: spacer

An invisible layout spacer. Takes up space in the layout without rendering anything. Useful for pushing controls apart. Give it a Weight to absorb extra space.

No type-specific properties, events, or methods.

Common Properties, Events, and Methods

SpinButton

DVX Extension -- DVX Widget: spinner | Name Prefix: Spin

A numeric input with up/down buttons. Supports integer mode (default) and real-number mode with configurable decimal places. Up/Down arrows step by the step size, Page Up/Page Down by ten steps. Typed or pasted text is committed on Enter or when the control loses focus; Esc cancels the edit. Ctrl+Z undoes the last edit of the typed text; once the text is committed or reformatted there is nothing to undo. Reading Value while the user is typing returns the typed number without interrupting the edit. Change also fires as each character is typed; stepping at a limit, or committing text that parses to the unchanged value, does not fire it.

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  Value      Integer   Current value (in real mode, the value truncated to an integer).
  RealMode   Boolean   True to use floating-point mode; False for integer mode.
  Decimals   Integer   Number of decimal places shown in real mode.

Type-Specific Methods

  Method     Parameters                       Description
  --------   ------------------------------   -------------------------------------------
  SetRange   Min As Integer, Max As Integer   Set the allowed value range (used in both integer and real mode; default 0 to 100).
  SetStep    Step As Integer                  Set the increment per button click.

Default Event: Change

Common Properties, Events, and Methods

Splitter

DVX Extension -- DVX Widget: splitter

A resizable split pane. Holds exactly two child widgets separated by a draggable divider. Default orientation is vertical (vertical divider, panes side-by-side).

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  Position   Integer   Position of the divider in pixels from the top (or left).

Container: Yes

No default event.

Common Properties, Events, and Methods

StatusBar

VB Equivalent: StatusBar -- DVX Widget: statusbar

A horizontal container styled as a status bar, typically placed at the bottom of a form. At the C API level it holds child widgets (such as labels), each drawn with a sunken-panel border for the classic segmented status-bar look. It is not registered as a container in the form runtime, so child controls cannot be nested inside it in .frm files.

No type-specific properties, events, or methods.

Common Properties, Events, and Methods

TabStrip

VB Equivalent: TabStrip -- DVX Widget: tabcontrol

A tabbed container. Each tab page is a separate container that holds child controls. Switching tabs shows one page and hides others.

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  TabIndex   Integer   Index of the active tab (0-based). Note: this property name collides with the common VB-compatibility TabIndex property, which shadows it at runtime. Use the SetActive method instead to switch tabs.

Type-Specific Methods

  Method                   Description
  ------                   -----------
  AddPage title$           Add a new tab page with the given title.
  GetActive()              Returns the index of the active tab.
  SetActive index%         Switch to the tab at the given index. This is the recommended way to change tabs at runtime (the TabIndex property is shadowed by the common property handler). A negative index selects the first tab and an index past the last tab selects the last tab. Switching closes a drop-down list opened from the page being hidden and moves the focus to the tab strip if it was on a control of the page being hidden. The Click event is not raised for a switch made in code.

Container: Yes

Default Event: Click

Warning: The TabIndex property is shadowed by the common property handler at runtime. Use the SetActive method to change tabs programmatically.

Common Properties, Events, and Methods

TextBox

VB Equivalent: TextBox -- DVX Widget: textbox (single-line text input, max 256 chars)

A single-line text input field. Supports data binding via DataSource and DataField properties.

Type-Specific Properties

  Property     Type     Description
  ----------   ------   -------------------------------------------
  Text         String   The text content of the input field. Setting it clears the undo history.
  DataSource   String   Name of a Data control for data binding.
  DataField    String   Column name for data binding.

Default Event: Change

Example

Begin TextBox Text1
    Text = "Enter text here"
End

Sub Text1_Change ()
    Label1.Caption = "You typed: " & Text1.Text
End Sub

Common Properties, Events, and Methods

Data Binding

TextArea

VB Equivalent: TextArea (DVX extension) -- DVX Widget: textarea (multi-line text input, default max 65536 chars)

A multi-line text editing area. This is a DVX extension with no direct VB3 equivalent (VB uses a TextBox with MultiLine=True). Supports line numbers, auto-indent, find/replace, and tab configuration.

Type-Specific Properties

  Property     Type      R/W   Description
  ----------   -------   ---   -------------------------------------------
  Text         String    R/W   The full text content. Setting it clears the undo history.
  CursorLine   Integer   R     Current cursor line number (1-based).

Type-Specific Methods

  Method                                          Description
  ------                                          -----------
  AppendText text$                                Append text to the end of the buffer and invalidate the widget.
  FindNext needle$, caseSensitive, forward        Search from the cursor and select the match. A forward search finds a match starting at the cursor; repeating it moves on to the next match. Returns True if found.
  GetWordAtCursor()                               Returns the word under the cursor.
  GoToLine line%                                  Scroll to the given line and select it.
  ReplaceAll needle$, replacement$, caseSensitive Replace all occurrences. Returns count of replacements.
  SetAutoIndent enabled                           Enable or disable automatic indentation.
  SetCaptureTabs enabled                          When True, Tab key inserts a tab/spaces (firing Change) instead of moving focus.
  SetCursor line%, col%                           Move the cursor to a line and column (both start at 1) without selecting anything. Values past the end clamp to the text.
  SetShowLineNumbers show                         Show or hide the line number gutter.
  SetSyntaxMode mode$                             Activate built-in syntax highlighting. Modes: "dhs" (help source), "bas" (BASIC). Pass "" to disable.
  SetTabWidth width%                              Set the tab stop width in characters.
  SetUseTabChar useChar                           When True, Tab inserts a tab character; when False, inserts spaces.

Default Event: Change

Example

TextArea1.SetShowLineNumbers True
TextArea1.SetAutoIndent True
TextArea1.SetTabWidth 4
TextArea1.SetCaptureTabs True

' Search for text
If TextArea1.FindNext("TODO", False, True) Then
    Print "Found at line"; TextArea1.CursorLine
End If

' Replace all occurrences
Dim count As Integer
count = TextArea1.ReplaceAll("old", "new", False)
Print "Replaced"; count; "occurrences"

Common Properties, Events, and Methods

Timer

VB Equivalent: Timer -- DVX Widget: timer (non-visual)

A non-visual control that fires its event at a regular interval. The Timer widget is invisible at runtime -- it has no on-screen representation.

Type-Specific Properties

  Property   Type      Description
  --------   -------   -------------------------------------------
  Enabled    Boolean   True to start the timer, False to stop it.
  Interval   Integer   Timer interval in milliseconds. Setting it restarts the countdown. An Interval of 0 (or less) disables the Timer event.

Type-Specific Methods

  Method   Parameters   Description
  ------   ----------   -------------------------------------------
  Start    (none)       Start the timer.
  Stop     (none)       Stop the timer.

Type-Specific Events

  Event   Parameters   Description
  -----   ----------   -------------------------------------------
  Timer   (none)       Fires each time the interval elapses. This is the default event. A one-shot timer is already stopped when its event runs, so the handler can call Start to run it again.
Note: The Timer control fires the Timer event instead of Change. The onChange callback on the underlying widget is remapped automatically.

Example

Begin Timer Timer1
    Interval = 1000
    Enabled  = True
End

Dim Shared counter As Integer

Sub Timer1_Timer ()
    counter = counter + 1
    Label1.Caption = "Ticks: " & Str$(counter)
End Sub

Common Properties, Events, and Methods

Toolbar

VB Equivalent: Toolbar -- DVX Widget: toolbar

A horizontal container styled as a toolbar, with compact padding and spacing. Place buttons, labels, or other controls inside.

Container: Yes

No type-specific properties, events, or methods.

Common Properties, Events, and Methods

TreeView

VB Equivalent: TreeView -- DVX Widget: treeview

A hierarchical tree of expandable/collapsible nodes. Supports multi-select and drag-to-reorder. Items are accessed by depth-first index (0-based).

Type-Specific Methods

  Method                                  Description
  ------                                  -----------
  AddChildItem parentIndex%, text$        Add a child node under the node at the given index.
  AddItem text$                           Add a root-level node.
  Clear                                   Remove all nodes.
  GetItemText$(index%)                    Returns the text of the node at the given index.
  IsExpanded(index%)                      Returns True if the node at the given index is expanded.
  IsItemSelected(index%)                  Returns True if the node at the given index is selected.
  ItemCount()                             Returns the total number of nodes (all levels).
  SetExpanded index%, expanded            Expand or collapse the node at the given index. Collapsing a node that hides the current item moves the current item to that node.
  SetItemSelected index%, selected        Select or deselect the node at the given index. Without multi-select this sets (or clears) the single selected node.
  SetMultiSelect multi                    Enable or disable multi-select mode. Turning it off clears the multi-selection.
  SetReorderable reorderable              Enable or disable node reordering.

Default Event: Click

Example

TreeView1.AddItem "Animals"
TreeView1.AddChildItem 0, "Cat"
TreeView1.AddChildItem 0, "Dog"
TreeView1.AddItem "Plants"
TreeView1.AddChildItem 3, "Oak"
TreeView1.SetExpanded 0, True
Print "Items:"; TreeView1.ItemCount()

Common Properties, Events, and Methods

WrapBox

DVX Extension -- DVX Widget: wrapbox | Name Prefix: WrapBox

A container that arranges children in a flowing layout, wrapping to the next row when the available width is exceeded. Similar to CSS flexbox with flex-wrap: wrap.

Type-Specific Properties

  Property    Type   Description
  ---------   ----   -------------------------------------------
  Alignment   Enum   Horizontal alignment of items: Left, Center, or Right.

Container: Yes

Default Event: Click

Common Properties, Events, and Methods