DVX_GUI/docs/dvx_basic_reference.html
2026-09-29 17:03:51 -05:00

3933 lines
249 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>DVX BASIC IDE Guide</title>
<style>
body { font-family: sans-serif; margin: 0; padding: 0; display: flex; }
nav { width: 250px; min-width: 250px; background: #f0f0f0; padding: 16px;
border-right: 1px solid #ccc; height: 100vh; overflow-y: auto;
position: sticky; top: 0; box-sizing: border-box; }
nav ul { list-style: none; padding-left: 16px; margin: 4px 0; }
nav > ul { padding-left: 0; }
nav a { text-decoration: none; color: #0066cc; }
nav a:hover { text-decoration: underline; }
main { flex: 1; padding: 24px 32px; max-width: 800px; }
h1 { border-bottom: 2px solid #333; padding-bottom: 4px; }
h2 { border-bottom: 1px solid #999; padding-bottom: 2px; margin-top: 32px; }
h3 { margin-top: 24px; }
pre { background: #f8f8f8; border: 1px solid #ddd; padding: 8px;
overflow-x: auto; font-size: 14px; }
blockquote { background: #fffde7; border-left: 4px solid #ffc107;
padding: 8px 12px; margin: 12px 0; }
hr { border: none; border-top: 1px solid #ccc; margin: 24px 0; }
img { max-width: 100%; }
.topic { margin-bottom: 48px; }
</style>
</head>
<body>
<nav>
<h3>Contents</h3>
<ul>
<li><a href="#ide.overview">Overview</a>
<ul>
<li><a href="#ide.menu.file">Menu Reference</a>
<ul>
<li><a href="#ide.menu.file">File Menu</a></li>
<li><a href="#ide.menu.edit">Edit Menu</a></li>
<li><a href="#ide.menu.run">Run Menu</a></li>
<li><a href="#ide.menu.view">View Menu</a></li>
<li><a href="#ide.menu.window">Window Menu</a></li>
<li><a href="#ide.menu.tools">Tools Menu</a></li>
<li><a href="#ide.menu.help">Help Menu</a></li>
</ul>
</li>
<li><a href="#ide.toolbar">Toolbar</a></li>
<li><a href="#ide.editor">Code Editor</a></li>
<li><a href="#ide.designer">Form Designer</a></li>
<li><a href="#ide.project">Project System</a></li>
<li><a href="#ide.properties">Properties Panel</a></li>
<li><a href="#ide.toolbox">Toolbox</a></li>
<li><a href="#ide.debugger">Debugger</a></li>
<li><a href="#ide.debug.locals">Debug Windows</a>
<ul>
<li><a href="#ide.debug.locals">Locals Window</a></li>
<li><a href="#ide.debug.callstack">Call Stack Window</a></li>
<li><a href="#ide.debug.watch">Watch Window</a></li>
<li><a href="#ide.debug.breakpoints">Breakpoints Window</a></li>
</ul>
</li>
<li><a href="#ide.immediate">Immediate Window</a></li>
<li><a href="#ide.output">Output Window</a></li>
<li><a href="#ide.findreplace">Find / Replace</a></li>
<li><a href="#ide.preferences">Preferences</a></li>
<li><a href="#ide.shortcuts">Keyboard Shortcuts</a></li>
</ul>
</li>
<li><a href="#ide.changes">Changes in This Release</a></li>
<li><a href="#lang.datatypes">Data Types</a>
<ul>
<li><a href="#lang.operators">Operators</a></li>
<li><a href="#lang.statements">Statements</a>
<ul>
<li><a href="#lang.declarations">Declarations</a></li>
<li><a href="#lang.conditionals">Conditionals</a></li>
<li><a href="#lang.loops">Loops</a></li>
<li><a href="#lang.procedures">Procedures</a></li>
<li><a href="#lang.flow">Flow Control</a></li>
<li><a href="#lang.io">Input/Output</a></li>
<li><a href="#lang.misc">Miscellaneous Statements</a></li>
<li><a href="#lang.sound">Sound, Joysticks and Frames</a></li>
</ul>
</li>
<li><a href="#lang.fileio">File I/O</a></li>
<li><a href="#lang.filesystem">File System Statements</a></li>
<li><a href="#lang.func.string">Built-in Functions</a>
<ul>
<li><a href="#lang.func.string">String Functions</a></li>
<li><a href="#lang.func.math">Math Functions</a></li>
<li><a href="#lang.func.conversion">Conversion Functions</a></li>
<li><a href="#lang.func.fileio">File I/O Functions</a></li>
<li><a href="#lang.func.misc">Miscellaneous Functions</a></li>
</ul>
</li>
<li><a href="#lang.forms">Form and Control Statements</a></li>
<li><a href="#lang.sql">SQL Functions</a></li>
<li><a href="#lang.app">App Object</a></li>
<li><a href="#lang.ini">INI Functions</a></li>
<li><a href="#lang.constants">Predefined Constants</a></li>
<li><a href="#lang.runtime">Include Libraries</a></li>
</ul>
</li>
<li><a href="#ctrl.common.props">Common Properties, Events, and Methods</a>
<ul>
<li><a href="#ctrl.databinding">Data Binding</a></li>
<li><a href="#ctrl.menus">Menu System</a></li>
<li><a href="#ctrl.arrays">Control Arrays</a></li>
<li><a href="#ctrl.frm">FRM File Format</a></li>
<li><a href="#ctrl.form">Form</a></li>
<li><a href="#ctrl.terminal">Special Controls</a></li>
<li><a href="#ctrl.terminal">Terminal</a></li>
<li><a href="#ctrl.frame">Frame</a></li>
<li><a href="#ctrl.hbox">HBox</a></li>
<li><a href="#ctrl.vbox">VBox</a></li>
<li><a href="#ctrl.button">CommandButton</a></li>
<li><a href="#ctrl.picturebox">PictureBox</a></li>
<li><a href="#ctrl.checkbox">CheckBox</a></li>
<li><a href="#ctrl.combobox">ComboBox</a></li>
<li><a href="#ctrl.data">Data Controls</a></li>
<li><a href="#ctrl.data">Data</a></li>
<li><a href="#ctrl.dbgrid">DBGrid</a></li>
<li><a href="#ctrl.dropdown">DropDown</a></li>
<li><a href="#ctrl.imagebutton">ImageButton</a></li>
<li><a href="#ctrl.image">Image</a></li>
<li><a href="#ctrl.label">Label</a></li>
<li><a href="#ctrl.listbox">ListBox</a></li>
<li><a href="#ctrl.listview">Data Display Controls</a></li>
<li><a href="#ctrl.listview">ListView</a></li>
<li><a href="#ctrl.progressbar">ProgressBar</a></li>
<li><a href="#ctrl.optionbutton">OptionButton</a></li>
<li><a href="#ctrl.scrollpane">ScrollPane</a></li>
<li><a href="#ctrl.line">Decorative Controls</a></li>
<li><a href="#ctrl.line">Line</a></li>
<li><a href="#ctrl.hscrollbar">HScrollBar</a></li>
<li><a href="#ctrl.spacer">Spacer</a></li>
<li><a href="#ctrl.spinbutton">SpinButton</a></li>
<li><a href="#ctrl.splitter">Splitter</a></li>
<li><a href="#ctrl.statusbar">StatusBar</a></li>
<li><a href="#ctrl.tabstrip">Tabbed and Split Controls</a></li>
<li><a href="#ctrl.tabstrip">TabStrip</a></li>
<li><a href="#ctrl.textbox">TextBox</a></li>
<li><a href="#ctrl.textarea">TextArea</a></li>
<li><a href="#ctrl.timer">Timer</a></li>
<li><a href="#ctrl.toolbar">Bar Controls</a></li>
<li><a href="#ctrl.toolbar">Toolbar</a></li>
<li><a href="#ctrl.treeview">TreeView</a></li>
<li><a href="#ctrl.wrapbox">WrapBox</a></li>
</ul>
</li>
</ul>
<h3>Index</h3>
<ul>
<li><a href="#ide.project">.dbp Files</a></li>
<li><a href="#ctrl.frm">.frm</a></li>
<li><a href="#ide.menu.help">About</a></li>
<li><a href="#lang.func.math">ABS</a></li>
<li><a href="#ide.shortcuts">Accelerators</a></li>
<li><a href="#ide.menu.file">Add File</a></li>
<li><a href="#ctrl.treeview">AddChildItem</a></li>
<li><a href="#ctrl.listbox">AddItem</a></li>
<li><a href="#ctrl.treeview">AddItem</a></li>
<li><a href="#ctrl.data">AddNew</a></li>
<li><a href="#ctrl.label">Alignment</a></li>
<li><a href="#lang.operators">AND</a></li>
<li><a href="#ctrl.terminal">ANSI Terminal</a></li>
<li><a href="#lang.app">App</a></li>
<li><a href="#lang.app">App.Config</a></li>
<li><a href="#lang.app">App.Data</a></li>
<li><a href="#lang.app">App.Path</a></li>
<li><a href="#lang.func.string">ASC</a></li>
<li><a href="#lang.func.math">ATN</a></li>
<li><a href="#ide.editor">Auto-indent</a></li>
<li><a href="#ctrl.textarea">AutoIndent</a></li>
<li><a href="#ctrl.form">AutoSize</a></li>
<li><a href="#lang.sound">BEEP</a></li>
<li><a href="#ctrl.image">BMP</a></li>
<li><a href="#lang.datatypes">Boolean</a></li>
<li><a href="#ide.debugger">Breakpoints</a></li>
<li><a href="#ide.debug.breakpoints">Breakpoints Window</a></li>
<li><a href="#ctrl.button">Button</a></li>
<li><a href="#lang.procedures">BYVAL</a></li>
<li><a href="#lang.flow">CALL</a></li>
<li><a href="#ide.debug.callstack">Call Stack</a></li>
<li><a href="#ctrl.picturebox">Canvas</a></li>
<li><a href="#ctrl.form">Caption</a></li>
<li><a href="#ctrl.label">Caption</a></li>
<li><a href="#lang.conditionals">CASE</a></li>
<li><a href="#lang.conditionals">CASE ELSE</a></li>
<li><a href="#lang.func.conversion">CBOOL</a></li>
<li><a href="#lang.func.conversion">CDBL</a></li>
<li><a href="#ide.changes">Changes</a></li>
<li><a href="#lang.filesystem">CHDIR</a></li>
<li><a href="#lang.filesystem">CHDRIVE</a></li>
<li><a href="#ctrl.checkbox">CheckBox</a></li>
<li><a href="#lang.func.string">CHR$</a></li>
<li><a href="#lang.func.conversion">CINT</a></li>
<li><a href="#ide.menu.run">Clear Output</a></li>
<li><a href="#ctrl.button">Click</a></li>
<li><a href="#lang.func.conversion">CLNG</a></li>
<li><a href="#lang.fileio">CLOSE</a></li>
<li><a href="#ide.menu.file">Close Project</a></li>
<li><a href="#ide.editor">Code Editor</a></li>
<li><a href="#ide.menu.view">Code View</a></li>
<li><a href="#ctrl.combobox">ComboBox</a></li>
<li><a href="#lang.runtime">comm.bas</a></li>
<li><a href="#lang.func.misc">Command Line</a></li>
<li><a href="#lang.func.misc">COMMAND$</a></li>
<li><a href="#ctrl.button">CommandButton</a></li>
<li><a href="#lang.runtime">commdlg.bas</a></li>
<li><a href="#lang.statements">Comments</a></li>
<li><a href="#lang.runtime">CommHandshake</a></li>
<li><a href="#ctrl.common.props">Common Events</a></li>
<li><a href="#ctrl.common.props">Common Methods</a></li>
<li><a href="#ctrl.common.props">Common Properties</a></li>
<li><a href="#lang.runtime">CommRecvEncrypted</a></li>
<li><a href="#lang.runtime">CommSetPlain</a></li>
<li><a href="#ide.output">Compile Errors</a></li>
<li><a href="#lang.declarations">CONST</a></li>
<li><a href="#ctrl.frame">Container</a></li>
<li><a href="#lang.forms">Control Arrays</a></li>
<li><a href="#ctrl.arrays">Control Arrays</a></li>
<li><a href="#ide.designer">Control Placement</a></li>
<li><a href="#ide.properties">Control Properties</a></li>
<li><a href="#ide.properties">Control Tree</a></li>
<li><a href="#ide.toolbox">Controls</a></li>
<li><a href="#ide.menu.edit">Copy</a></li>
<li><a href="#lang.func.math">COS</a></li>
<li><a href="#lang.forms">CreateControl</a></li>
<li><a href="#lang.forms">CreateForm</a></li>
<li><a href="#lang.func.conversion">CSNG</a></li>
<li><a href="#lang.func.conversion">CSTR</a></li>
<li><a href="#ctrl.textarea">CursorLine</a></li>
<li><a href="#ide.menu.edit">Cut</a></li>
<li><a href="#lang.io">DATA</a></li>
<li><a href="#ctrl.data">Data</a></li>
<li><a href="#ctrl.databinding">Data Binding</a></li>
<li><a href="#lang.datatypes">Data Types</a></li>
<li><a href="#ctrl.dbgrid">Data-Bound Grid</a></li>
<li><a href="#ctrl.data">Database</a></li>
<li><a href="#ctrl.data">DatabaseName</a></li>
<li><a href="#ctrl.databinding">DataField</a></li>
<li><a href="#ctrl.textbox">DataField</a></li>
<li><a href="#ctrl.databinding">DataSource</a></li>
<li><a href="#ctrl.textbox">DataSource</a></li>
<li><a href="#lang.func.misc">DATE$</a></li>
<li><a href="#ctrl.dbgrid">DBGrid</a></li>
<li><a href="#ide.menu.run">Debug</a></li>
<li><a href="#ide.menu.tools">Debug Layout</a></li>
<li><a href="#ide.debugger">Debug Mode</a></li>
<li><a href="#ide.debugger">Debugger</a></li>
<li><a href="#ctrl.spinbutton">Decimals</a></li>
<li><a href="#lang.declarations">DECLARE</a></li>
<li><a href="#lang.declarations">DECLARE LIBRARY</a></li>
<li><a href="#lang.runtime">DECLARE LIBRARY</a></li>
<li><a href="#lang.procedures">DEF FN</a></li>
<li><a href="#lang.declarations">DEFDBL</a></li>
<li><a href="#lang.declarations">DEFINT</a></li>
<li><a href="#lang.declarations">DEFLNG</a></li>
<li><a href="#lang.declarations">DEFSNG</a></li>
<li><a href="#lang.declarations">DEFSTR</a></li>
<li><a href="#ide.menu.edit">Delete</a></li>
<li><a href="#ide.designer">Design Surface</a></li>
<li><a href="#ide.menu.view">Design View</a></li>
<li><a href="#ide.overview">Development Environment</a></li>
<li><a href="#lang.declarations">DIM</a></li>
<li><a href="#lang.loops">DO</a></li>
<li><a href="#lang.forms">DoEvents</a></li>
<li><a href="#lang.forms">DOEVENTS</a></li>
<li><a href="#lang.datatypes">Double</a></li>
<li><a href="#ctrl.picturebox">Drawing</a></li>
<li><a href="#ctrl.dropdown">DropDown</a></li>
<li><a href="#ide.overview">DVX BASIC</a></li>
<li><a href="#ide.menu.edit">Edit Menu</a></li>
<li><a href="#lang.conditionals">ELSE</a></li>
<li><a href="#lang.conditionals">ELSEIF</a></li>
<li><a href="#lang.misc">END</a></li>
<li><a href="#lang.procedures">END FUNCTION</a></li>
<li><a href="#lang.conditionals">END IF</a></li>
<li><a href="#lang.conditionals">END SELECT</a></li>
<li><a href="#lang.procedures">END SUB</a></li>
<li><a href="#lang.declarations">END TYPE</a></li>
<li><a href="#lang.func.misc">ENVIRON$</a></li>
<li><a href="#lang.func.fileio">EOF</a></li>
<li><a href="#lang.operators">EQV</a></li>
<li><a href="#lang.declarations">ERASE</a></li>
<li><a href="#lang.misc">ERL</a></li>
<li><a href="#lang.misc">ERR</a></li>
<li><a href="#lang.misc">ERROR</a></li>
<li><a href="#lang.forms">Event Handlers</a></li>
<li><a href="#ctrl.common.props">Events</a></li>
<li><a href="#ide.menu.file">Exit</a></li>
<li><a href="#lang.flow">EXIT</a></li>
<li><a href="#lang.loops">EXIT DO</a></li>
<li><a href="#lang.loops">EXIT FOR</a></li>
<li><a href="#lang.procedures">EXIT FUNCTION</a></li>
<li><a href="#lang.procedures">EXIT SUB</a></li>
<li><a href="#lang.func.math">EXP</a></li>
<li><a href="#ide.immediate">Expression Evaluation</a></li>
<li><a href="#lang.constants">False</a></li>
<li><a href="#lang.filesystem">File Attributes</a></li>
<li><a href="#ide.menu.file">File Menu</a></li>
<li><a href="#lang.filesystem">FILECOPY</a></li>
<li><a href="#ide.menu.edit">Find</a></li>
<li><a href="#ide.findreplace">Find</a></li>
<li><a href="#ide.menu.edit">Find Next</a></li>
<li><a href="#ide.findreplace">Find Next</a></li>
<li><a href="#ctrl.textarea">FindNext</a></li>
<li><a href="#lang.func.math">FIX</a></li>
<li><a href="#ctrl.wrapbox">Flow Layout</a></li>
<li><a href="#lang.loops">FOR</a></li>
<li><a href="#lang.fileio">FOR APPEND</a></li>
<li><a href="#lang.fileio">FOR BINARY</a></li>
<li><a href="#lang.fileio">FOR INPUT</a></li>
<li><a href="#lang.fileio">FOR OUTPUT</a></li>
<li><a href="#lang.fileio">FOR RANDOM</a></li>
<li><a href="#ctrl.form">Form</a></li>
<li><a href="#ide.designer">Form Designer</a></li>
<li><a href="#ctrl.frm">Form File</a></li>
<li><a href="#lang.func.string">FORMAT$</a></li>
<li><a href="#ctrl.frame">Frame</a></li>
<li><a href="#lang.sound">Frame rate</a></li>
<li><a href="#lang.sound">FRAMEWAIT</a></li>
<li><a href="#lang.func.fileio">FREEFILE</a></li>
<li><a href="#ctrl.frm">FRM</a></li>
<li><a href="#lang.procedures">FUNCTION</a></li>
<li><a href="#ide.editor">Function Dropdown</a></li>
<li><a href="#lang.runtime">game.bas</a></li>
<li><a href="#lang.runtime">GameKeyDown</a></li>
<li><a href="#lang.fileio">GET</a></li>
<li><a href="#lang.filesystem">GETATTR</a></li>
<li><a href="#lang.flow">GOSUB</a></li>
<li><a href="#lang.flow">GOTO</a></li>
<li><a href="#ctrl.textarea">GoToLine</a></li>
<li><a href="#ide.designer">Grab Handles</a></li>
<li><a href="#ide.designer">Grid Snapping</a></li>
<li><a href="#ctrl.hbox">HBox</a></li>
<li><a href="#ide.menu.help">Help Menu</a></li>
<li><a href="#lang.runtime">help.bas</a></li>
<li><a href="#lang.func.string">HEX$</a></li>
<li><a href="#lang.forms">Hide</a></li>
<li><a href="#ctrl.form">Hide</a></li>
<li><a href="#ctrl.hbox">Horizontal Layout</a></li>
<li><a href="#lang.runtime">HostLookup$</a></li>
<li><a href="#ide.shortcuts">Hotkeys</a></li>
<li><a href="#ctrl.hscrollbar">HScrollBar</a></li>
<li><a href="#ide.overview">IDE</a></li>
<li><a href="#lang.conditionals">IF</a></li>
<li><a href="#ctrl.image">Image</a></li>
<li><a href="#ctrl.imagebutton">ImageButton</a></li>
<li><a href="#ide.immediate">Immediate Window</a></li>
<li><a href="#lang.operators">IMP</a></li>
<li><a href="#lang.runtime">Include Libraries</a></li>
<li><a href="#ctrl.arrays">Index Property</a></li>
<li><a href="#lang.ini">INI</a></li>
<li><a href="#lang.ini">IniRead</a></li>
<li><a href="#lang.ini">IniWrite</a></li>
<li><a href="#lang.io">INPUT</a></li>
<li><a href="#lang.fileio">INPUT #</a></li>
<li><a href="#lang.func.fileio">INPUT$</a></li>
<li><a href="#lang.forms">InputBox$</a></li>
<li><a href="#lang.forms">INPUTBOX$</a></li>
<li><a href="#lang.func.string">INSTR</a></li>
<li><a href="#lang.func.math">INT</a></li>
<li><a href="#lang.datatypes">Integer</a></li>
<li><a href="#ctrl.timer">Interval</a></li>
<li><a href="#lang.runtime">JoyAxis</a></li>
<li><a href="#lang.runtime">JoyButton</a></li>
<li><a href="#lang.runtime">JoyCount</a></li>
<li><a href="#lang.runtime">JoyHat</a></li>
<li><a href="#lang.runtime">Joystick</a></li>
<li><a href="#lang.runtime">joystick.bas</a></li>
<li><a href="#lang.runtime">JoyX</a></li>
<li><a href="#lang.runtime">JoyY</a></li>
<li><a href="#ide.shortcuts">Keyboard Shortcuts</a></li>
<li><a href="#lang.filesystem">KILL</a></li>
<li><a href="#ctrl.label">Label</a></li>
<li><a href="#lang.func.fileio">LBOUND</a></li>
<li><a href="#lang.func.string">LCASE$</a></li>
<li><a href="#lang.func.string">LEFT$</a></li>
<li><a href="#lang.func.string">LEN</a></li>
<li><a href="#lang.declarations">LET</a></li>
<li><a href="#ctrl.line">Line</a></li>
<li><a href="#lang.fileio">LINE INPUT</a></li>
<li><a href="#ide.editor">Line Numbers</a></li>
<li><a href="#ctrl.textarea">LineNumbers</a></li>
<li><a href="#ctrl.listbox">ListBox</a></li>
<li><a href="#ctrl.listbox">ListCount</a></li>
<li><a href="#ctrl.listbox">ListIndex</a></li>
<li><a href="#ctrl.listview">ListView</a></li>
<li><a href="#lang.forms">LOAD</a></li>
<li><a href="#ctrl.form">Load</a></li>
<li><a href="#lang.func.fileio">LOC</a></li>
<li><a href="#ide.debug.locals">Locals Window</a></li>
<li><a href="#lang.func.fileio">LOF</a></li>
<li><a href="#lang.func.math">LOG</a></li>
<li><a href="#lang.datatypes">Long</a></li>
<li><a href="#lang.loops">LOOP</a></li>
<li><a href="#lang.io">LPRINT</a></li>
<li><a href="#lang.io">LPRINT USING</a></li>
<li><a href="#lang.func.string">LTRIM$</a></li>
<li><a href="#ctrl.databinding">Master-Detail</a></li>
<li><a href="#ctrl.hscrollbar">Max</a></li>
<li><a href="#lang.sound">MB</a></li>
<li><a href="#lang.forms">Me</a></li>
<li><a href="#ctrl.menus">Menu</a></li>
<li><a href="#ctrl.menus">Menu Bar</a></li>
<li><a href="#ide.menu.view">Menu Editor</a></li>
<li><a href="#ctrl.common.props">Methods</a></li>
<li><a href="#lang.sound">MF</a></li>
<li><a href="#lang.func.string">MID$</a></li>
<li><a href="#lang.runtime">MIDI</a></li>
<li><a href="#ide.changes">Migration</a></li>
<li><a href="#ctrl.hscrollbar">Min</a></li>
<li><a href="#lang.filesystem">MKDIR</a></li>
<li><a href="#lang.operators">MOD</a></li>
<li><a href="#ctrl.data">MoveFirst</a></li>
<li><a href="#ctrl.data">MoveNext</a></li>
<li><a href="#lang.forms">MsgBox</a></li>
<li><a href="#lang.forms">MSGBOX</a></li>
<li><a href="#ctrl.listview">Multi-Column List</a></li>
<li><a href="#lang.runtime">Music</a></li>
<li><a href="#lang.sound">Music macro language</a></li>
<li><a href="#lang.runtime">music.bas</a></li>
<li><a href="#lang.runtime">MusicControl</a></li>
<li><a href="#lang.runtime">MusicError$</a></li>
<li><a href="#lang.runtime">MusicFree</a></li>
<li><a href="#lang.runtime">MusicLength</a></li>
<li><a href="#lang.runtime">MusicLoad</a></li>
<li><a href="#lang.runtime">MusicMidiOpen</a></li>
<li><a href="#lang.runtime">MusicNoteOff</a></li>
<li><a href="#lang.runtime">MusicNoteOn</a></li>
<li><a href="#lang.runtime">MusicPause</a></li>
<li><a href="#lang.runtime">MusicPitchBend</a></li>
<li><a href="#lang.runtime">MusicPlay</a></li>
<li><a href="#lang.runtime">MusicPlaying</a></li>
<li><a href="#lang.runtime">MusicPosition</a></li>
<li><a href="#lang.runtime">MusicProgram</a></li>
<li><a href="#lang.runtime">MusicResume</a></li>
<li><a href="#lang.runtime">MusicSeek</a></li>
<li><a href="#lang.runtime">MusicStop</a></li>
<li><a href="#lang.runtime">MusicVolume</a></li>
<li><a href="#lang.filesystem">NAME</a></li>
<li><a href="#lang.runtime">net.bas</a></li>
<li><a href="#ide.menu.file">New Project</a></li>
<li><a href="#lang.loops">NEXT</a></li>
<li><a href="#lang.operators">NOT</a></li>
<li><a href="#lang.forms">Nothing</a></li>
<li><a href="#ide.editor">Object Dropdown</a></li>
<li><a href="#lang.func.string">OCT$</a></li>
<li><a href="#lang.misc">ON ERROR</a></li>
<li><a href="#lang.flow">ON GOSUB</a></li>
<li><a href="#lang.flow">ON GOTO</a></li>
<li><a href="#lang.fileio">OPEN</a></li>
<li><a href="#ide.menu.file">Open Project</a></li>
<li><a href="#lang.operators">Operators</a></li>
<li><a href="#lang.declarations">OPTION</a></li>
<li><a href="#lang.declarations">OPTION BASE</a></li>
<li><a href="#lang.declarations">OPTION COMPARE</a></li>
<li><a href="#ide.preferences">Option Explicit</a></li>
<li><a href="#lang.declarations">OPTION EXPLICIT</a></li>
<li><a href="#ctrl.optionbutton">OptionButton</a></li>
<li><a href="#ctrl.optionbutton">OptionIndex</a></li>
<li><a href="#lang.operators">OR</a></li>
<li><a href="#ide.output">Output Window</a></li>
<li><a href="#ide.menu.edit">Paste</a></li>
<li><a href="#ctrl.image">Picture</a></li>
<li><a href="#ctrl.picturebox">PictureBox</a></li>
<li><a href="#lang.sound">PLAY</a></li>
<li><a href="#lang.sound">PLAY function</a></li>
<li><a href="#lang.runtime">PlayNoise</a></li>
<li><a href="#lang.runtime">PlayTone</a></li>
<li><a href="#lang.runtime">PlayWave</a></li>
<li><a href="#lang.runtime">PlayWaveLoop</a></li>
<li><a href="#lang.operators">Precedence</a></li>
<li><a href="#lang.constants">Predefined Constants</a></li>
<li><a href="#ide.menu.tools">Preferences</a></li>
<li><a href="#ide.preferences">Preferences</a></li>
<li><a href="#lang.io">PRINT</a></li>
<li><a href="#lang.fileio">PRINT #</a></li>
<li><a href="#ide.output">PRINT Output</a></li>
<li><a href="#lang.io">PRINT USING</a></li>
<li><a href="#lang.runtime">print.bas</a></li>
<li><a href="#lang.runtime">PrintPageSetup</a></li>
<li><a href="#lang.runtime">PrintPictureDialog</a></li>
<li><a href="#lang.runtime">PrintTextDialog</a></li>
<li><a href="#ctrl.progressbar">ProgressBar</a></li>
<li><a href="#ide.project">Project Explorer</a></li>
<li><a href="#ide.project">Project Files</a></li>
<li><a href="#ide.menu.file">Project Properties</a></li>
<li><a href="#ide.project">Project System</a></li>
<li><a href="#ctrl.common.props">Properties</a></li>
<li><a href="#ide.properties">Properties Panel</a></li>
<li><a href="#ide.properties">Property List</a></li>
<li><a href="#lang.fileio">PUT</a></li>
<li><a href="#ctrl.optionbutton">Radio Button</a></li>
<li><a href="#lang.misc">RANDOMIZE</a></li>
<li><a href="#lang.misc">RANDOMIZE TIMER</a></li>
<li><a href="#lang.io">READ</a></li>
<li><a href="#ctrl.spinbutton">RealMode</a></li>
<li><a href="#ctrl.data">RecordSource</a></li>
<li><a href="#lang.declarations">REDIM</a></li>
<li><a href="#ide.changes">Release Notes</a></li>
<li><a href="#lang.statements">REM</a></li>
<li><a href="#ide.menu.file">Remove File</a></li>
<li><a href="#lang.forms">RemoveControl</a></li>
<li><a href="#ctrl.listbox">RemoveItem</a></li>
<li><a href="#ide.immediate">REPL</a></li>
<li><a href="#ide.menu.edit">Replace</a></li>
<li><a href="#ide.findreplace">Replace</a></li>
<li><a href="#ctrl.textarea">ReplaceAll</a></li>
<li><a href="#ctrl.data">Reposition</a></li>
<li><a href="#ctrl.form">Resizable</a></li>
<li><a href="#lang.runtime">resource.bas</a></li>
<li><a href="#lang.io">RESTORE</a></li>
<li><a href="#lang.misc">RESUME</a></li>
<li><a href="#lang.misc">RESUME NEXT</a></li>
<li><a href="#lang.flow">RETURN</a></li>
<li><a href="#lang.func.string">RIGHT$</a></li>
<li><a href="#lang.filesystem">RMDIR</a></li>
<li><a href="#lang.func.math">RND</a></li>
<li><a href="#lang.func.string">RTRIM$</a></li>
<li><a href="#ide.menu.run">Run</a></li>
<li><a href="#ide.menu.run">Run Menu</a></li>
<li><a href="#ide.menu.run">Run to Cursor</a></li>
<li><a href="#ide.menu.run">Run Without Recompile</a></li>
<li><a href="#ide.output">Runtime Errors</a></li>
<li><a href="#ide.menu.file">Save All</a></li>
<li><a href="#ide.menu.file">Save File</a></li>
<li><a href="#ide.menu.run">Save on Run</a></li>
<li><a href="#ide.menu.file">Save Project</a></li>
<li><a href="#ctrl.scrollpane">Scrollable Container</a></li>
<li><a href="#ctrl.scrollpane">ScrollPane</a></li>
<li><a href="#ide.findreplace">Search</a></li>
<li><a href="#lang.fileio">SEEK</a></li>
<li><a href="#ide.menu.edit">Select All</a></li>
<li><a href="#lang.conditionals">SELECT CASE</a></li>
<li><a href="#ctrl.menus">Separator</a></li>
<li><a href="#ctrl.line">Separator</a></li>
<li><a href="#ctrl.tabstrip">SetActive</a></li>
<li><a href="#lang.filesystem">SETATTR</a></li>
<li><a href="#ctrl.listview">SetColumns</a></li>
<li><a href="#ctrl.textarea">SetCursor</a></li>
<li><a href="#lang.forms">SetEvent</a></li>
<li><a href="#ctrl.picturebox">SetPenColor</a></li>
<li><a href="#ctrl.picturebox">SetPenSize</a></li>
<li><a href="#ctrl.spinbutton">SetRange</a></li>
<li><a href="#ctrl.optionbutton">SetSelected</a></li>
<li><a href="#ctrl.listview">SetSort</a></li>
<li><a href="#ctrl.spinbutton">SetStep</a></li>
<li><a href="#ide.preferences">Settings</a></li>
<li><a href="#lang.func.math">SGN</a></li>
<li><a href="#lang.declarations">SHARED</a></li>
<li><a href="#lang.misc">SHELL</a></li>
<li><a href="#lang.forms">Show</a></li>
<li><a href="#ctrl.form">Show</a></li>
<li><a href="#lang.func.math">SIN</a></li>
<li><a href="#lang.datatypes">Single</a></li>
<li><a href="#lang.misc">SLEEP</a></li>
<li><a href="#ctrl.hscrollbar">Slider</a></li>
<li><a href="#lang.sound">SOUND</a></li>
<li><a href="#lang.runtime">Sound</a></li>
<li><a href="#lang.runtime">sound.bas</a></li>
<li><a href="#lang.runtime">SoundError$</a></li>
<li><a href="#lang.runtime">SoundInfo$</a></li>
<li><a href="#lang.runtime">SoundPlaying</a></li>
<li><a href="#lang.runtime">SoundVolume</a></li>
<li><a href="#ide.project">Source Map</a></li>
<li><a href="#lang.func.string">SPACE$</a></li>
<li><a href="#ctrl.spacer">Spacer</a></li>
<li><a href="#lang.io">SPC</a></li>
<li><a href="#ctrl.spinbutton">SpinButton</a></li>
<li><a href="#ctrl.spinbutton">Spinner</a></li>
<li><a href="#ctrl.splitter">Split Pane</a></li>
<li><a href="#ctrl.splitter">Splitter</a></li>
<li><a href="#lang.runtime">sql.bas</a></li>
<li><a href="#lang.sql">SQLAffected</a></li>
<li><a href="#lang.sql">SQLClose</a></li>
<li><a href="#lang.sql">SQLEof</a></li>
<li><a href="#lang.sql">SQLError$</a></li>
<li><a href="#lang.sql">SQLExec</a></li>
<li><a href="#lang.sql">SQLField$</a></li>
<li><a href="#lang.sql">SQLFieldCount</a></li>
<li><a href="#lang.sql">SQLFieldDbl</a></li>
<li><a href="#lang.sql">SQLFieldInt</a></li>
<li><a href="#lang.sql">SQLFreeResult</a></li>
<li><a href="#lang.sql">SQLite</a></li>
<li><a href="#ctrl.data">SQLite</a></li>
<li><a href="#lang.sql">SQLNext</a></li>
<li><a href="#lang.sql">SQLOpen</a></li>
<li><a href="#lang.sql">SQLQuery</a></li>
<li><a href="#lang.func.math">SQR</a></li>
<li><a href="#ide.debug.callstack">Stack Trace</a></li>
<li><a href="#ctrl.timer">Start</a></li>
<li><a href="#lang.statements">Statements</a></li>
<li><a href="#lang.declarations">STATIC</a></li>
<li><a href="#ide.menu.view">Status Bar Toggle</a></li>
<li><a href="#ctrl.statusbar">StatusBar</a></li>
<li><a href="#lang.loops">STEP</a></li>
<li><a href="#ide.menu.run">Step Into</a></li>
<li><a href="#ide.menu.run">Step Out</a></li>
<li><a href="#ide.menu.run">Step Over</a></li>
<li><a href="#ide.debugger">Stepping</a></li>
<li><a href="#lang.sound">STICK</a></li>
<li><a href="#ide.menu.run">Stop</a></li>
<li><a href="#ctrl.timer">Stop</a></li>
<li><a href="#lang.runtime">StopAllSounds</a></li>
<li><a href="#lang.runtime">StopWave</a></li>
<li><a href="#lang.func.string">STR$</a></li>
<li><a href="#lang.sound">STRIG</a></li>
<li><a href="#lang.datatypes">String</a></li>
<li><a href="#lang.func.string">STRING$</a></li>
<li><a href="#lang.procedures">SUB</a></li>
<li><a href="#ctrl.menus">Submenu</a></li>
<li><a href="#lang.declarations">SWAP</a></li>
<li><a href="#ide.editor">Syntax Highlighting</a></li>
<li><a href="#lang.io">TAB</a></li>
<li><a href="#ide.preferences">Tab Width</a></li>
<li><a href="#ctrl.tabstrip">TabControl</a></li>
<li><a href="#ctrl.tabstrip">TabStrip</a></li>
<li><a href="#lang.func.math">TAN</a></li>
<li><a href="#lang.runtime">TcpConnect</a></li>
<li><a href="#lang.runtime">TcpRecv$</a></li>
<li><a href="#ctrl.terminal">Terminal</a></li>
<li><a href="#ctrl.textbox">Text</a></li>
<li><a href="#ctrl.textarea">TextArea</a></li>
<li><a href="#ctrl.textbox">TextBox</a></li>
<li><a href="#lang.conditionals">THEN</a></li>
<li><a href="#lang.func.misc">TIME$</a></li>
<li><a href="#lang.func.math">TIMER</a></li>
<li><a href="#ctrl.timer">Timer</a></li>
<li><a href="#ide.menu.run">Toggle Breakpoint</a></li>
<li><a href="#ide.toolbar">Toolbar</a></li>
<li><a href="#ctrl.toolbar">Toolbar</a></li>
<li><a href="#ide.menu.view">Toolbar Toggle</a></li>
<li><a href="#ide.toolbox">Toolbox</a></li>
<li><a href="#ide.menu.tools">Tools Menu</a></li>
<li><a href="#ctrl.treeview">TreeView</a></li>
<li><a href="#lang.func.string">TRIM$</a></li>
<li><a href="#lang.constants">True</a></li>
<li><a href="#lang.declarations">TYPE</a></li>
<li><a href="#lang.func.fileio">UBOUND</a></li>
<li><a href="#lang.func.string">UCASE$</a></li>
<li><a href="#lang.runtime">UdpSend</a></li>
<li><a href="#lang.forms">UNLOAD</a></li>
<li><a href="#ctrl.form">Unload</a></li>
<li><a href="#lang.loops">UNTIL</a></li>
<li><a href="#lang.func.string">VAL</a></li>
<li><a href="#ctrl.data">Validate</a></li>
<li><a href="#ctrl.checkbox">Value</a></li>
<li><a href="#ide.immediate">Variable Assignment</a></li>
<li><a href="#ide.debug.locals">Variable Inspection</a></li>
<li><a href="#lang.constants">vbArchive</a></li>
<li><a href="#lang.constants">vbCancel</a></li>
<li><a href="#lang.constants">vbCritical</a></li>
<li><a href="#lang.constants">vbDirectory</a></li>
<li><a href="#lang.constants">vbExclamation</a></li>
<li><a href="#lang.constants">vbHidden</a></li>
<li><a href="#lang.constants">vbInformation</a></li>
<li><a href="#lang.forms">vbModal</a></li>
<li><a href="#lang.constants">vbNo</a></li>
<li><a href="#lang.constants">vbNormal</a></li>
<li><a href="#lang.constants">vbOK</a></li>
<li><a href="#lang.constants">vbOKCancel</a></li>
<li><a href="#lang.constants">vbOKOnly</a></li>
<li><a href="#ctrl.vbox">VBox</a></li>
<li><a href="#lang.constants">vbQuestion</a></li>
<li><a href="#lang.constants">vbReadOnly</a></li>
<li><a href="#lang.constants">vbRetry</a></li>
<li><a href="#lang.constants">vbRetryCancel</a></li>
<li><a href="#lang.constants">vbSystem</a></li>
<li><a href="#lang.constants">vbYes</a></li>
<li><a href="#lang.constants">vbYesNo</a></li>
<li><a href="#lang.constants">vbYesNoCancel</a></li>
<li><a href="#ctrl.vbox">Vertical Layout</a></li>
<li><a href="#ide.menu.view">View Menu</a></li>
<li><a href="#ide.overview">Visual Basic</a></li>
<li><a href="#ctrl.terminal">VT100</a></li>
<li><a href="#ide.debug.watch">Watch Expressions</a></li>
<li><a href="#ide.debug.watch">Watch Window</a></li>
<li><a href="#lang.loops">WEND</a></li>
<li><a href="#ide.changes">What's New</a></li>
<li><a href="#lang.loops">WHILE</a></li>
<li><a href="#ide.toolbox">Widget Palette</a></li>
<li><a href="#ctrl.form">Window</a></li>
<li><a href="#ide.menu.window">Window Menu</a></li>
<li><a href="#lang.forms">With</a></li>
<li><a href="#ctrl.wrapbox">WrapBox</a></li>
<li><a href="#lang.fileio">WRITE #</a></li>
<li><a href="#ide.designer">WYSIWYG</a></li>
<li><a href="#lang.operators">XOR</a></li>
</ul>
</nav>
<main>
<div class="topic" id="ide.overview">
<h1>DVX BASIC IDE Guide</h1>
<p>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.</p>
<p>This guide covers every feature of the IDE: menus, toolbar, editor, form designer, project management, debugger, and auxiliary windows.</p>
<h2>IDE Windows</h2>
<p>The DVX BASIC IDE is modeled after Visual Basic 3.0. It consists of several floating windows arranged on the DVX desktop:</p>
<ul>
<li>Main Toolbar Window -- anchored at the top of the screen. Contains the menu bar, toolbar buttons, and status bar.</li>
<li>Code Editor -- the primary editing surface for BASIC source code, with Object/Event dropdowns, syntax highlighting, and line numbers.</li>
<li>Form Designer -- a visual design surface for .frm files, showing a WYSIWYG preview of the form with grab handles for resizing controls.</li>
<li>Project Explorer -- a tree view listing all files in the project.</li>
<li>Toolbox -- a palette of available controls for placing on forms.</li>
<li>Properties Panel -- a tree of controls and a list of editable properties for the selected control.</li>
<li>Output Window -- displays PRINT output and runtime errors.</li>
<li>Immediate Window -- an interactive REPL for evaluating expressions and modifying variables at runtime.</li>
<li>Debug Windows -- Locals, Call Stack, Watch, and Breakpoints windows that appear automatically when debugging.</li>
</ul>
<p>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.</p>
<p><a href="#ide.menu.file">File Menu</a></p>
<p><a href="#ide.menu.edit">Edit Menu</a></p>
<p><a href="#ide.menu.run">Run Menu</a></p>
<p><a href="#ide.menu.view">View Menu</a></p>
<p><a href="#ide.menu.window">Window Menu</a></p>
<p><a href="#ide.menu.tools">Tools Menu</a></p>
<p><a href="#ide.menu.help">Help Menu</a></p>
<p><a href="#ide.toolbar">Toolbar</a></p>
<p><a href="#ide.editor">Code Editor</a></p>
<p><a href="#ide.designer">Form Designer</a></p>
<p><a href="#ide.project">Project System</a></p>
<p><a href="#ide.properties">Properties Panel</a></p>
<p><a href="#ide.toolbox">Toolbox</a></p>
<p><a href="#ide.debugger">Debugger</a></p>
<p><a href="#ide.debug.locals">Locals Window</a></p>
<p><a href="#ide.debug.callstack">Call Stack Window</a></p>
<p><a href="#ide.debug.watch">Watch Window</a></p>
<p><a href="#ide.debug.breakpoints">Breakpoints Window</a></p>
<p><a href="#ide.immediate">Immediate Window</a></p>
<p><a href="#ide.output">Output Window</a></p>
<p><a href="#ide.findreplace">Find / Replace</a></p>
<p><a href="#ide.preferences">Preferences</a></p>
<p><a href="#ide.shortcuts">Keyboard Shortcuts</a></p>
</div>
<div class="topic" id="ide.menu.file">
<h1>File Menu</h1>
<pre> 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 or .frm 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.
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.
---
Remove File Remove the selected file from the project (prompts to save if modified).
---
Exit Close the IDE (prompts to save unsaved changes).</pre>
<p>A project (.dbp) or source file (.bas, .frm) 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.</p>
<p>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.</p>
<p><a href="#ide.menu.edit">Edit Menu</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.menu.edit">
<h1>Edit Menu</h1>
<pre> 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.</pre>
<p>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.</p>
<p><a href="#ide.menu.run">Run Menu</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.menu.run">
<h1>Run Menu</h1>
<pre> 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.</pre>
<p><a href="#ide.menu.view">View Menu</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.menu.view">
<h1>View Menu</h1>
<pre> 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.</pre>
<p><a href="#ide.menu.window">Window Menu</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.menu.window">
<h1>Window Menu</h1>
<pre> 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.</pre>
<p><a href="#ide.menu.tools">Tools Menu</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.menu.tools">
<h1>Tools Menu</h1>
<pre> 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.</pre>
<p><a href="#ide.menu.help">Help Menu</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.menu.help">
<h1>Help Menu</h1>
<pre> 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.</pre>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.toolbar">
<h1>Toolbar</h1>
<p>The toolbar is organized into four groups separated by vertical dividers. Each button has a tooltip showing its name and keyboard shortcut.</p>
<h2>File Group</h2>
<pre> Button Shortcut Action
------ -------- ------
Open Ctrl+O Add a file to the project (same as File &gt; Add File).
Save Ctrl+S Save the active file.</pre>
<h2>Run Group</h2>
<pre> Button Shortcut Action
------ -------- ------
Run F5 Compile and run the program.
Stop Esc Stop the running program.</pre>
<h2>Debug Group</h2>
<pre> 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.</pre>
<h2>View Group</h2>
<pre> Button Shortcut Action
------ -------- ------
Code F7 Switch to Code view.
Design Shift+F7 Switch to Design view.</pre>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.editor">
<h1>Code Editor</h1>
<p>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.</p>
<h2>Object and Function Dropdowns</h2>
<p>At the top of the Code Editor are two dropdown lists:</p>
<ul>
<li>Object -- lists (General) plus all objects (form name, control names, menu item names). Selecting an object filters the Function dropdown.</li>
<li>Function -- lists all event handlers (procedures) for the selected object. Implemented handlers are listed first (plain text); unimplemented handlers follow in brackets (e.g., [Click]). Selecting an unimplemented event creates a new event handler stub.</li>
</ul>
<p>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.</p>
<p>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.</p>
<h2>Syntax Highlighting</h2>
<p>The editor applies real-time syntax coloring as you type. Seven categories are highlighted in distinct colors; the colors themselves are editable in Tools &gt; Preferences &gt; Colors.</p>
<pre> 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, TRUE, FALSE
Strings &quot;Hello, World!&quot;
Comments ' This is a comment, REM This is a comment
Numbers 42, 3.14, &amp;HFF
Operators =, &lt;, &gt;, +, -, *, /, \, &amp;</pre>
<h2>Editor Features</h2>
<ul>
<li>Line numbers -- displayed in the gutter on the left side.</li>
<li>Auto-indent -- new lines are automatically indented to match the previous line.</li>
<li>Tab handling -- the Tab key is captured by the editor. Tab width and whether to insert spaces or tab characters are configurable in Preferences (default: 3 spaces).</li>
<li>Gutter click -- clicking in the line number gutter toggles a breakpoint on that line.</li>
<li>Line decorations -- breakpoint lines show a red dot in the gutter. The current debug line (when paused) is highlighted with a yellow background.</li>
</ul>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.designer">
<h1>Form Designer</h1>
<p>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.</p>
<h2>Design Surface</h2>
<ul>
<li>Grid snapping -- controls snap to an 8-pixel grid when placed or resized.</li>
<li>Selection -- click a control to select it. The selected control is highlighted with grab handles.</li>
<li>Grab handles -- 6x6 pixel handles appear on the right edge (E), bottom edge (S), and bottom-right corner (SE) of the selected control. Drag a handle to resize the control.</li>
<li>Reordering -- drag a control to reorder it among its siblings in the layout (VBox/HBox). A container moves together with its contents.</li>
<li>Placing controls -- select a control type in the Toolbox, then click on the form to place a new instance. The control is auto-named (e.g., Command1, Command2), skipping names already used by a control, a menu item or the form. Clicking the same tool again deselects it (toggles back to pointer mode). Controls nest at most 15 levels deep; a drop into a container that is already that deep goes into its parent container.</li>
<li>Menu bar preview -- if the form has menu items (defined via the Menu Editor), a preview menu bar is rendered on the design window.</li>
<li>Delete key -- removes the selected control and everything inside it.</li>
</ul>
<p>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.</p>
<h2>Menu Editor</h2>
<p>The Menu Editor (View &gt; 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.</p>
<h2>Form Properties</h2>
<p>Forms have the following design-time properties: Name, Caption, Width, Height, Left, Top, Layout (VBox or HBox), Centered, AutoSize, Resizable, HelpTopic and ContextMenu.</p>
<p><a href="#ide.properties">Properties Panel</a></p>
<p><a href="#ide.toolbox">Toolbox</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.project">
<h1>Project System</h1>
<h2>Project Files (.dbp)</h2>
<p>A DVX BASIC project is stored as a .dbp file (DVX BASIC Project). The project file records:</p>
<ul>
<li>Name -- the project display name (up to 32 characters).</li>
<li>Startup Form -- which form to show automatically when the program starts.</li>
<li>Metadata -- Author, Company, Version, Copyright, Description (a single line), and Icon Path (for compiled binaries).</li>
<li>Arguments -- the command line the program gets (COMMAND$) when it is run from the IDE, for trying out a program that opens the file it is given. It is not built into the compiled program: there COMMAND$ returns whatever the program was started with.</li>
<li>Help File -- a compiled help file (.hlp) for the program. It is copied next to the compiled program, and F1 in the running program opens it, at the HelpTopic of the focused control or, failing that, of the form. Add help.bas to the project and call HelpView to open it from a Help menu.</li>
<li>File list -- relative paths of all .bas and .frm files in the project. Each entry tracks whether it is a form file.</li>
</ul>
<h2>How Projects are Compiled</h2>
<p>When the project is compiled, all source files are concatenated into a single source stream. The IDE tracks which lines belong to which file so error messages and debugger locations point to the correct .bas or .frm file. The code section of each .frm file is preceded by a hidden BEGINFORM marker that ties its code to its form.</p>
<h2>Compile-Time Validation</h2>
<p>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:</p>
<ul>
<li>Unknown widget types -- any Begin TypeName ... End block whose TypeName does not match a registered widget is flagged. The error message names the offending form, control, and type, and hints that DVX uses VB6-style names (SpinButton, not Spinner).</li>
<li>Unknown properties -- statements of the form CtrlName.Property = value, or reads of CtrlName.Property, are checked against the widget's declared property list. A typo such as btn.Captoin triggers a compile error with the form, control, and property name. A control name that is used with different types on different forms is not checked.</li>
<li>Unknown methods -- method calls CtrlName.Method ... are checked the same way against the widget's method list, catching mistakes like list.AddTiem before the program ever runs.</li>
<li>Menu items -- only Name (read), Checked and Enabled can be used on a menu item in code; Caption, Visible and RadioCheck are design-time settings.</li>
</ul>
<p>These checks use the same metadata the Properties panel and Toolbox read from each widget DXE, so property and method names always match the current widget set without any separate list to maintain.</p>
<h2>Project Operations</h2>
<pre> 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 &quot;Cannot load &lt;file&gt;: unreadable or larger than 65535 bytes.&quot; 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 or .frm file to the project. Opening a file without a project auto-creates an implicit project.
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.</pre>
<h2>Project Explorer</h2>
<p>The Project Explorer is a tree view window listing all project files. Double-click a file to open it: .bas files open in Code view, .frm files open in Design view. The selected file in the Project Explorer determines the target for View &gt; Code and View &gt; Designer commands.</p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.properties">
<h1>Properties Panel</h1>
<p>The Properties panel (Window &gt; Properties) has two sections:</p>
<ul>
<li>Control tree -- a TreeView at the top listing the form and all its controls in layout order. Click a control name to select it in both the Properties panel and the Form Designer. Drag items in the tree to reorder controls in the form's layout.</li>
<li>Property list -- a two-column ListView below the tree showing property names and values for the selected control. Double-click a property value to edit it via an InputBox dialog. Changes take effect immediately in the designer preview.</li>
</ul>
<p>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).</p>
<p><a href="#ide.designer">Form Designer</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.toolbox">
<h1>Toolbox</h1>
<p>The Toolbox (Window &gt; 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.</p>
<p>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.</p>
<h2>Available Controls</h2>
<pre> 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.</pre>
<p>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.</p>
<p><a href="#ide.designer">Form Designer</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.debugger">
<h1>Debugger</h1>
<p>The DVX BASIC IDE includes a full interactive debugger. The debugger has three states:</p>
<pre> 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.</pre>
<h2>Starting a Debug Session</h2>
<ul>
<li>Shift+F5 (Debug) -- compiles the project and starts execution in debug mode. Breakpoints are active but execution does not pause at the first statement.</li>
<li>F8 (Step Into) -- if idle, starts a debug session and breaks at the first statement.</li>
<li>F5 (Run) -- compiles and runs without the debugger. No breakpoints are active. If already paused, resumes execution with debugging disabled.</li>
</ul>
<h2>Breakpoints</h2>
<h3>Setting Breakpoints</h3>
<ul>
<li>Press F9 to toggle a breakpoint on the current editor line.</li>
<li>Click in the line number gutter to toggle a breakpoint on that line.</li>
</ul>
<h3>Breakpoint Validation</h3>
<p>Not every line can have a breakpoint. The IDE validates the line content and silently refuses to set breakpoints on:</p>
<ul>
<li>Blank lines</li>
<li>Comment lines (' or REM)</li>
<li>SUB and FUNCTION declaration lines</li>
<li>END SUB and END FUNCTION lines</li>
</ul>
<h3>Breakpoint Storage</h3>
<p>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.</p>
<h3>Visual Indicators</h3>
<ul>
<li>Breakpoint lines show a red dot in the gutter.</li>
<li>The current debug line (when paused) has a yellow background.</li>
</ul>
<h3>Breakpoint Adjustment on Edit</h3>
<p>Breakpoints follow their statements when lines are added, removed, joined, split or pasted. A breakpoint whose line is deleted is removed.</p>
<h2>Stepping</h2>
<pre> 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.</pre>
<h2>Debug Run Behavior</h2>
<p>When a program is running under the debugger:</p>
<ul>
<li>The program runs in short cooperative slices so the IDE remains responsive.</li>
<li>When the program hits a breakpoint, execution pauses immediately. The IDE switches to Code View, navigates to the breakpoint line, highlights it in yellow, and opens the Locals and Call Stack windows if they are not already visible.</li>
<li>While paused, you can inspect variables in Locals and Watch, evaluate expressions in the Immediate window, assign new values to variables, toggle breakpoints, step, continue, or stop. A pause in module-level code works the same way as a pause in an event handler.</li>
<li>Resuming (F5, Shift+F5, or any Step command) returns the program to Running state.</li>
</ul>
<h2>Stopping</h2>
<p>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.</p>
<p><a href="#ide.debug.locals">Locals Window</a></p>
<p><a href="#ide.debug.callstack">Call Stack Window</a></p>
<p><a href="#ide.debug.watch">Watch Window</a></p>
<p><a href="#ide.debug.breakpoints">Breakpoints Window</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.debug.locals">
<h1>Locals Window</h1>
<p>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.</p>
<p>Shows variables for the current execution scope. Displayed as a three-column ListView:</p>
<pre> Column Content
------ -------
Name Variable name (internal mangled names like static variable placeholders are filtered out).
Type Data type: Integer, Long, Single, Double, String, Boolean, Array, UDT. 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).</pre>
<p>The Locals window displays:</p>
<ul>
<li>Local variables of the current procedure, including its STATIC variables and the module variables it names in a SHARED statement.</li>
<li>Module-level variables. While execution is paused inside a SUB or FUNCTION, only the variables declared with DIM SHARED (or REDIM SHARED) are listed, because the procedure cannot see the others. This also applies inside a DEF FN function, although a DEF FN can read every module variable.</li>
<li>Form-scoped variables for the current form (if the program is executing within a form context), with the same SHARED rule.</li>
</ul>
<p>The Watch window and the Immediate window follow the same rules. The window is resizable.</p>
<p><a href="#ide.debug.callstack">Call Stack Window</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.debug.callstack">
<h1>Call Stack Window</h1>
<p>Shows the current call chain as a two-column ListView:</p>
<pre> Column Content
------ -------
Procedure Procedure name (or (module) for module-level code).
Line Line number where execution is paused (shown for the topmost frame).</pre>
<p>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.</p>
<p><a href="#ide.debug.watch">Watch Window</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.debug.watch">
<h1>Watch Window</h1>
<p>Allows monitoring arbitrary expressions while debugging. The window has a text input at the top and a two-column ListView below:</p>
<pre> Column Content
------ -------
Expression The watch expression text.
Value Evaluated result (or &lt;error&gt; if evaluation fails). Blank when not paused.</pre>
<h2>Adding Watch Expressions</h2>
<p>Type an expression in the text input and press Enter. Up to 16 watch expressions can be active at once.</p>
<h2>Watch Expression Syntax</h2>
<p>Watch expressions support:</p>
<ul>
<li>Simple variable names: x, count</li>
<li>Array subscripts: arr(5), matrix(2, 3)</li>
<li>UDT field access: player.name</li>
<li>Combined: items(i).price</li>
<li>Arbitrary BASIC expressions (compiled and evaluated against the paused VM's state): x + y * 2, Len(name$)</li>
</ul>
<h2>Editing and Deleting</h2>
<ul>
<li>Double-click or press Enter on a watch entry to move it back into the input box for editing.</li>
<li>Press Delete to remove the selected watch expression.</li>
</ul>
<p><a href="#ide.debug.breakpoints">Breakpoints Window</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.debug.breakpoints">
<h1>Breakpoints Window</h1>
<p>Lists all set breakpoints as a three-column ListView:</p>
<pre> Column Content
------ -------
File Project file path.
Procedure Procedure name (Object.Event format, or (General)).
Line Code line number within the file.</pre>
<ul>
<li>Double-click a breakpoint to navigate the code editor to that location.</li>
<li>Press Delete to remove selected breakpoints (multi-select is supported).</li>
</ul>
<p><a href="#ide.debugger">Debugger</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.immediate">
<h1>Immediate Window</h1>
<p>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 &quot;Error: Statement did not finish; stopped.&quot;</p>
<h2>Expression Evaluation</h2>
<p>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.</p>
<p>You can also type full statements:</p>
<ul>
<li>PRINT x * 2 -- evaluate and print an expression.</li>
<li>DIM tmp As Integer -- declare a temporary variable.</li>
<li>LET x = 42 -- explicit assignment (see below).</li>
</ul>
<p>Parse or runtime errors are displayed inline with an Error: prefix.</p>
<h2>Inspecting Variables While Paused</h2>
<p>When the debugger is paused at a breakpoint, the Immediate window has access to the running program's state. Expressions like count or name$ &amp; &quot; test&quot; display live values.</p>
<h2>Assigning Variables While Paused</h2>
<p>When paused, you can modify variables in the running program directly from the Immediate window using assignment syntax:</p>
<pre><code>variableName = newValue</code></pre>
<p>The optional LET keyword is also accepted:</p>
<pre><code>LET variableName = newValue</code></pre>
<p>Assignment works for:</p>
<ul>
<li>Scalar variables -- x = 42, name$ = &quot;test&quot;, count = count + 1 (any expression is allowed on the right)</li>
<li>Array elements -- arr(5) = 100, matrix(2, 3) = 7.5</li>
<li>UDT fields -- player.score = 1000</li>
<li>Combined -- items(0).price = 9.99</li>
</ul>
<p>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.</p>
<p>If the assignment target cannot be resolved (unknown variable, out-of-bounds index, wrong type), an error message is displayed.</p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.output">
<h1>Output Window</h1>
<p>The Output window is a read-only TextArea at the bottom-left of the screen. It displays:</p>
<ul>
<li>PRINT output -- all PRINT statement output from the running program is appended here.</li>
<li>Runtime errors -- if the VM encounters a runtime error (division by zero, out-of-bounds, etc.), the error message and line number are displayed in the output with an Error on line N: prefix.</li>
<li>Compile errors -- if compilation fails, the error message and location are shown.</li>
</ul>
<p>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 &gt; Clear Output to clear it.</p>
<p>INPUT statements prompt the user via a modal InputBox dialog; the prompt text is also echoed to the Output window.</p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.findreplace">
<h1>Find / Replace</h1>
<p>Open with Ctrl+F (Find) or Ctrl+H (Replace). The Find/Replace dialog is modeless -- it stays open while you continue editing.</p>
<h2>Dialog Controls</h2>
<pre> 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.</pre>
<h2>Buttons</h2>
<pre> 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.</pre>
<h2>Keyboard Shortcut</h2>
<p>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.</p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.preferences">
<h1>Preferences</h1>
<p>Open via Tools &gt; Preferences. Settings are saved to dvxbasic.ini in the app's config directory. The dialog has two tabs.</p>
<h2>General Tab</h2>
<h3>Editor Section</h3>
<pre> 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</pre>
<h3>New Project Defaults Section</h3>
<p>These fields set the default values for new project metadata:</p>
<pre> 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)</pre>
<h2>Colors Tab</h2>
<p>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 and adjust its red, green, and blue components using the three sliders on the right. The Preview swatch shows the current color. Changes are applied to the open editor when you click OK.</p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.shortcuts">
<h1>Keyboard Shortcuts</h1>
<pre> 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</pre>
<p><a href="#ide.changes">Changes in This Release</a></p>
<p><a href="#ide.overview">Back to Overview</a></p>
</div>
<div class="topic" id="ide.changes">
<h1>Changes in This Release</h1>
<p>This release fixes a large number of problems in the language, the runtime, the controls and the IDE. Most programs keep working unchanged. The one change that needs attention in existing programs is variable scope: see Module Variables Need SHARED below.</p>
<h2>Module Variables Need SHARED</h2>
<p>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.</p>
<ul>
<li>In an existing program, change DIM to DIM SHARED for every module-level variable that a SUB, FUNCTION or event handler uses.</li>
<li>Without that change such a name silently becomes a local variable of the procedure (or a compile error with OPTION EXPLICIT, or when the procedure indexes or dots it).</li>
<li>New: the SHARED statement inside a procedure, and REDIM SHARED at module level. DIM SHARED inside a procedure is a compile error.</li>
<li>CONSTs, TYPEs, procedures, forms and controls are visible everywhere as before; a DEF FN still sees every module variable.</li>
</ul>
<p><a href="#lang.declarations">See: Variable Scope and SHARED</a></p>
<h2>Language</h2>
<ul>
<li>GOSUB and RETURN work inside SUB and FUNCTION: each procedure call has its own GOSUB stack. RETURN with no pending GOSUB in the procedure raises error 3 (RETURN without GOSUB); before, RETURN inside a procedure left the procedure (use EXIT SUB / EXIT FUNCTION for that).</li>
<li>Labels belong to their SUB or FUNCTION (or to the module level). GOTO, GOSUB, ON GOTO/GOSUB and ON ERROR GOTO reach only labels of the same procedure; the same label name can be used in several procedures, and a label may share a name with a variable. An undefined label, or a jump to a SUB or variable name, is a compile error. &quot;SubName:&quot; at the start of a line is an error instead of a silent label.</li>
<li>A CONST inside a SUB or FUNCTION is local and no longer overrides a module constant. CONST name AS type converts the literal (Integer and Long round and range-check); a string/number mismatch or an overflow is a compile error.</li>
<li>DEF FN must be defined before it is used; its free names are module variables.</li>
<li>DEFINT, DEFLNG and the other DEFtype statements also apply to parameters, STATIC variables and FUNCTION results. A typed FUNCTION converts the value assigned to it (FUNCTION F AS INTEGER with F = 2.5 returns 2). STATIC variables convert on store and their names no longer leak out of the procedure.</li>
<li>DIM a, b AS STRING, c(3) declares several variables in one statement.</li>
<li>name(...) in an expression only calls FUNCTIONs; a SUB there, or indexing a scalar or CONST, is a compile error.</li>
<li>A FUNCTION can be called as a statement (F 3), discarding its result.</li>
<li>DECLARE must match the definition's BYVAL and OPTIONAL flags too.</li>
<li>SWAP and GET #n, , arr(i) evaluate each subscript exactly once. A BYREF argument written as an expression such as arr(i) + 1 is passed by value.</li>
<li>Numeric literals: an Integer/Long suffix on a literal with a fraction or exponent rounds (1E3% is 1000); -32768% and -2147483648&amp; are accepted; 1. is a valid literal; an over-long literal is an error.</li>
<li>DATA: unquoted items are raw text up to the next comma, colon, comment or end of line.</li>
<li>READ, INPUT, INPUT # and LINE INPUT # accept array elements and TYPE fields; PRINT #n, alone writes an empty line.</li>
<li>PRINT USING: ; and , both separate values, and a trailing ; or , suppresses the newline.</li>
<li>More than 8 array dimensions, or an LBOUND/UBOUND dimension outside 1..8, is a compile error.</li>
<li>A missing END SUB, END FUNCTION, END TYPE or END DECLARE is a compile error.</li>
<li>FOR: a constant fractional STEP with an Integer or Long counter is a compile error, and a computed STEP is rounded to the counter's type. A fractional STEP no longer turns a Single counter into a Double.</li>
<li>DECLARE LIBRARY arguments are always passed by value, converted to the declared parameter type (a Single parameter receives a Single).</li>
<li>Name(idx).Member works with any member name (including keywords such as Name and Text), with method calls and in chains; Me.Method (x) is a method call.</li>
<li>Compile errors read &quot;Line N, Col C: message&quot;.</li>
<li>New: COMMAND$ returns the arguments the program was started with (for example the document it was opened with), and COMMAND$(n) returns the nth argument without its quotes. The DVX programs that open documents (Notepad, Image Viewer, Icon Editor, Resource Editor, Help Editor) open the file named there when they start. In the IDE, set the arguments under Project Properties. A program that uses COMMAND$ does not run on an older DVX.</li>
<li>A SUB or FUNCTION may use at most 64 local slots (parameters, local variables and hidden temporaries). More is a compile error &quot;Too many local variables in X (n, limit is 64)&quot; instead of a runtime error 9; READ and INPUT # into many array elements no longer use a slot per target.</li>
<li>SHARED naming a variable that does not exist at module level creates it there; in a form's code it becomes a variable of that form, not a program-wide one.</li>
</ul>
<h2>Sound, Joysticks and Frames</h2>
<ul>
<li>New statements from QBasic: BEEP, SOUND frequency, duration (in clock ticks, 18.2 a second) and PLAY with the whole music macro language (notes, octaves, lengths, dots, pauses, tempo, MN/ML/MS, and MF/MB for foreground or background music), plus the PLAY(n) function (notes still waiting in the background). They play on whatever sound hardware the computer has, or silently when there is none.</li>
<li>PLAY's new I command plays the notes that follow on a General MIDI instrument (I1 to I128) through the music synthesizer; I0 goes back to tones.</li>
<li>New functions from QBasic: STICK(n) (joystick position, 1 to 200) and STRIG(n) (joystick buttons), on any joystick DVX knows, or the keyboard when there is none.</li>
<li>New statement FRAMEWAIT rate: waits for the next frame of a steady clock, keeping the desktop running, so a game loop runs at the same speed on every computer.</li>
<li>BEEP, SOUND, PLAY and FRAMEWAIT are now keywords, and STICK and STRIG built-in functions: a variable, SUB or FUNCTION with one of these names must be renamed.</li>
<li>Message boxes (MsgBox) play the desktop sound chosen for their kind on the Control Panel's Sounds tab.</li>
</ul>
<p><a href="#lang.sound">See: Sound, Joysticks and Frames</a></p>
<h2>Runtime</h2>
<ul>
<li>Nested BYREF parameters reach the original variable or array element.</li>
<li>ON ERROR is per procedure. A procedure called from a handler can trap its own errors, returning from a procedure that only installed a handler leaves the caller's ERR alone, and an error inside a running handler passes to the caller's handler.</li>
<li>RESUME NEXT after an error in an IF/ELSEIF/WHILE/DO/LOOP condition skips the block or leaves the loop; 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 and the next value or CASE is tried; after an error in an ON selector no branch is taken.</li>
<li>New error numbers: 3 RETURN without GOSUB, 14 Out of string space, 28 Out of stack space (was reported as 7), 63 Bad record number, 91 Object variable not set. ERR is a Long, and ERROR n reports the standard message for known numbers.</li>
<li>Using a property or method (or Show, Hide, Unload) on a value that is not a form or control raises error 91 instead of doing nothing.</li>
<li>EXP, ^ and other math that leaves the numeric range raise error 6 (Overflow); an undefined result raises error 5.</li>
<li>INT, FIX and SGN return an Integer (Long or Double when needed); RND returns a Double and follows QBasic (RND(0) repeats the last number, a negative argument reseeds). RANDOMIZE with a negative or very large seed, and RND with a very large negative argument, seed predictably (the seed is taken modulo 2^32), so the sequence for a negative RANDOMIZE seed may differ from before. -x of the most negative Integer or Long widens like 0 - x.</li>
<li>INSTR follows OPTION COMPARE TEXT. INSTR and the MID$ statement reject a start below 1 (error 5); MID$ with a length of 0 replaces nothing.</li>
<li>PRINT # writes a space after numbers, as PRINT does. PRINT USING and FORMAT$ show a value too wide for the field in scientific notation.</li>
<li>SEEK on a RANDOM file works in records (statement and function); a position below 1 is error 63. PUT of a value longer than the record length raises error 59 before writing anything.</li>
<li>SLEEP keeps the desktop and the program's forms running, SLEEP 0 just processes events, and closing the program ends the sleep.</li>
<li>DIR$ returns only files. GETATTR and SETATTR on a missing file raise error 53; SETATTR raises 75 when it cannot change the attributes.</li>
<li>IniRead and IniWrite use the same INI reader as the DVX system settings. IniWrite keeps the text of every other line (of any length) unchanged, ends every line of the saved file with CR LF, and raises error 75 when it cannot read the existing file or write the new one (a write failure used to be ignored); a failed write leaves the old file intact. IniRead no longer finds keys in the tail of a long line, and keys above the first section header are read with section &quot;&quot;. Section names are matched with surrounding blanks ignored.</li>
<li>VAL keeps the magnitude of very long digit strings. Running out of memory while building a string raises error 14.</li>
<li>REDIM PRESERVE of a TYPE array keeps the existing elements.</li>
<li>Appending to a String variable with s = s + x or s = s &amp; x no longer copies the whole string each time, so building long strings in a loop is much faster. When x is InputBox$, MsgBox, CreateForm, CreateControl or Shell, s is still read before x runs (left to right).</li>
<li>Programs compiled with an older release must be rebuilt. A program whose procedure table records more than 64 locals for a procedure is refused when it is loaded.</li>
</ul>
<h2>Forms and Controls</h2>
<ul>
<li>A reference to a removed control or to a control of an unloaded form raises an &quot;unknown control&quot; runtime error. CreateControl with a parent that is not a container on the same form raises &quot;CreateControl: invalid parent&quot;.</li>
<li>SetEvent works on forms (Me) and menu items; a handler without parameters is called without the event's arguments.</li>
<li>Form.Visible = True/False behaves exactly like Show/Hide, but only on a real change: Visible = True on a form that is already shown does nothing (a modal form stays modal), and on a form that has no window it is ignored. MinWidth and MinHeight read back the value that was set. Size properties are limited to 0..32767.</li>
<li>Disabling a container (for example Frame.Enabled = False) blocks mouse and keyboard input to every control inside it (also inside a disabled ScrollPane or Splitter), and SetFocus on such a control does nothing.</li>
<li>OptionButton.Value is a read/write Boolean (True = selected); the button's index is the new read-only OptionIndex. Setting Value raises no Click.</li>
<li>HScrollBar has Min and Max properties. SpinButton's RealMode uses the range set with SetRange. PictureBox has read-only ImageWidth and ImageHeight.</li>
<li>ListBox SetItems &quot;&quot; empties the list, and every | separates items. ListView SetColumns has no length limit. TreeView Clear resets scrolling. TextArea FindNext finds a match that starts at the cursor, and the new SetCursor method moves the caret without selecting.</li>
<li>TabStrip/TabControl: a negative tab index selects the first tab and an index past the end the last one.</li>
<li>The mouse wheel over a DBGrid scrolls the rows without moving the current record, and over a Terminal scrolls its history locally.</li>
<li>.frm files: End followed by blanks or a comment (also End'comment) closes its block while End followed by a word does not, in the compiler, the build and the release renamer exactly as in the loader, Begin followed by a tab is accepted, Enabled = False on popup-menu items is applied, properties after a nested child's End apply to the parent, and Layout on a control that is not a container is reported.</li>
<li>Include libraries: sql.bas, comm.bas and commdlg.bas take and return Long (SQLFieldInt and SQLAffected no longer wrap above 32767); resource.bas string functions are declared AS STRING. CommHandshake takes an optional passphrase, and the new CommSetPlain accepts unencrypted data on a channel.</li>
<li>commdlg.bas functions are renamed to match the other include libraries: basFileOpen is now DlgFileOpen$, basFileSave is DlgFileSave$, basInputBox2 is DlgInputBox$, basInputCancelled is DlgInputCancelled, basChoiceDialog is DlgChoice, basIntInput is DlgIntInput and basPromptSave is DlgPromptSave. The old names are gone; programs that use them must be updated and rebuilt.</li>
<li>New in comm.bas: CommRecvEncrypted(handle, channel) returns True when every byte the last CommRecv$ on that channel returned arrived encrypted and authenticated (also when it returned nothing), and False when any arrived unencrypted (before CommHandshake or on a CommSetPlain channel).</li>
<li>KeyDown: Shift, Ctrl or Alt with F1-F12, and Alt with Home, End, PgUp, PgDn, Ins, Del and the arrow keys, report the plain key's KeyCode with the modifier in Shift, even when the modifier is released before the program sees the key.</li>
<li>Data control: while its Validate handler runs, MoveFirst, MoveLast, MoveNext, MovePrevious, AddNew, Refresh and Update on the same Data control are ignored (they used to validate the same record again without end); Delete is allowed. Only unloading the Data control itself from Validate or Reposition stops the operation that fired it; removing other controls does not.</li>
<li>Data control: writing a field back with the value it already has is not an edit, so leaving a bound control no longer fires Validate. With a SELECT query as RecordSource, edits are dropped when the current record changes. Update and Delete still find a record whose key is a number stored without a declared column type, or is NULL, when the key names exactly one record; Delete keeps the record shown when the database row could not be deleted.</li>
<li>DBGrid re-sorts and re-measures its columns when the Data control's records change (Refresh, AddNew, Delete or an edit), keeping the chosen sort column, and not on a plain record move.</li>
<li>Image and ImageButton: Picture = &quot;&quot; clears the picture (Picture then reads back &quot;&quot;); a file that cannot be loaded leaves the picture and Picture unchanged. A disabled Image keeps its transparent color transparent.</li>
<li>Timer: a Timer whose handler shows a modal dialog no longer fires a second time from inside that dialog.</li>
<li>TextArea: the horizontal scroll bar appears as soon as the longest line fills the visible width, and the caret stays visible while typing at the right edge.</li>
<li>Terminal: pasting with Ctrl+V returns the view to the live screen and sends the text in small pieces.</li>
<li>ListBox and ListView: changing the items while an item is being dragged ends the drag.</li>
<li>TabControl: switching tabs closes an open drop-down list only when it belongs to a control on the page being hidden. A Label on a Toolbar is drawn on the toolbar's color.</li>
<li>Compile errors from the command-line compiler name the file and line. A .frm without a Begin Form line is an error. A release build that runs out of memory while renaming names fails instead of producing a broken program.</li>
<li>A form shown modal has no minimize gadget.</li>
<li>Menu items accept only Name (read-only), Checked and Enabled in code; Caption, Visible and RadioCheck are design-time settings, and using them in code is a compile error in the IDE.</li>
</ul>
<h2>IDE</h2>
<ul>
<li>Immediate window: Enter evaluates the line it is pressed on, assignments accept any expression, and a statement that does not finish is stopped.</li>
<li>Output window: always shows the newest output and drops the oldest lines when full; Output Window to Log also logs errors.</li>
<li>Find/Replace: Object and File scopes search only that object or file; F3 works after the dialog is closed.</li>
<li>Edit commands act on the window last worked in (designer control or text window). A pasted control keeps all its properties.</li>
<li>The code editor never drops text outside the shown procedure; only untouched generated event handlers are removed.</li>
<li>Files are saved exactly as written, with LF line endings, through a temporary file (for FORM1.FRM, FORM1.$FR, with the old file kept as FORM1.~FR until the save is complete; your own name.BAK is never touched); carriage returns are removed when files are loaded. Don't Save discards Project Properties changes too. A project file may hold up to 64 KB of text not counting carriage returns; a file of twice that size or more is refused without being read.</li>
<li>Debugger: while paused inside a SUB or FUNCTION, Locals and Watch show only the variables the procedure can see (its locals, its STATIC and SHARED names, and DIM SHARED module variables), and STATIC variables are now listed.</li>
<li>Compile-time checks of control properties and methods use the control on the form whose code is being compiled, so a control name used for different control types on different forms is checked too.</li>
<li>Form designer: Image and ImageButton are no longer in the Toolbox, controls nest at most 15 levels, Delete removes a control with its contents, AutoSize matches the runtime, TabStrip TabIndex and the form's ContextMenu are kept on save, control arrays inside containers no longer duplicate controls, and a control keeps any number of design-time properties.</li>
<li>Error and debugger line numbers in a form's code match the editor exactly (the indentation of the first code line is kept).</li>
<li>Menu Editor: at most 15 levels, the close box cancels, and only real renames rewrite event handlers.</li>
<li>Project Properties: Description is a single line.</li>
<li>A Sub or Function whose name already exists (typed or pasted) stays its own procedure, and the compiler reports the duplicate; before, it was moved into (General).</li>
<li>Breakpoints and the caret follow lines that the editor moves when it tidies a procedure (blank lines after End Sub, text typed outside a Sub, a deleted Sub line); a breakpoint whose line disappears is removed.</li>
<li>Immediate window: output leaves room for typing, and Enter in a completely full window evaluates nothing and says so in the status bar.</li>
<li>Debugger: a breakpoint reached while a stopped program is unwinding no longer pauses it.</li>
<li>The title bar's * also shows for a form changed in the designer but not yet saved.</li>
<li>Form designer: a property value may be as long as a full .frm line (511 characters); a value too long for the line it is saved on (deeply nested controls) stops the save with &quot;A property value is too long to save at its position in the form&quot;. Making a container part of a control array keeps its contents. Only one OptionButton per container keeps Value = True: setting it on one (in the property grid or by pasting a selected one) clears the others.</li>
</ul>
<p><a href="#ide.overview">Back to Overview</a></p>
<hr>
<p>DVX BASIC 1.0 -- Copyright 2026 Scott Duensing</p>
</div>
<div class="topic" id="lang.datatypes">
<h1>Data Types</h1>
<p>DVX BASIC supports the following data types. Each type has a corresponding type suffix character that can be appended to variable names.</p>
<h2>Primary Types</h2>
<pre> Type Size Suffix Range / Description
---- ---- ------ -------------------
Integer 2 bytes % -32768 to 32767
Long 4 bytes &amp; -2147483648 to 2147483647
Single 4 bytes ! 32-bit float, approximately 7 digits precision
Double 8 bytes # 64-bit float, approximately 15 digits precision
String variable $ Variable-length, reference-counted, dynamic string
Boolean 2 bytes (none) True (-1) or False (0)</pre>
<h2>Internal Types</h2>
<p>These types are not directly declarable but are used internally by the runtime.</p>
<pre> Internal Type Description
------------- -----------
Array Reference-counted multi-dimensional array (up to 8 dimensions)
UDT User-defined type instance (created with TYPE...END TYPE)
Object Opaque host object (form reference, control reference)
Ref ByRef pointer to a variable slot (used for ByRef parameters)</pre>
<h2>Type Suffixes</h2>
<p>Type suffixes can be appended to variable names to declare their type implicitly:</p>
<pre><code>count% = 42 ' Integer
total&amp; = 100000 ' Long
rate! = 3.14 ' Single
pi# = 3.14159265 ' Double
name$ = &quot;Hello&quot; ' String</code></pre>
<h2>Numeric Literals</h2>
<pre> Form Example Description
---- ------- -----------
Decimal integer 42 Values -32768..32767 are Integer; larger are Long
Hex integer &amp;HFF, &amp;H1234 Hexadecimal literal (0-9, A-F)
Octal integer &amp;O10, &amp;O77 Octal literal (0-7)
Binary integer &amp;B1010, &amp;B11111111 Binary literal (0-1)
Integer suffix 42% Force Integer type
Long suffix 42&amp;, &amp;HFF&amp; 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</pre>
<blockquote><strong>Note:</strong> Both E and D can introduce an exponent (e.g. 1.5E10 and 2.5D3 are equivalent forms of a scientific-notation double).</blockquote>
<p>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&amp; are valid. A trailing decimal point is allowed (1. is the Double 1). A numeric literal too long to read is a compile error.</p>
<h2>Type Promotion</h2>
<p>When mixing types in expressions, values are automatically promoted to a common type: Integer -&gt; Long -&gt; Single -&gt; Double. + joins two strings; when a string meets a number in an arithmetic operator (including +) the string is converted as VAL does (&quot;1&quot; + 2 is 3, &quot;abc&quot; + 2 is 2). Use &amp; to join text and numbers, and VAL / STR$ to convert explicitly.</p>
<h2>Assignment Conversion</h2>
<p>Storing a value into a variable declared as Integer, Long, Single or Boolean (by suffix, by AS clause, by DEFINT/DEFLNG/DEFSNG, or as a typed parameter, STATIC variable, FUNCTION result, TYPE field or array element) converts the value to that type. DEFtype statements also give parameters, STATIC variables and FUNCTION results their default type. 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. 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. 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.</p>
<pre><code>Dim n As Integer
n = 3.7 ' n is 4
n = 40000 ' Error 6: Overflow
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</code></pre>
<h2>Boolean Values</h2>
<p>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.</p>
<p><a href="#lang.func.conversion">See also: Conversion Functions</a></p>
</div>
<div class="topic" id="lang.operators">
<h1>Operators</h1>
<p>Operators listed from highest precedence (evaluated first) to lowest precedence (evaluated last). Parentheses override precedence and may be nested freely.</p>
<pre> 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 &amp; String concatenation
8 = &lt;&gt; &lt; &gt; &lt;= &gt;= 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</pre>
<h2>Arithmetic Operators</h2>
<pre> 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)</pre>
<h2>Comparison Operators</h2>
<p>Comparison operators return True (-1) or False (0).</p>
<pre> Operator Description
-------- -----------
= Equal to
&lt;&gt; Not equal to
&lt; Less than
&gt; Greater than
&lt;= Less than or equal to
&gt;= Greater than or equal to</pre>
<p>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.</p>
<h2>Logical / Bitwise Operators</h2>
<p>The logical operators work on Boolean values and also perform bitwise operations on integer values.</p>
<pre> 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)</pre>
<h2>String Concatenation</h2>
<p>Use &amp; to concatenate strings. The + operator also concatenates when both operands are strings. Prefer &amp; because it does not depend on operand types.</p>
<pre><code>result$ = &quot;Hello&quot; &amp; &quot; &quot; &amp; &quot;World&quot;
result$ = firstName$ &amp; &quot; &quot; &amp; lastName$
' + also concatenates when both operands are strings
greeting$ = &quot;Hi &quot; + name$</code></pre>
</div>
<div class="topic" id="lang.statements">
<h1>Statements</h1>
<p>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.</p>
<pre><code>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
? &quot;Hello&quot; ' same as PRINT &quot;Hello&quot;</code></pre>
<p><a href="#lang.declarations">Declaration Statements (DIM, REDIM, CONST, TYPE, DECLARE)</a></p>
<p><a href="#lang.conditionals">Conditional Statements (IF, SELECT CASE)</a></p>
<p><a href="#lang.loops">Loop Statements (FOR, DO, WHILE)</a></p>
<p><a href="#lang.procedures">Procedures (SUB, FUNCTION, DEF FN)</a></p>
<p><a href="#lang.flow">Flow Control (EXIT, CALL, GOTO, GOSUB, ON)</a></p>
<p><a href="#lang.io">Input/Output (PRINT, INPUT, DATA/READ)</a></p>
<p><a href="#lang.misc">Miscellaneous Statements (ON ERROR, SHELL, SLEEP, END)</a></p>
<p><a href="#lang.sound">Sound, Joysticks and Frames (BEEP, SOUND, PLAY, STICK, STRIG, FRAMEWAIT)</a></p>
</div>
<div class="topic" id="lang.declarations">
<h1>Declaration Statements</h1>
<h2>DIM</h2>
<p>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.</p>
<pre><code>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 SHARED variable AS type
DIM variable1 [AS type], variable2 [AS type], ...</code></pre>
<p>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).</p>
<p>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:</p>
<pre><code>Dim name$, count%, total&amp; ' suffixes infer the types
Dim first, last As String, list(10) As Integer</code></pre>
<p>Examples:</p>
<pre><code>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</code></pre>
<blockquote><strong>Note:</strong> 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 &quot;Too many local variables&quot;.</blockquote>
<p>Fixed-length strings (STRING * n) are padded with spaces and truncated when assigned so their length is always exactly n.</p>
<h2>Variable Scope and SHARED</h2>
<p>DVX BASIC follows the QBasic scope rules:</p>
<ul>
<li>Variables declared (or first used) at module level -- outside every SUB and FUNCTION -- are module variables. The code section of a form (.frm) is module-level code of that form.</li>
<li>A SUB or FUNCTION sees a module variable only when it was declared with DIM SHARED at module level, or when the procedure names it in a SHARED statement. This applies to arrays as well.</li>
<li>Any other name used inside a SUB or FUNCTION is a local variable of that procedure, even when a module variable of the same name exists. With OPTION EXPLICIT, using such a name without a DIM is a compile error that says the module variable is not SHARED.</li>
<li>Indexing (name(...)) or dotting (name.member) a module variable the procedure cannot see is a compile error.</li>
<li>CONSTs declared at module level, TYPEs, SUBs, FUNCTIONs, forms and controls are visible everywhere; no SHARED is needed for them.</li>
<li>A DEF FN is module-level code: its expression sees every module variable.</li>
</ul>
<pre><code>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</code></pre>
<p>DIM SHARED and REDIM SHARED are only allowed at module level. Inside a procedure use the SHARED statement:</p>
<pre><code>SHARED variable [()] [AS type] [, variable [()] [AS type] ...]</code></pre>
<p>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).</p>
<h2>REDIM</h2>
<p>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).</p>
<pre><code>REDIM array(newBounds) AS type
REDIM PRESERVE array(newBounds) AS type
REDIM SHARED array(newBounds) AS type</code></pre>
<p>REDIM SHARED (module level only) also makes the array visible in every SUB and FUNCTION, like DIM SHARED.</p>
<pre><code>ReDim items(newSize) As String
ReDim Preserve scores(1 To newCount) As Integer</code></pre>
<h2>CONST</h2>
<p>Declares a named constant. The value must be a literal (integer, long, float, string, or boolean). Constants are not variables -- you cannot assign a new value to them or pass them by reference.</p>
<pre><code>CONST name = value
CONST name AS type = value</code></pre>
<pre><code>Const MAX_SIZE = 100
Const PI = 3.14159265
Const APP_NAME = &quot;DVX App&quot;
Const DEBUG_MODE = True
Const HEADER As String = &quot;=== Report ===&quot;</code></pre>
<p>With an AS clause the literal is converted to that type: Integer and Long values are rounded and must fit the type, and a string literal for a numeric type (or a number for String) is a compile error. Without an AS clause an integer literal makes a Long constant and a literal with a fraction a Double constant.</p>
<p>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.</p>
<h2>TYPE...END TYPE</h2>
<p>Defines a user-defined type (record/structure).</p>
<pre><code>TYPE TypeName
fieldName AS type
fieldName AS STRING * n
...
END TYPE</code></pre>
<pre><code>Type PersonType
firstName As String
lastName As String * 20
age As Integer
End Type
Dim p As PersonType
p.firstName = &quot;Scott&quot;
p.age = 30</code></pre>
<p>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).</p>
<h2>DECLARE</h2>
<p>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:</p>
<pre><code>DECLARE SUB name ([BYVAL] [OPTIONAL] param AS type, ...)
DECLARE FUNCTION name ([BYVAL] [OPTIONAL] param AS type, ...) AS returnType</code></pre>
<p>A DECLARE must match the SUB or FUNCTION it declares: the same parameter types, BYVAL and OPTIONAL flags, and return type.</p>
<h2>DECLARE LIBRARY</h2>
<p>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.</p>
<pre><code>DECLARE LIBRARY &quot;libraryName&quot;
DECLARE SUB name ([BYVAL] param AS type, ...)
DECLARE FUNCTION name ([BYVAL] param AS type, ...) AS returnType
END DECLARE</code></pre>
<pre><code>Declare Library &quot;basrt&quot;
Declare Function SQLOpen(ByVal path As String) As Long
Declare Sub SQLClose(ByVal db As Long)
End Declare</code></pre>
<p>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.</p>
<p><a href="#lang.runtime">See also: BASIC Runtime Libraries</a></p>
<h2>STATIC</h2>
<p>Declares a local variable that retains its value between calls.</p>
<pre><code>STATIC variable AS type</code></pre>
<pre><code>Sub Counter()
Static count As Integer
count = count + 1
Print count
End Sub</code></pre>
<h2>OPTION</h2>
<p>Sets compiler options. Must appear before any executable code.</p>
<pre><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</code></pre>
<h2>DEFtype Statements</h2>
<p>Set the default type for variables based on their first letter.</p>
<pre><code>DEFINT letterRange
DEFLNG letterRange
DEFSNG letterRange
DEFDBL letterRange
DEFSTR letterRange</code></pre>
<pre><code>DefInt I-N ' Variables starting with I through N default to Integer
DefStr S ' Variables starting with S default to String</code></pre>
<h2>Assignment</h2>
<p>Assigns a value to a variable, array element, or UDT field.</p>
<pre><code>variable = expression
array(index) = expression
udt.field = expression
LET variable = expression</code></pre>
<p>The LET keyword is optional and supported for compatibility.</p>
<h2>SWAP</h2>
<p>Exchanges the values of two variables or array elements. The two operands should be the same type.</p>
<pre><code>SWAP variable1, variable2
SWAP array(index), variable</code></pre>
<pre><code>Swap a, b
Swap names(i), names(j)</code></pre>
<h2>SET</h2>
<p>Assigns an object reference (form or control) to a variable. Required when creating a form or control with CreateForm / CreateControl so that the returned reference is stored in the variable:</p>
<pre><code>SET variable = objectExpression</code></pre>
<pre><code>Dim frm As Long
Set frm = CreateForm(&quot;MyForm&quot;, 320, 240)
frm.Caption = &quot;Built in code&quot;</code></pre>
<p>For ordinary numeric or string assignment, SET is not used.</p>
<h2>ERASE</h2>
<p>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.</p>
<pre><code>ERASE arrayName</code></pre>
</div>
<div class="topic" id="lang.conditionals">
<h1>Conditional Statements</h1>
<h2>IF...THEN...ELSE...END IF</h2>
<p>Conditional execution. Supports single-line and multi-line forms.</p>
<h3>Single-line form</h3>
<pre><code>IF condition THEN statement
IF condition THEN statement ELSE statement</code></pre>
<h3>Multi-line form</h3>
<pre><code>IF condition THEN
statements
ELSEIF condition THEN
statements
ELSE
statements
END IF</code></pre>
<pre><code>If x &gt; 10 Then
Print &quot;Large&quot;
ElseIf x &gt; 5 Then
Print &quot;Medium&quot;
Else
Print &quot;Small&quot;
End If
If ready Then Print &quot;Go!&quot;</code></pre>
<h2>SELECT CASE</h2>
<p>Multi-way branch based on an expression value.</p>
<pre><code>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</code></pre>
<pre><code>Select Case grade
Case 90 To 100
Print &quot;A&quot;
Case 80 To 89
Print &quot;B&quot;
Case Is &gt;= 70
Print &quot;C&quot;
Case 60, 65
Print &quot;D (borderline)&quot;
Case Else
Print &quot;F&quot;
End Select</code></pre>
<p>CASE items can be combined with commas. The IS keyword allows comparison operators: &lt;, &gt;, &lt;=, &gt;=, =, &lt;&gt;.</p>
</div>
<div class="topic" id="lang.loops">
<h1>Loop Statements</h1>
<h2>FOR...NEXT</h2>
<p>Counted loop with an optional step value.</p>
<pre><code>FOR variable = start TO limit [STEP step]
statements
NEXT [variable]</code></pre>
<pre><code>For i = 1 To 10
Print i
Next i
For x = 10 To 0 Step -2
Print x
Next</code></pre>
<p>The variable name after NEXT is optional. Use EXIT FOR to break out early.</p>
<p>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.</p>
<h2>DO...LOOP</h2>
<p>General-purpose loop with pre-test, post-test, or infinite forms.</p>
<pre><code>DO [WHILE condition | UNTIL condition]
statements
LOOP [WHILE condition | UNTIL condition]</code></pre>
<pre><code>' Pre-test
Do While count &lt; 10
count = count + 1
Loop
' Post-test
Do
line$ = ReadLine()
Loop Until line$ = &quot;quit&quot;
' Infinite loop (exit with EXIT DO)
Do
DoEvents
If done Then Exit Do
Loop</code></pre>
<h2>WHILE...WEND</h2>
<p>Simple pre-test loop (legacy form; prefer DO...LOOP).</p>
<pre><code>WHILE condition
statements
WEND</code></pre>
<pre><code>While Not EOF(1)
Line Input #1, line$
Print line$
Wend</code></pre>
</div>
<div class="topic" id="lang.procedures">
<h1>Procedures</h1>
<h2>SUB...END SUB</h2>
<p>Defines a subroutine (no return value).</p>
<pre><code>SUB name ([BYVAL | BYREF] [OPTIONAL] param AS type, ...)
SUB name (arrayParam() AS type, ...)
statements
END SUB</code></pre>
<pre><code>Sub Greet(ByVal name As String)
Print &quot;Hello, &quot; &amp; name
End Sub</code></pre>
<p>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. Writes to a by-reference parameter update the caller's variable, including individual array elements: `bump a(3)` passed to a by-reference parameter will modify `a(3)` in place. 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:</p>
<pre><code>Greet &quot;World&quot;
Greet(&quot;World&quot;)
Call Greet(&quot;World&quot;)</code></pre>
<pre><code>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</code></pre>
<h3>Optional Parameters</h3>
<p>Mark a parameter OPTIONAL to allow callers to omit it. An optional parameter must be positioned after all required parameters and receives an empty/zero default when not supplied.</p>
<pre><code>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 &quot;hello&quot; ' loud defaults to 0
Announce &quot;hello&quot;, True ' loud is -1</code></pre>
<h2>FUNCTION...END FUNCTION</h2>
<p>Defines a function with a return value.</p>
<pre><code>FUNCTION name ([BYVAL] [OPTIONAL] param AS type, ...) AS returnType
statements
name = returnValue
END FUNCTION</code></pre>
<pre><code>Function Square(ByVal n As Double) As Double
Square = n * n
End Function</code></pre>
<p>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.</p>
<p>A FUNCTION can also be called as a statement, with or without parentheses; its result is discarded:</p>
<pre><code>Function Beep2(ByVal n As Integer) As Integer
Beep2 = n * 2
End Function
Beep2 3 ' result discarded</code></pre>
<p>name(...) in an expression calls a FUNCTION; using a SUB there is a compile error.</p>
<h3>Labels, GOSUB and Variables in Procedures</h3>
<p>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.</p>
<h2>DEF FN</h2>
<p>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.</p>
<pre><code>DEF FNname(params) = expression</code></pre>
<pre><code>Def FnSquare(x) = x * x
Print FnSquare(5) ' prints 25
Def FnCelsius(f As Double) = (f - 32) * 5 / 9
Print FnCelsius(212) ' prints 100</code></pre>
</div>
<div class="topic" id="lang.flow">
<h1>Flow Control</h1>
<h2>EXIT</h2>
<p>Exits the current block early.</p>
<pre><code>EXIT FOR
EXIT DO
EXIT SUB
EXIT FUNCTION</code></pre>
<h2>CALL</h2>
<p>Explicitly calls a subroutine or function. The return value (if any) is discarded.</p>
<pre><code>CALL name
CALL name(args)</code></pre>
<p>Normally you can omit CALL and just use the name directly.</p>
<h2>GOTO / GOSUB / RETURN</h2>
<pre><code>GOTO label
GOSUB label
RETURN</code></pre>
<p>A label is a name followed by a colon at the start of a line. 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.</p>
<p>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.</p>
<pre><code>GoSub Initialize
Print &quot;Done&quot;
End
Initialize:
count = 0
name$ = &quot;&quot;
Return</code></pre>
<pre><code>Sub Report(n As Integer)
GoSub Heading
Print &quot;value&quot;; n
Exit Sub
Heading:
Print &quot;--- report ---&quot;
Return
End Sub</code></pre>
<h2>ON...GOTO / ON...GOSUB</h2>
<p>Computed branch based on an integer expression.</p>
<pre><code>ON expression GOTO label1, label2, ...
ON expression GOSUB label1, label2, ...</code></pre>
<p>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).</p>
</div>
<div class="topic" id="lang.io">
<h1>Input/Output Statements</h1>
<h2>PRINT</h2>
<p>Writes expressions to the output window (or to a file channel).</p>
<pre><code>PRINT [expression [{; | ,} expression] ...]
PRINT #channel, expression [; expression] ...
PRINT USING format$; expression [; expression] ...</code></pre>
<ul>
<li>; between items -- no separator (items appear next to each other, or separated by a space for numbers)</li>
<li>, between items -- advance to the next 14-column tab zone</li>
<li>A trailing ; or , suppresses the newline normally written at the end of the statement (PRINT USING and PRINT # too)</li>
<li>? is an alias for PRINT</li>
</ul>
<p>PRINT # writes numbers exactly as PRINT shows them, with the space after each number, so PRINT #1, 1; 2 writes &quot;1 2 &quot;. PRINT #n, with nothing after the comma writes an empty line.</p>
<p>Special functions inside PRINT:</p>
<ul>
<li>SPC(n) -- print n spaces</li>
<li>TAB(n) -- advance to column n (first column is 1); when the cursor is already past column n, a new line is started first</li>
</ul>
<pre><code>Print &quot;Name:&quot;; Tab(20); name$
Print &quot;X=&quot;; x, &quot;Y=&quot;; y ' comma = next 14-column zone
Print #1, &quot;Written to file&quot;</code></pre>
<h2>LPRINT</h2>
<p>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.</p>
<pre><code>LPRINT [expression [{; | ,} expression] ...]
LPRINT USING format$; expression [; expression] ...</code></pre>
<p>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.</p>
<pre><code>LPrint &quot;Invoice&quot;; Tab(40); Date$
LPrint Using &quot;Total: $$####.##&quot;; total
LPrint Chr$(12) ' eject the page</code></pre>
<p>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).</p>
<h3>PRINT USING</h3>
<p>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.</p>
<pre> 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
&amp; Entire string (variable length)
\ ... \ Fixed-length string field (width = 2 + number of spaces between backslashes)
_ The next character is printed literally</pre>
<p>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.</p>
<pre><code>Print Using &quot;###.##&quot;; -3.14159 ' &quot; -3.14&quot;
Print Using &quot;+###&quot;; 42 ' &quot; +42&quot;
Print Using &quot;$$#,##0.00&quot;; 1234.5 ' &quot; $1,234.50&quot;
Print Using &quot;**#,##0.00&quot;; 42.5 ' &quot;*****42.50&quot;
Print Using &quot;###&quot;; 12345 ' &quot;%12345&quot;
Print Using &quot;####.####^^^^&quot;; 0.000123 ' scientific notation
Print Using &quot;\ \&quot;; &quot;Hello&quot; ' fixed-width 4-char: &quot;Hell&quot;
Print Using &quot;&amp; likes &amp;&quot;; name$; food$ ' &quot;Scott likes pizza&quot;
Print Using &quot;Total: ###.## units&quot;; 7.5 ' &quot;Total: 7.50 units&quot;
Print Using &quot;## and ##&quot;; 1; 2; 3 ' &quot; 1 and 2 3 and &quot;</code></pre>
<h2>INPUT</h2>
<p>Reads a line of text from the user or from a file channel.</p>
<pre><code>INPUT variable
INPUT &quot;prompt&quot;; variable
INPUT #channel, variable</code></pre>
<pre><code>Input &quot;Enter your name: &quot;; name$
Input #1, line$</code></pre>
<p>The target may be a variable, an array element or a TYPE field (INPUT, INPUT #, LINE INPUT # and READ alike).</p>
<h2>DATA / READ / RESTORE</h2>
<p>Inline data pool for constants.</p>
<pre><code>DATA value1, value2, &quot;string&quot;, ...
READ variable1, variable2, ...
RESTORE</code></pre>
<p>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. 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. The most negative Integer and Long values (-32768, -2147483648) are accepted.</p>
<pre><code>Data 10, 20, 30, &quot;Hello&quot;
Read a, b, c, msg$
Print a; b; c; msg$
Restore</code></pre>
</div>
<div class="topic" id="lang.misc">
<h1>Miscellaneous Statements</h1>
<h2>Error Handling</h2>
<pre><code>ON ERROR GOTO label ' Enable error handler
ON ERROR GOTO 0 ' Disable error handler
RESUME ' Retry the statement that caused the error
RESUME NEXT ' Continue at the next statement after the error
ERROR n ' Raise a runtime error with error number n</code></pre>
<p>The ERR keyword returns the current error number (a Long) in expressions and ERL the source line the error was raised on (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 &quot;Division by zero&quot;); numbers without a standard message report &quot;User-defined error&quot;.</p>
<p>Each SUB and FUNCTION has its own ON ERROR handler:</p>
<ul>
<li>An error is handled by the handler of the procedure it happens in; if that procedure has none, the calling procedures are searched outward.</li>
<li>A procedure called from a running handler can trap its own errors with its own handler.</li>
<li>Returning from a procedure that merely installed a handler leaves the caller's ERR and handler alone.</li>
<li>An error raised inside a running handler passes to the calling procedure's handler (untrapped if there is none).</li>
<li>The label named by ON ERROR GOTO must be in the same procedure.</li>
</ul>
<p>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.</p>
<pre><code>On Error GoTo ErrorHandler
Open &quot;missing.txt&quot; For Input As #1
Exit Sub
ErrorHandler:
Print &quot;Error number:&quot;; Err; &quot;on line&quot;; Erl
Resume Next</code></pre>
<h3>Common Error Numbers</h3>
<pre> 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
11 Division by zero
13 Type mismatch / 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)
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)
1000 No form runtime (a form or control statement ran without the form runtime, e.g. under a headless runner)</pre>
<h2>SHELL</h2>
<p>Executes an operating-system command.</p>
<pre><code>SHELL &quot;command&quot;</code></pre>
<p>When used as a function, SHELL returns the exit code of the command.</p>
<pre><code>Shell &quot;DIR /B&quot;
exitCode = Shell(&quot;COPY A.TXT B.TXT&quot;)</code></pre>
<h2>SLEEP</h2>
<p>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.</p>
<pre><code>SLEEP [seconds]</code></pre>
<h2>RANDOMIZE</h2>
<p>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.</p>
<pre><code>RANDOMIZE seed
RANDOMIZE TIMER ' Seed from system clock</code></pre>
<h2>END</h2>
<p>Terminates program execution immediately. Any form that is loaded is unloaded before the program exits.</p>
<pre><code>END</code></pre>
</div>
<div class="topic" id="lang.sound">
<h1>Sound, Joysticks and Frames</h1>
<p>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.</p>
<h2>BEEP</h2>
<p>Sounds a short beep (800 hertz for a quarter of a second).</p>
<pre><code>BEEP</code></pre>
<h2>SOUND</h2>
<p>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).</p>
<pre><code>SOUND frequency, duration
SOUND 440, 18.2 ' A for one second
SOUND 440, 0 ' stop</code></pre>
<h2>PLAY</h2>
<p>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.</p>
<pre><code>PLAY commands$
PLAY &quot;T160 O3 L8 E D C D E E E4&quot;</code></pre>
<pre> 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.
&gt; and &lt; 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).</pre>
<p>A string with a mistake in it plays nothing and raises error 5 (Illegal function call). QBasic's X command (play a string variable) and the &quot;=&quot; form of numbers are not supported; build the string with + instead, such as PLAY &quot;O&quot; + 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.</p>
<pre><code>PLAY &quot;MB T120 L4 CDEF GAB&gt;C&quot; ' a scale in the background
PLAY &quot;I74 O4 L8 GAB&gt;C&quot; ' on the flute</code></pre>
<h2>PLAY Function</h2>
<p>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:</p>
<pre><code>If PLAY(0) &lt; 4 Then PLAY &quot;MB &quot; + tune$</code></pre>
<h2>STICK and STRIG</h2>
<p>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.</p>
<p>STRIG(n) returns True (-1) or False (0) for the buttons:</p>
<pre> 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</pre>
<p>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.</p>
<pre><code>x = STICK(0)
y = STICK(1)
If STRIG(0) Then FireShot</code></pre>
<h2>FRAMEWAIT</h2>
<p>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.</p>
<pre><code>FRAMEWAIT rate
Do
MoveEverything
DrawEverything
FRAMEWAIT 30
Loop Until quitting</code></pre>
</div>
<div class="topic" id="lang.fileio">
<h1>File I/O</h1>
<h2>OPEN</h2>
<p>Opens a file for reading, writing, or appending.</p>
<pre><code>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</code></pre>
<pre> 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.</pre>
<h3>Printing Through OPEN</h3>
<p>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.</p>
<pre><code>Open &quot;LPT1:&quot; For Output As #1
Print #1, &quot;Line one&quot;
Print #1, &quot;Line two&quot;
Close #1 ' now it prints</code></pre>
<h2>CLOSE</h2>
<p>Closes an open file channel.</p>
<pre><code>CLOSE #channel</code></pre>
<h2>PRINT #</h2>
<p>Writes text to a file, formatted exactly as PRINT shows it (numbers are followed by a space). See PRINT.</p>
<pre><code>PRINT #channel, expression</code></pre>
<h2>INPUT #</h2>
<p>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.</p>
<pre><code>INPUT #channel, variable [, variable ...]</code></pre>
<pre><code>Open &quot;data.txt&quot; For Input As #1
Input #1, name$, age%, score#
Close #1</code></pre>
<h2>LINE INPUT #</h2>
<p>Reads an entire line from a file into a string variable.</p>
<pre><code>LINE INPUT #channel, variable$</code></pre>
<h2>WRITE #</h2>
<p>Writes comma-delimited data to a file. Strings are enclosed in quotes, numbers are undecorated. Each statement writes a newline at the end.</p>
<pre><code>WRITE #channel, expr1, expr2, ...</code></pre>
<pre><code>Write #1, &quot;Scott&quot;, 42, 3.14
' Output: &quot;Scott&quot;,42,3.14</code></pre>
<h2>GET / PUT</h2>
<p>Read and write records in RANDOM or BINARY mode files. When recordNum is omitted the transfer starts at the current file position.</p>
<pre><code>GET #channel, [recordNum], variable
PUT #channel, [recordNum], variable</code></pre>
<p>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 (Integer and Boolean 2 bytes, Long 4, Single 4, Double 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.</p>
<p>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).</p>
<p>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.</p>
<p>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.</p>
<pre><code>Type RecT
id As Integer
score As Double
nm As String * 6
End Type
Dim r As RecT
Open &quot;recs.dat&quot; 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</code></pre>
<pre><code>Dim buf As String
Open &quot;raw.bin&quot; For Binary As #1
buf = Space$(16)
Get #1, 1, buf ' read bytes 1-16
Put #1, 33, &quot;TAG&quot; ' write 3 bytes at position 33
Close #1</code></pre>
<h2>SEEK</h2>
<p>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).</p>
<pre><code>SEEK #channel, position ' Statement: set position
pos = SEEK(channel) ' Function: get current position</code></pre>
</div>
<div class="topic" id="lang.filesystem">
<h1>File System Statements</h1>
<p>DVX BASIC provides statements for working with the file system -- creating, deleting, renaming, and copying files and directories, and reading or setting file attributes.</p>
<h2>KILL</h2>
<p>Deletes a file.</p>
<pre><code>KILL filename$</code></pre>
<pre><code>Kill &quot;temp.bak&quot;</code></pre>
<h2>NAME ... AS</h2>
<p>Renames (or moves) a file.</p>
<pre><code>NAME oldName$ AS newName$</code></pre>
<pre><code>Name &quot;draft.txt&quot; As &quot;final.txt&quot;</code></pre>
<h2>FILECOPY</h2>
<p>Copies a file. If the destination already exists it is overwritten.</p>
<pre><code>FILECOPY source$, destination$</code></pre>
<pre><code>FileCopy &quot;data.db&quot;, &quot;data.bak&quot;</code></pre>
<h2>MKDIR / RMDIR</h2>
<p>Creates or removes a directory.</p>
<pre><code>MKDIR path$
RMDIR path$</code></pre>
<pre><code>MkDir App.Data &amp; &quot;\backups&quot;
RmDir &quot;C:\OLD&quot;</code></pre>
<h2>CHDIR / CHDRIVE</h2>
<p>Changes the current working directory or drive.</p>
<pre><code>CHDIR path$
CHDRIVE drive$</code></pre>
<pre><code>ChDir &quot;C:\DVX\PROJECTS&quot;
ChDrive &quot;D&quot;</code></pre>
<h2>GETATTR / SETATTR</h2>
<p>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.</p>
<pre><code>attrs = GETATTR(filename$)
SETATTR filename$, attrs</code></pre>
<pre> 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</pre>
<pre><code>If (GetAttr(&quot;readme.txt&quot;) And vbReadOnly) &lt;&gt; 0 Then
Print &quot;File is read-only.&quot;
End If
SetAttr &quot;secret.dat&quot;, vbHidden + vbReadOnly</code></pre>
<h2>CURDIR$ / DIR$</h2>
<p>CURDIR$ returns the current directory. DIR$ returns the first file matching a pattern; subsequent calls with no arguments return additional matches (or &quot;&quot; when done). DIR$ returns only files: never &quot;.&quot;, &quot;..&quot; or subdirectories.</p>
<pre><code>cwd$ = CURDIR$
first$ = DIR$(&quot;*.txt&quot;)
WHILE first$ &lt;&gt; &quot;&quot;
Print first$
first$ = DIR$ ' next match, no argument
WEND</code></pre>
<h2>FILELEN</h2>
<p>Returns the length of a file in bytes. A file that does not exist raises error 53 (File not found).</p>
<pre><code>bytes = FILELEN(filename$)</code></pre>
</div>
<div class="topic" id="lang.func.string">
<h1>String Functions</h1>
<pre> Function Returns Description
-------- ------- -----------
ASC(s$) Integer ASCII code of the first character of s$
CHR$(n) String Character with ASCII code n
FORMAT$(value, fmt$) String Formats a numeric value using a format string
HEX$(n) String Hexadecimal representation of n (uppercase, no leading &amp;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)
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 &amp;O)
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)
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)
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</pre>
<p>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.</p>
<h2>FORMAT$</h2>
<p>FORMAT$ formats a numeric value using a BASIC-style format string. The format characters are the same as the ones used by PRINT USING.</p>
<pre><code>s$ = FORMAT$(value, fmt$)</code></pre>
<pre><code>Print Format$(3.14159, &quot;###.##&quot;) ' &quot; 3.14&quot;
Print Format$(-7, &quot;+###&quot;) ' &quot; -7&quot;
Print Format$(42, &quot;00000&quot;) ' &quot;00042&quot;
Print Format$(1234.5, &quot;#,##0.00&quot;) ' &quot;1,234.50&quot;
Print Format$(5, &quot;#,##0.00&quot;) ' &quot; 5.00&quot;
Print Format$(0.5, &quot;PERCENT&quot;) ' &quot;50%&quot;</code></pre>
<p>The whole format string is one numeric field. 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.</p>
<h2>MID$ Assignment</h2>
<p>MID$ can also be used on the left side of an assignment to replace a portion of a string without changing its length:</p>
<pre><code>Mid$(s$, start [, length]) = replacement$</code></pre>
<pre><code>Dim s$
s$ = &quot;Hello, World!&quot;
Mid$(s$, 8, 5) = &quot;DVX--&quot;
Print s$ ' Hello, DVX--!</code></pre>
<p>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).</p>
</div>
<div class="topic" id="lang.func.math">
<h1>Math Functions</h1>
<pre> 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 &lt;= RND &lt; 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</pre>
<p>RND follows QBasic: RND or RND(n) with n &gt; 0 returns the next number in the sequence, RND(0) repeats the last number, and RND(n) with n &lt; 0 reseeds the generator from n (the same n always gives the same number). The result is a Double, 0 &lt;= RND &lt; 1.</p>
<p>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).</p>
<blockquote><strong>Note:</strong> Use RANDOMIZE or RANDOMIZE TIMER to seed the generator so you don't get the same sequence each run.</blockquote>
<h2>Color Functions</h2>
<p>The color functions work with 24-bit RGB colors packed into a Long.</p>
<pre> Function Returns Description
-------- ------- -----------
RGB(r, g, b) Long Combine red, green, and blue components (0-255) into a 24-bit color
GETRED(color) Integer Red component (0-255) of a color built with RGB
GETGREEN(color) Integer Green component (0-255) of a color built with RGB
GETBLUE(color) Integer Blue component (0-255) of a color built with RGB</pre>
<pre><code>Dim c As Long
c = RGB(255, 128, 0) ' bright orange
Print GetRed(c); GetGreen(c); GetBlue(c) ' 255 128 0
Me.BackColor = RGB(0, 0, 128) ' dark blue background</code></pre>
</div>
<div class="topic" id="lang.func.conversion">
<h1>Conversion Functions</h1>
<pre> Function Returns Description
-------- ------- -----------
CBOOL(n) Boolean Returns True (-1) if n is nonzero or a non-empty string; False (0) otherwise
CDBL(n) Double Converts n to Double
CINT(n) Integer Converts n to Integer; halves round to the nearest even number (2.5 -&gt; 2, 3.5 -&gt; 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</pre>
</div>
<div class="topic" id="lang.func.fileio">
<h1>File I/O Functions</h1>
<pre> 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
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 &quot;&quot;
DIR$ String Next match from the last DIR$(pattern$), or &quot;&quot; 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)</pre>
<p>The dim argument of LBOUND and UBOUND must be a constant from 1 to 8.</p>
</div>
<div class="topic" id="lang.func.misc">
<h1>Miscellaneous Functions</h1>
<pre> Function Returns Description
-------- ------- -----------
DATE$ String Current date as &quot;MM-DD-YYYY&quot;
TIME$ String Current time as &quot;HH:MM:SS&quot; (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)</pre>
<h2>COMMAND$</h2>
<p>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:</p>
<pre><code>IF COMMAND$(1) &lt;&gt; &quot;&quot; THEN
OpenFile COMMAND$(1)
END IF</code></pre>
<p>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).</p>
</div>
<div class="topic" id="lang.forms">
<h1>Form and Control Statements</h1>
<p>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.</p>
<h2>Loading and Unloading Forms</h2>
<pre><code>LOAD FormName
UNLOAD FormName
UNLOAD Me</code></pre>
<p>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.</p>
<h2>Showing and Hiding Forms</h2>
<pre><code>FormName.Show [mode]
FormName.Hide
Me.Show [mode]
Me.Hide</code></pre>
<p>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.</p>
<pre><code>Form2.Show vbModal
Me.Hide</code></pre>
<h2>Property Access</h2>
<p>Read and write control properties using dot notation:</p>
<pre><code>ControlName.Property = value
value = ControlName.Property</code></pre>
<pre><code>Text1.Text = &quot;Hello&quot;
Label1.Caption = &quot;Name: &quot; &amp; name$
x = Text1.Left</code></pre>
<p>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.</p>
<p>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.</p>
<pre><code>Form2.Label1.Caption = &quot;From Form1&quot;
total = Form2.List1.ListCount
Form2.List1.Clear</code></pre>
<h2>Method Calls</h2>
<pre><code>ControlName.Method [args]</code></pre>
<pre><code>List1.AddItem &quot;New entry&quot;
List1.Clear</code></pre>
<h2>Me Keyword</h2>
<p>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.</p>
<pre><code>Me.Caption = &quot;Updated Title&quot;
Me.Text1.Text = &quot;&quot;
Me.Hide</code></pre>
<h2>Nothing</h2>
<p>Nothing is a null object reference. Assign it to an object-typed variable to indicate &quot;no object&quot;.</p>
<pre><code>Set myCtrl = Nothing</code></pre>
<h2>Control Arrays</h2>
<p>Multiple controls can share a name with unique indices. Access individual controls with parenthesized indices:</p>
<pre><code>Option1(0).Value = True
Label1(idx).Caption = &quot;Item &quot; &amp; Str$(idx)
Me.Label1(i).Visible = True</code></pre>
<h2>WITH</h2>
<p>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.</p>
<pre><code>WITH ControlName
.Property1 = value1
.Property2 = value2
.Method arg1, arg2
END WITH</code></pre>
<pre><code>With Label1
.Caption = &quot;Status: Ready&quot;
.ForeColor = RGB(0, 128, 0)
.Visible = True
End With</code></pre>
<h2>Building Forms in Code</h2>
<p>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.</p>
<h3>CreateForm</h3>
<pre><code>SET formVar = CreateForm(name$, width%, height%)</code></pre>
<p>Creates a new form with the given name and initial size. Returns a form reference.</p>
<h3>CreateControl</h3>
<pre><code>SET ctrlVar = CreateControl(formRef, typeName$, ctrlName$ [, parentCtrlRef])</code></pre>
<p>Creates a control on the given form. typeName$ is the control type (e.g. &quot;CommandButton&quot;, &quot;Label&quot;, &quot;TextBox&quot;). 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.</p>
<h3>SetEvent</h3>
<pre><code>SETEVENT ctrlRef, eventName$, handlerName$</code></pre>
<p>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.</p>
<h3>RemoveControl</h3>
<pre><code>REMOVECONTROL formRef, ctrlName$</code></pre>
<p>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.</p>
<pre><code>Dim frm As Long
Dim lbl As Long
Set frm = CreateForm(&quot;MyDlg&quot;, 300, 200)
frm.Caption = &quot;Built in code&quot;
Set lbl = CreateControl(frm, &quot;Label&quot;, &quot;StatusLabel&quot;)
StatusLabel.Caption = &quot;Hello, world!&quot;
Dim btn As Long
Set btn = CreateControl(frm, &quot;CommandButton&quot;, &quot;BtnClose&quot;)
BtnClose.Caption = &quot;Close&quot;
SetEvent btn, &quot;Click&quot;, &quot;OnCloseClick&quot;
frm.Show
Sub OnCloseClick
Unload Me
End Sub</code></pre>
<h2>DoEvents</h2>
<p>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).</p>
<pre><code>DOEVENTS</code></pre>
<pre><code>For i = 1 To 10000
' process data
If i Mod 100 = 0 Then DoEvents
Next</code></pre>
<h2>MsgBox</h2>
<p>Displays a message-box dialog. Can be used as a statement (discards the result) or as a function (returns the button clicked).</p>
<pre><code>MSGBOX message$ [, flags [, title$]]
result = MSGBOX(message$ [, flags [, title$]])</code></pre>
<p>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).</p>
<pre><code>MsgBox &quot;Operation complete&quot;
answer = MsgBox(&quot;Continue?&quot;, vbYesNo + vbQuestion, &quot;Confirm&quot;)
If answer = vbYes Then
' proceed
End If</code></pre>
<h2>InputBox$</h2>
<p>Displays an input dialog and returns the user's text entry. Returns an empty string if the user cancels.</p>
<pre><code>result$ = INPUTBOX$(prompt$ [, title$ [, default$]])</code></pre>
<pre><code>name$ = InputBox$(&quot;Enter your name:&quot;, &quot;Name Entry&quot;, &quot;&quot;)
If name$ &lt;&gt; &quot;&quot; Then
Print &quot;Hello, &quot;; name$
End If</code></pre>
<h2>Event Handler Convention</h2>
<p>Event handlers are named ControlName_EventName and defined as SUBs:</p>
<pre><code>Sub Command1_Click()
MsgBox &quot;Button clicked!&quot;
End Sub
Sub Form_Load()
Me.Caption = &quot;My App&quot;
End Sub
Sub Text1_Change()
Label1.Caption = &quot;You typed: &quot; &amp; Text1.Text
End Sub</code></pre>
<h3>Common Events</h3>
<pre> 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)</pre>
</div>
<div class="topic" id="lang.sql">
<h1>SQL Functions</h1>
<p>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.</p>
<h2>Opening and Closing Databases</h2>
<h3>SQLOpen</h3>
<p>Opens a SQLite database file and returns a database handle (&gt; 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.</p>
<pre><code>db = SQLOpen(path$)</code></pre>
<pre><code>db = SQLOpen(App.Data &amp; &quot;\mydata.db&quot;)</code></pre>
<h3>SQLClose</h3>
<p>Closes an open database.</p>
<pre><code>SQLClose db</code></pre>
<h2>Executing SQL</h2>
<h3>SQLExec</h3>
<p>Executes a SQL statement that does not return data (INSERT, UPDATE, DELETE, CREATE TABLE, etc.). Returns True on success.</p>
<pre><code>ok = SQLExec(db, sql$)</code></pre>
<pre><code>SQLExec db, &quot;CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)&quot;
SQLExec db, &quot;INSERT INTO users (name) VALUES ('Scott')&quot;
ok = SQLExec(db, &quot;DELETE FROM users WHERE id = 5&quot;)</code></pre>
<p>Put text values in single quotes, as in the examples. Text in double quotes is read as a column name, so &quot;Scott&quot; in place of 'Scott' gives the error &quot;no such column: Scott&quot;.</p>
<h3>SQLAffected</h3>
<p>Returns the number of rows affected by the last INSERT, UPDATE, or DELETE.</p>
<pre><code>count = SQLAffected(db)</code></pre>
<h2>Querying Data</h2>
<h3>SQLQuery</h3>
<p>Executes a SELECT query and returns a result-set cursor.</p>
<pre><code>rs = SQLQuery(db, sql$)</code></pre>
<pre><code>rs = SQLQuery(db, &quot;SELECT id, name FROM users ORDER BY name&quot;)</code></pre>
<h3>SQLNext</h3>
<p>Advances the cursor to the next row. Returns True if a row is available, False when there are no more rows.</p>
<pre><code>hasRow = SQLNext(rs)</code></pre>
<h3>SQLEof</h3>
<p>Returns True if the cursor is past the last row.</p>
<pre><code>done = SQLEof(rs)</code></pre>
<h2>Reading Fields</h2>
<h3>SQLField$ / SQLFieldText$</h3>
<p>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.</p>
<pre><code>value$ = SQLField$(rs, columnName$)
value$ = SQLFieldText$(rs, columnIndex)</code></pre>
<pre><code>name$ = SQLField$(rs, &quot;name&quot;)
first$ = SQLFieldText$(rs, 0)</code></pre>
<h3>SQLFieldName$</h3>
<p>Returns the column name for a given 0-based column index.</p>
<pre><code>colName$ = SQLFieldName$(rs, columnIndex)</code></pre>
<h3>SQLFieldInt</h3>
<p>Returns a field value as a Long integer.</p>
<pre><code>value = SQLFIELDINT(rs, columnIndex)</code></pre>
<h3>SQLFieldDbl</h3>
<p>Returns a field value as a double.</p>
<pre><code>value# = SQLFIELDDBL(rs, columnIndex)</code></pre>
<h3>SQLFieldCount</h3>
<p>Returns the number of columns in the result set.</p>
<pre><code>count = SQLFieldCount(rs)</code></pre>
<h2>Result Set Cleanup</h2>
<h3>SQLFreeResult</h3>
<p>Frees a result-set cursor. Always call this when finished iterating a query.</p>
<pre><code>SQLFreeResult rs</code></pre>
<h2>Error Information</h2>
<h3>SQLError$</h3>
<p>Returns the last error message for the database.</p>
<pre><code>msg$ = SQLError$(db)</code></pre>
<p>When a database file could not be opened, read or written, the message ends with the reason in parentheses, for example &quot;unable to open database file (No such file or directory)&quot;. If another program, or another handle in your own program, is changing the same database at that moment, the message is &quot;database is locked&quot;: 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.</p>
<h2>Complete SQL Example</h2>
<pre><code>Dim db As Long
Dim rs As Long
db = SQLOpen(App.Data &amp; &quot;\contacts.db&quot;)
SQLExec db, &quot;CREATE TABLE IF NOT EXISTS contacts (name TEXT, phone TEXT)&quot;
SQLExec db, &quot;INSERT INTO contacts VALUES ('Alice', '555-1234')&quot;
rs = SQLQuery(db, &quot;SELECT name, phone FROM contacts&quot;)
Do While SQLNext(rs)
Print SQLField$(rs, &quot;name&quot;); Tab(20); SQLField$(rs, &quot;phone&quot;)
Loop
SQLFreeResult rs
SQLClose db</code></pre>
</div>
<div class="topic" id="lang.app">
<h1>App Object</h1>
<p>The App object provides read-only properties for the application's directory paths.</p>
<pre> 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.)</pre>
<pre><code>configFile$ = App.Config &amp; &quot;\settings.ini&quot;
dbPath$ = App.Data &amp; &quot;\myapp.db&quot;
Print &quot;Running from: &quot; &amp; App.Path</code></pre>
</div>
<div class="topic" id="lang.ini">
<h1>INI Functions</h1>
<p>DVX BASIC provides built-in functions for reading and writing standard INI configuration files (the same text format used by DVX system configuration).</p>
<h2>IniRead</h2>
<p>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 &quot;&quot; (an empty section name). Lines starting with ; or # are comments.</p>
<pre><code>value$ = IniRead(file$, section$, key$, default$)</code></pre>
<pre><code>name$ = IniRead(App.Config &amp; &quot;\app.ini&quot;, &quot;User&quot;, &quot;Name&quot;, &quot;Unknown&quot;)
fontSize = Val(IniRead(App.Config &amp; &quot;\app.ini&quot;, &quot;Display&quot;, &quot;FontSize&quot;, &quot;12&quot;))</code></pre>
<h2>IniWrite</h2>
<p>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.</p>
<pre><code>INIWRITE file$, section$, key$, value$</code></pre>
<pre><code>IniWrite App.Config &amp; &quot;\app.ini&quot;, &quot;User&quot;, &quot;Name&quot;, &quot;Scott&quot;
IniWrite App.Config &amp; &quot;\app.ini&quot;, &quot;Display&quot;, &quot;FontSize&quot;, Str$(fontSize)</code></pre>
</div>
<div class="topic" id="lang.constants">
<h1>Predefined Constants</h1>
<p>The following constants are predefined by the compiler and available in all programs. No DIM or CONST declaration is required to use them.</p>
<h2>MsgBox Button Style Flags</h2>
<pre> 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</pre>
<h2>MsgBox Icon Flags</h2>
<p>Add an icon flag to the button style (with + or OR) to display an icon in the message box.</p>
<pre> Constant Value Description
-------- ----- -----------
vbInformation &amp;H10 Information icon (i)
vbExclamation &amp;H20 Warning icon (!)
vbCritical &amp;H30 Error/critical icon (X)
vbQuestion &amp;H40 Question icon (?)</pre>
<h2>MsgBox Return Values</h2>
<pre> 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</pre>
<h2>Show Mode Flags</h2>
<pre> Constant Value Description
-------- ----- -----------
vbModal 1 Show form as modal dialog</pre>
<h2>File Attribute Flags</h2>
<p>Bit values used with GETATTR and SETATTR.</p>
<pre> 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</pre>
<h2>Boolean Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
True -1 Boolean true
False 0 Boolean false</pre>
</div>
<div class="topic" id="lang.runtime">
<h1>Include Libraries</h1>
<p>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.</p>
<pre> File Provides
---- --------
commdlg.bas File Open/Save dialogs, input dialogs, choice dialogs, save-prompt dialogs
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, ...)</pre>
<h2>Using an Include Library</h2>
<pre><code>' With commdlg.bas added to the project
Dim path As String
path = DlgFileOpen$(&quot;Open a file&quot;, &quot;Text Files (*.txt)|All Files (*.*)&quot;)
If path &lt;&gt; &quot;&quot; Then
Print &quot;Selected: &quot; &amp; path
End If</code></pre>
<blockquote><strong>Note:</strong> DVX BASIC does not have an $INCLUDE directive. Libraries are added to the project so that the compiler sees their DECLARE LIBRARY blocks.</blockquote>
<h2>Encrypted Serial Links</h2>
<p>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.</p>
<pre><code>Dim link As Long
link = CommOpen(1, 115200, 8, &quot;N&quot;, 1, SER_HANDSHAKE_NONE)
If CommHandshake(link, &quot;shared secret&quot;) Then
CommSend link, &quot;hello&quot;, 0, True
Else
Print &quot;Handshake failed&quot;
End If</code></pre>
<p>After the handshake, data that arrives unencrypted is ignored unless that channel is opened for it with CommSetPlain link, channel, True.</p>
<h2>Printing</h2>
<p>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.</p>
<pre><code>Sub mnuPrint_Click ()
PrintTextDialog txtNotes.Text, &quot;Notes&quot;
End Sub
Sub mnuPageSetup_Click ()
PrintPageSetup
End Sub</code></pre>
<p>For printer output a line at a time, see LPRINT and OPEN &quot;LPT1:&quot;.</p>
<h2>Held Keys for Games</h2>
<p>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 &amp;H80 for the grey keys between the typing keys and the number pad). A Timer polls it:</p>
<pre><code>Sub Timer1_Timer ()
If GameKeyDown(GAMEKEY_LEFT) Then shipX = shipX - 2
If GameKeyDown(GAMEKEY_RIGHT) Then shipX = shipX + 2
End Sub</code></pre>
<h2>Joysticks</h2>
<p>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.</p>
<pre><code>Sub Timer1_Timer ()
If JoyCount() = 0 Then Exit Sub
shipX = shipX + JoyX(1) \ 8192
If JoyButton(1, 1) Then FireShot
End Sub</code></pre>
<p>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.</p>
<p><a href="#lang.sound">See: STICK and STRIG</a></p>
<h2>Sound</h2>
<p>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.</p>
<p>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 &quot;Sound Blaster 16 (DSP 4.05) at 220h, 22050 Hz, 16-bit stereo&quot;.</p>
<pre><code>Dim Shared boom As Long
Sub cmdFire_Click ()
boom = PlayWave(&quot;BOOM.WAV&quot;)
If boom = SOUND_FAILED Then
lblStatus.Caption = SoundError$()
End If
End Sub</code></pre>
<p>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.</p>
<p><a href="#lang.sound">See: BEEP, SOUND and PLAY</a></p>
<h2>Music</h2>
<p>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.</p>
<p>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.</p>
<pre><code>Dim Shared tune As Long
Sub Form_Load ()
tune = MusicLoad(&quot;THEME.MOD&quot;)
If tune = MUSIC_FAILED Then
lblStatus.Caption = MusicError$()
Else
MusicPlay tune, True
End If
End Sub</code></pre>
<p>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.</p>
<pre><code>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</code></pre>
<h2>Network Connections</h2>
<p>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:</p>
<pre><code>Dim conn As Long
Sub Form_Load ()
conn = TcpConnect(&quot;bbs.example.org&quot;, 23)
If conn = 0 Then
Print &quot;Could not connect: &quot; &amp; NetError$()
End If
End Sub
Sub Timer1_Timer ()
If TcpPending(conn) &gt; 0 Then Print TcpRecv$(conn)
If TcpConnected(conn) = 0 Then Timer1.Enabled = False
End Sub</code></pre>
<pre> Function Description
-------- -----------
HostLookup$(hostName) The address of a name, such as &quot;192.0.2.10&quot;, or &quot;&quot; when it is not found.
NetAddress$() This computer's address (&quot;&quot; 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 &quot;&quot;.
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. &quot;255.255.255.255&quot; reaches every computer nearby.
UdpRecv$(handle) The next message that arrived, or &quot;&quot;.
UdpFrom$() &quot;address:port&quot; of the sender of the last UdpRecv$ message.
UdpClose handle Close a UDP handle.</pre>
<p>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.</p>
<p>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.</p>
<pre><code>Dim msg As String
msg = CommRecv$(link, 1)
If msg &lt;&gt; &quot;&quot; And Not CommRecvEncrypted(link, 1) Then
Print &quot;Unencrypted: &quot; &amp; msg
End If</code></pre>
<p><a href="#lang.declarations">See also: DECLARE LIBRARY</a></p>
</div>
<div class="topic" id="ctrl.common.props">
<h1>Common Properties, Events, and Methods</h1>
<p>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.</p>
<h2>Common Properties</h2>
<pre> Property Type R/W Description
---------- ------- --- -------------------------------------------
Name String R The control's name (e.g. &quot;Command1&quot;). 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, &gt;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.</pre>
<p>Size properties (Width, Height and the Min/Max sizes) are limited to 0..32767.</p>
<h2>Common Events</h2>
<p>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.</p>
<pre> 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).</pre>
<h2>Common Methods</h2>
<pre> Method Parameters Description
-------- ---------- -------------------------------------------
SetFocus (none) Gives keyboard focus to this control.
Refresh (none) Forces the control to repaint.</pre>
<p><a href="#ctrl.form">Form</a></p>
<p><a href="#ctrl.databinding">Data Binding</a></p>
<p><a href="#ctrl.frm">FRM File Format</a></p>
</div>
<div class="topic" id="ctrl.databinding">
<h1>Data Binding</h1>
<p>DVX BASIC provides VB3-style data binding through three properties that can be set on most controls:</p>
<pre> Property Set On Description
---------- ----------- -------------------------------------------
DataSource Any control Name of the Data control to bind to (e.g. &quot;Data1&quot;).
DataField Any control Column name from the Data control's recordset to display.</pre>
<h2>How It Works</h2>
<ul>
<li>Place a Data control on the form and set its DatabaseName and RecordSource properties.</li>
<li>Place one or more display/edit controls (TextBox, Label, etc.) and set their DataSource to the Data control's name and DataField to a column name.</li>
<li>When the form loads, the Data control auto-refreshes: it opens the database, runs the query, and navigates to the first record.</li>
<li>Bound controls are updated automatically each time the Data control repositions (the Reposition event fires, and the runtime pushes the current record's field values into all bound controls).</li>
<li>When a bound control loses focus (LostFocus), its current text is written back to the Data control's record cache, and Update is called automatically to persist changes.</li>
</ul>
<h2>Master-Detail Binding</h2>
<p>For hierarchical data (e.g. orders and order items), use two Data controls:</p>
<ul>
<li>A master Data control bound to the parent table.</li>
<li>A detail Data control with its MasterSource set to the master's name, MasterField set to the key column in the master, and DetailField set to the foreign key column in the detail table.</li>
</ul>
<p>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.</p>
<h2>DBGrid Binding</h2>
<p>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.</p>
<h2>Example</h2>
<pre><code>VERSION DVX 1.00
Begin Form frmData
Caption = &quot;Data Binding Example&quot;
AutoSize = False
Width = 400
Height = 280
Begin Data Data1
DatabaseName = &quot;myapp.db&quot;
RecordSource = &quot;customers&quot;
End
Begin Label lblName
Caption = &quot;Name:&quot;
End
Begin TextBox txtName
DataSource = &quot;Data1&quot;
DataField = &quot;name&quot;
End
Begin Label lblEmail
Caption = &quot;Email:&quot;
End
Begin TextBox txtEmail
DataSource = &quot;Data1&quot;
DataField = &quot;email&quot;
End
End
Sub Data1_Reposition ()
Print &quot;Current record changed&quot;
End Sub
Sub Data1_Validate (Cancel As Integer)
If txtName.Text = &quot;&quot; Then
MsgBox &quot;Name cannot be empty!&quot;
Cancel = 1
End If
End Sub</code></pre>
<p><a href="#ctrl.data">Data</a></p>
<p><a href="#ctrl.dbgrid">DBGrid</a></p>
</div>
<div class="topic" id="ctrl.menus">
<h1>Menu System</h1>
<p>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.</p>
<h2>FRM Syntax</h2>
<pre><code>Begin Form Form1
Caption = &quot;Menu Demo&quot;
Begin Menu mnuFile
Caption = &quot;&amp;File&quot;
Begin Menu mnuOpen
Caption = &quot;&amp;Open&quot;
End
Begin Menu mnuSave
Caption = &quot;&amp;Save&quot;
End
Begin Menu mnuSep1
Caption = &quot;-&quot;
End
Begin Menu mnuExit
Caption = &quot;E&amp;xit&quot;
End
End
Begin Menu mnuEdit
Caption = &quot;&amp;Edit&quot;
Begin Menu mnuCopy
Caption = &quot;&amp;Copy&quot;
End
Begin Menu mnuPaste
Caption = &quot;&amp;Paste&quot;
End
End
End</code></pre>
<h2>Menu Item Properties</h2>
<p>In the .frm file a menu item takes these keys:</p>
<pre> Key Type Description
---------- ------- -------------------------------------------
Caption String The text displayed. Use &amp; for accelerator key. Set to &quot;-&quot; 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.</pre>
<p>At run time code can use only these properties of a menu item:</p>
<pre> 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.</pre>
<p>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.</p>
<h2>Nesting</h2>
<p>Menu items are nested by placing Begin Menu blocks inside other Begin Menu blocks:</p>
<ul>
<li>Level 0: top-level menu bar headers (e.g. &quot;File&quot;, &quot;Edit&quot;).</li>
<li>Level 1: items within a top-level menu.</li>
<li>Level 2+: submenu items.</li>
</ul>
<p>A level-0 menu that contains children becomes a top-level menu header. A non-level-0 menu that contains children becomes a submenu.</p>
<h2>Event Dispatch</h2>
<p>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.</p>
<pre><code>Sub mnuOpen_Click ()
MsgBox &quot;Open was clicked&quot;
End Sub
Sub mnuExit_Click ()
Unload Form1
End Sub</code></pre>
<p><a href="#ctrl.form">Form</a></p>
<p><a href="#ctrl.frm">FRM File Format</a></p>
</div>
<div class="topic" id="ctrl.arrays">
<h1>Control Arrays</h1>
<p>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.</p>
<h2>Defining Control Arrays in FRM</h2>
<pre><code>Begin CommandButton Command1
Caption = &quot;Button A&quot;
Index = 0
End
Begin CommandButton Command1
Caption = &quot;Button B&quot;
Index = 1
End
Begin CommandButton Command1
Caption = &quot;Button C&quot;
Index = 2
End</code></pre>
<h2>Event Handler Convention</h2>
<p>When a control has an Index property (&gt;= 0), the event handler receives Index As Integer as the first parameter, before any event-specific parameters.</p>
<pre><code>Sub Command1_Click (Index As Integer)
Select Case Index
Case 0
MsgBox &quot;Button A clicked&quot;
Case 1
MsgBox &quot;Button B clicked&quot;
Case 2
MsgBox &quot;Button C clicked&quot;
End Select
End Sub</code></pre>
<h2>Accessing Array Elements in Code</h2>
<p>Use the indexed form ControlName(Index) to access a specific element:</p>
<pre><code>Command1(0).Caption = &quot;New Text&quot;
Command1(1).Enabled = False</code></pre>
<blockquote><strong>Note:</strong> 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)).</blockquote>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.frm">FRM File Format</a></p>
</div>
<div class="topic" id="ctrl.frm">
<h1>FRM File Format</h1>
<p>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.</p>
<h2>Structure</h2>
<pre><code>VERSION DVX 1.00
Begin Form FormName
form-level properties...
Begin Menu mnuFile
Caption = &quot;&amp;File&quot;
Begin Menu mnuOpen
Caption = &quot;&amp;Open&quot;
End
End
Begin TypeName ControlName
property = value
...
End
Begin Frame Frame1
Caption = &quot;Group&quot;
Begin TypeName ChildName
...
End
End
End
BASIC code follows...
Sub FormName_Load ()
...
End Sub</code></pre>
<h2>Rules</h2>
<ul>
<li>The VERSION line is optional. VERSION DVX 1.00 marks a native DVX form. VB forms with version &lt;= 2.0 are accepted for import.</li>
<li>The form block begins with Begin Form Name and ends with End.</li>
<li>Controls are nested with Begin TypeName Name / End.</li>
<li>Container controls (Frame, VBox, HBox, Toolbar, TabStrip, ScrollPane, Splitter, WrapBox) can have child controls nested inside them.</li>
<li>Properties are assigned as Key = Value. String values are optionally quoted.</li>
<li>Everything after the form's closing End is BASIC source code.</li>
<li>Comments in the form section use ' (single quote).</li>
<li>Blank lines are ignored in the form section.</li>
</ul>
<h2>Common FRM Properties</h2>
<pre> 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 &quot;VBox&quot; or &quot;HBox&quot;.
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.</pre>
<p><a href="#ctrl.form">Form</a></p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.menus">Menu System</a></p>
<p><a href="#ctrl.arrays">Control Arrays</a></p>
</div>
<div class="topic" id="ctrl.form">
<h1>Form</h1>
<p>VB Equivalent: Form -- DVX Widget: Window + VBox/HBox root</p>
<p>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.</p>
<h2>Form Properties</h2>
<pre> Property Type Default Description
---------- ------- -------------- -------------------------------------------
Name String &quot;Form1&quot; 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 &quot;VBox&quot; Content box layout: &quot;VBox&quot; (vertical) or &quot;HBox&quot; (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 &quot;&quot; Name of a popup menu shown when the form is right-clicked.
HelpTopic String &quot;&quot; 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.</pre>
<h2>Form Events</h2>
<pre> 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.</pre>
<h2>Form Methods</h2>
<pre> 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.</pre>
<h2>Example</h2>
<pre><code>Sub Form_Load ()
Form1.Caption = &quot;Hello World&quot;
Print &quot;Form loaded!&quot;
End Sub
Sub Form_QueryUnload (Cancel As Integer)
If MsgBox(&quot;Really quit?&quot;, 4) &lt;&gt; 6 Then
Cancel = 1
End If
End Sub
Sub Form_Resize ()
Print &quot;Window resized&quot;
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.frm">FRM File Format</a></p>
</div>
<div class="topic" id="ctrl.terminal">
<h1>Terminal</h1>
<p>DVX Extension -- DVX Widget: ansiterm</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<p>No default event. Uses common events only.</p>
<h2>Serial Communication</h2>
<p>Use the comm.bas library to connect a Terminal to a serial link:</p>
<pre><code>Dim link As Long
link = CommOpen(1, 115200, 8, &quot;N&quot;, 1, SER_HANDSHAKE_NONE)
If link &lt;&gt; 0 Then
If CommHandshake(link, &quot;secret&quot;) Then
CommAttach link, &quot;Terminal1&quot;, 0, True
Else
MsgBox &quot;Handshake failed&quot;
End If
End If</code></pre>
<p>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.</p>
<h2>Example</h2>
<pre><code>Begin Terminal Terminal1
MinWidth = 640
MinHeight = 400
End
Sub Form_Load ()
Terminal1.Write &quot;Welcome!&quot; &amp; Chr$(13) &amp; Chr$(10)
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.frame">
<h1>Frame</h1>
<p>VB Equivalent: Frame -- DVX Widget: frame (titled container)</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
-------- ------ -------------------------------------------
Caption String The title displayed in the frame border.</pre>
<p>No type-specific methods or events.</p>
<p>Setting Enabled = False on a Frame disables every control inside it for mouse and keyboard input.</p>
<p>Container: Yes</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin Frame Frame1
Caption = &quot;Options&quot;
Begin CheckBox Check1
Caption = &quot;Option A&quot;
End
Begin CheckBox Check2
Caption = &quot;Option B&quot;
End
End</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.hbox">
<h1>HBox</h1>
<p>DVX Extension -- DVX Widget: hbox (horizontal layout container)</p>
<p>A container that arranges its children horizontally, left to right. No visible border. Use Weight on children to distribute extra space proportionally.</p>
<p>No type-specific properties, methods, or events.</p>
<p>Container: Yes</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin HBox ButtonRow
Spacing = 4
Begin CommandButton Command1
Caption = &quot;OK&quot;
End
Begin CommandButton Command2
Caption = &quot;Cancel&quot;
End
End</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.vbox">VBox</a></p>
</div>
<div class="topic" id="ctrl.vbox">
<h1>VBox</h1>
<p>DVX Extension -- DVX Widget: vbox (vertical layout container)</p>
<p>A container that arranges its children vertically, top to bottom. No title or border. Use Weight on children to distribute extra space proportionally.</p>
<p>No type-specific properties, methods, or events.</p>
<p>Container: Yes</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin VBox Column1
Spacing = 4
Begin Label Label1
Caption = &quot;Name:&quot;
End
Begin TextBox Text1
End
End</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.hbox">HBox</a></p>
</div>
<div class="topic" id="ctrl.button">
<h1>CommandButton</h1>
<p>VB Equivalent: CommandButton -- DVX Widget: button | Name Prefix: Command</p>
<p>A push button that triggers an action when clicked. The Caption may include a '&amp;' before a character to mark an accelerator key (e.g. &quot;&amp;OK&quot; underlines 'O', and Alt+O activates the button).</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
-------- ------ -------------------------------------------
Caption String The text displayed on the button. Use '&amp;' for an accelerator key.</pre>
<p>No type-specific methods or events.</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin Form Form1
Caption = &quot;Button Demo&quot;
Begin CommandButton Command1
Caption = &quot;&amp;Click Me!&quot;
End
End
Sub Command1_Click ()
MsgBox &quot;Button was clicked!&quot;
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.picturebox">
<h1>PictureBox</h1>
<p>VB Equivalent: PictureBox -- DVX Widget: canvas | Name Prefix: Picture</p>
<p>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.</p>
<p>Colors are specified as 0x00RRGGBB integers (e.g. &amp;HFF0000 for red).</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<p>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.</p>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Picture1.Resize 200, 150
Picture1.Clear &amp;HFFFFFF
Picture1.SetPenSize 2
Picture1.DrawRect 10, 10, 180, 130, &amp;H000000
Picture1.FillCircle 100, 75, 40, &amp;HFF0000
Picture1.DrawText 60, 130, &quot;Hello!&quot;
If Picture1.Save(&quot;output.bmp&quot;) &lt;&gt; 0 Then
MsgBox &quot;Could not save output.bmp&quot;
End If</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.checkbox">
<h1>CheckBox</h1>
<p>VB Equivalent: CheckBox -- DVX Widget: checkbox</p>
<p>A toggle control with a label. The checked state is exposed as a Boolean. Supports accelerator keys (put '&amp;' before a character in the Caption). Press Space or Enter to toggle when focused.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
-------- ------- -------------------------------------------
Caption String The text displayed next to the checkbox.
Value Boolean True if checked, False if unchecked.</pre>
<p>No type-specific methods or events.</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin CheckBox Check1
Caption = &quot;Enable feature&quot;
End
Sub Check1_Click ()
If Check1.Value Then
Label1.Caption = &quot;Feature ON&quot;
Else
Label1.Caption = &quot;Feature OFF&quot;
End If
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.combobox">
<h1>ComboBox</h1>
<p>VB Equivalent: ComboBox -- DVX Widget: combobox (editable text field + drop-down list, default maxLen 256)</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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).</pre>
<h2>Type-Specific Methods</h2>
<pre> 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).</pre>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin ComboBox Combo1
End
Sub Form_Load ()
Combo1.AddItem &quot;Small&quot;
Combo1.AddItem &quot;Medium&quot;
Combo1.AddItem &quot;Large&quot;
End Sub
Sub Combo1_Change ()
Label1.Caption = &quot;Selected: &quot; &amp; Combo1.Text
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.listbox">See ListBox for details</a></p>
</div>
<div class="topic" id="ctrl.data">
<h1>Data</h1>
<p>VB Equivalent: Data -- DVX Widget: data | Name Prefix: Data</p>
<p>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.</p>
<p><a href="#ctrl.databinding">See Data Binding for details</a></p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<h2>Type-Specific Events</h2>
<pre> 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.</pre>
<p>Default Event: Reposition</p>
<h2>Example</h2>
<pre><code>Begin Data Data1
DatabaseName = &quot;books.db&quot;
RecordSource = &quot;titles&quot;
KeyColumn = &quot;id&quot;
End
Begin TextBox Text1
DataSource = &quot;Data1&quot;
DataField = &quot;title&quot;
End
Sub Form_Load ()
Data1.Refresh
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.databinding">Data Binding</a></p>
<p><a href="#ctrl.dbgrid">DBGrid</a></p>
</div>
<div class="topic" id="ctrl.dbgrid">
<h1>DBGrid</h1>
<p>VB Equivalent: DBGrid -- DVX Widget: dbgrid | Name Prefix: DBGrid</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<h2>Type-Specific Events</h2>
<pre> Event Parameters Description
-------- ---------- -------------------------------------------
Click (none) Fires when a row is clicked.
DblClick (none) Fires when a row is double-clicked. Default event.</pre>
<p>Default Event: DblClick</p>
<h2>Example</h2>
<pre><code>Begin Data Data1
DatabaseName = &quot;books.db&quot;
RecordSource = &quot;titles&quot;
End
Begin DBGrid DBGrid1
DataSource = &quot;Data1&quot;
GridLines = True
End
Sub Form_Load ()
Data1.Refresh
End Sub
Sub DBGrid1_DblClick ()
MsgBox &quot;Opening row &quot; &amp; Str$(Data1.BOF)
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.data">Data</a></p>
<p><a href="#ctrl.databinding">Data Binding</a></p>
</div>
<div class="topic" id="ctrl.dropdown">
<h1>DropDown</h1>
<p>DVX Extension -- DVX Widget: dropdown (non-editable drop-down list)</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
--------- ------- -------------------------------------------
ListIndex Integer Index of the currently selected item (-1 = none).</pre>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<p>Default Event: Change (fires when the user picks a new item; Click fires only when the arrow opens the popup)</p>
<h2>Example</h2>
<pre><code>Begin DropDown DropDown1
End
Sub Form_Load ()
DropDown1.AddItem &quot;Small&quot;
DropDown1.AddItem &quot;Medium&quot;
DropDown1.AddItem &quot;Large&quot;
DropDown1.ListIndex = 1
End Sub
Sub DropDown1_Change ()
Label1.Caption = &quot;Picked: &quot; &amp; DropDown1.List(DropDown1.ListIndex)
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.listbox">See ListBox for details</a></p>
</div>
<div class="topic" id="ctrl.imagebutton">
<h1>ImageButton</h1>
<p>DVX Extension -- DVX Widget: imagebutton</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
----------- ------- -------------------------------------------
Picture String Path to an image file to load. Reads back the file the image came from. Setting it to &quot;&quot; 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).</pre>
<p>No type-specific methods or events.</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin Toolbar Toolbar1
Begin ImageButton ImageButton1
Picture = &quot;icons/save.bmp&quot;
End
Begin ImageButton ImageButton2
Picture = &quot;icons/open.bmp&quot;
End
End
Sub ImageButton1_Click ()
MsgBox &quot;Save clicked&quot;
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.image">
<h1>Image</h1>
<p>VB Equivalent: Image -- DVX Widget: image</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
----------- ------- -------------------------------------------
Picture String Path to an image file to load. Reads back the file the image came from. Setting it to &quot;&quot; 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).</pre>
<p>No type-specific methods or events.</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin Image Image1
Picture = &quot;assets/logo.bmp&quot;
Stretch = True
End
Sub Image1_Click ()
MsgBox &quot;Size: &quot; &amp; Str$(Image1.ImageWidth) &amp; &quot;x&quot; &amp; Str$(Image1.ImageHeight)
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.label">
<h1>Label</h1>
<p>VB Equivalent: Label -- DVX Widget: label</p>
<p>A static text label. Supports left, center, and right alignment. Put '&amp;' before a character in the Caption to define an accelerator that moves focus to the next focusable control.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
--------- ---- -------------------------------------------
Caption String The text displayed by the label.
Alignment Enum Text alignment: Left (default), Center, or Right.</pre>
<p>No type-specific methods or events.</p>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Begin Label Label1
Caption = &quot;Hello, World!&quot;
Alignment = &quot;Center&quot;
End</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.listbox">
<h1>ListBox</h1>
<p>VB Equivalent: ListBox -- DVX Widget: listbox</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
--------- ------- -------------------------------------------
ListIndex Integer Index of the currently selected item (-1 = no selection).</pre>
<h2>Type-Specific Methods</h2>
<pre> 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. &quot;Red|Green|Blue&quot;). Replaces existing items. Every &quot;|&quot; separates two items (&quot;a|&quot; is &quot;a&quot; and an empty item); &quot;&quot; empties the list.
SetMultiSelect Multi As Boolean Enable or disable multi-select mode.
SetReorderable Reorderable As Boolean Enable or disable drag-to-reorder.</pre>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>Sub Form_Load ()
List1.AddItem &quot;Apple&quot;
List1.AddItem &quot;Banana&quot;
List1.AddItem &quot;Cherry&quot;
End Sub
Sub List1_Click ()
Dim idx As Integer
idx = List1.ListIndex
If idx &gt;= 0 Then
Label1.Caption = &quot;Selected: &quot; &amp; List1.List(idx)
End If
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.combobox">ComboBox</a></p>
<p><a href="#ctrl.dropdown">DropDown</a></p>
</div>
<div class="topic" id="ctrl.listview">
<h1>ListView</h1>
<p>VB Equivalent: ListView -- DVX Widget: listview</p>
<p>A multi-column list with column headers. Supports sorting, multi-select, and drag-to-reorder.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type R/W Description
--------- ------- --- -------------------------------------------
ListIndex Integer R/W Index of the currently selected row (-1 = none).</pre>
<h2>Type-Specific Methods</h2>
<pre> 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 &quot;Name,Width|Name,Width&quot; (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.</pre>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>ListView1.SetColumns &quot;Name,20|Size,10|Type,15&quot;
ListView1.AddItem &quot;readme.txt&quot;
ListView1.SetCell 0, 1, &quot;1024&quot;
ListView1.SetCell 0, 2, &quot;Text&quot;
ListView1.SetSort 0, 1</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.progressbar">
<h1>ProgressBar</h1>
<p>VB Equivalent: ProgressBar -- DVX Widget: progressbar</p>
<p>A horizontal progress indicator bar.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
-------- ------- -------------------------------------------
Value Integer Current progress value (0-100).</pre>
<p>No type-specific events or methods. No default event.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.optionbutton">
<h1>OptionButton</h1>
<p>VB Equivalent: OptionButton -- DVX Widget: radio (radio group + radio button) | Name Prefix: Option</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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).</pre>
<h2>Type-Specific Methods</h2>
<pre> Method Parameters Description
----------- ----------------- -------------------------------------------
SetSelected Index As Integer Select the OptionButton at the given index within this button's container.</pre>
<p>Default Event: Click</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.scrollpane">
<h1>ScrollPane</h1>
<p>DVX Extension -- DVX Widget: scrollpane | Name Prefix: Scroll</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
-------- ------- -------------------------------------------
NoBorder Boolean When True, suppresses the border around the scroll pane.</pre>
<p>Container: Yes</p>
<p>No default event.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.line">
<h1>Line</h1>
<p>VB Equivalent: Line -- DVX Widget: separator</p>
<p>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.</p>
<p>No type-specific properties, events, or methods.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.hscrollbar">
<h1>HScrollBar</h1>
<p>VB Equivalent: HScrollBar -- DVX Widget: slider | Name Prefix: HScroll</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<p>Default Event: Change</p>
<h2>Example</h2>
<pre><code>Begin HScrollBar HScroll1
MinWidth = 200
End
Sub HScroll1_Change ()
Label1.Caption = &quot;Value: &quot; &amp; Str$(HScroll1.Value)
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.spacer">
<h1>Spacer</h1>
<p>DVX Extension -- DVX Widget: spacer</p>
<p>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.</p>
<p>No type-specific properties, events, or methods.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.spinbutton">
<h1>SpinButton</h1>
<p>DVX Extension -- DVX Widget: spinner | Name Prefix: Spin</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<p>Default Event: Change</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.splitter">
<h1>Splitter</h1>
<p>DVX Extension -- DVX Widget: splitter</p>
<p>A resizable split pane. Holds exactly two child widgets separated by a draggable divider. Default orientation is vertical (vertical divider, panes side-by-side).</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
-------- ------- -------------------------------------------
Position Integer Position of the divider in pixels from the top (or left).</pre>
<p>Container: Yes</p>
<p>No default event.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.statusbar">
<h1>StatusBar</h1>
<p>VB Equivalent: StatusBar -- DVX Widget: statusbar</p>
<p>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.</p>
<p>No type-specific properties, events, or methods.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.tabstrip">
<h1>TabStrip</h1>
<p>VB Equivalent: TabStrip -- DVX Widget: tabcontrol</p>
<p>A tabbed container. Each tab page is a separate container that holds child controls. Switching tabs shows one page and hides others.</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<p>Container: Yes</p>
<p>Default Event: Click</p>
<blockquote><strong>Warning:</strong> The TabIndex property is shadowed by the common property handler at runtime. Use the SetActive method to change tabs programmatically.</blockquote>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.textbox">
<h1>TextBox</h1>
<p>VB Equivalent: TextBox -- DVX Widget: textbox (single-line text input, max 256 chars)</p>
<p>A single-line text input field. Supports data binding via DataSource and DataField properties.</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<p>Default Event: Change</p>
<h2>Example</h2>
<pre><code>Begin TextBox Text1
Text = &quot;Enter text here&quot;
End
Sub Text1_Change ()
Label1.Caption = &quot;You typed: &quot; &amp; Text1.Text
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
<p><a href="#ctrl.databinding">Data Binding</a></p>
</div>
<div class="topic" id="ctrl.textarea">
<h1>TextArea</h1>
<p>VB Equivalent: TextArea (DVX extension) -- DVX Widget: textarea (multi-line text input, default max 65536 chars)</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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).</pre>
<h2>Type-Specific Methods</h2>
<pre> 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: &quot;dhs&quot; (help source), &quot;bas&quot; (BASIC). Pass &quot;&quot; to disable.
SetTabWidth width% Set the tab stop width in characters.
SetUseTabChar useChar When True, Tab inserts a tab character; when False, inserts spaces.</pre>
<p>Default Event: Change</p>
<h2>Example</h2>
<pre><code>TextArea1.SetShowLineNumbers True
TextArea1.SetAutoIndent True
TextArea1.SetTabWidth 4
TextArea1.SetCaptureTabs True
' Search for text
If TextArea1.FindNext(&quot;TODO&quot;, False, True) Then
Print &quot;Found at line&quot;; TextArea1.CursorLine
End If
' Replace all occurrences
Dim count As Integer
count = TextArea1.ReplaceAll(&quot;old&quot;, &quot;new&quot;, False)
Print &quot;Replaced&quot;; count; &quot;occurrences&quot;</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.timer">
<h1>Timer</h1>
<p>VB Equivalent: Timer -- DVX Widget: timer (non-visual)</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> 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.</pre>
<h2>Type-Specific Methods</h2>
<pre> Method Parameters Description
------ ---------- -------------------------------------------
Start (none) Start the timer.
Stop (none) Stop the timer.</pre>
<h2>Type-Specific Events</h2>
<pre> 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.</pre>
<blockquote><strong>Note:</strong> The Timer control fires the Timer event instead of Change. The onChange callback on the underlying widget is remapped automatically.</blockquote>
<h2>Example</h2>
<pre><code>Begin Timer Timer1
Interval = 1000
Enabled = True
End
Dim Shared counter As Integer
Sub Timer1_Timer ()
counter = counter + 1
Label1.Caption = &quot;Ticks: &quot; &amp; Str$(counter)
End Sub</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.toolbar">
<h1>Toolbar</h1>
<p>VB Equivalent: Toolbar -- DVX Widget: toolbar</p>
<p>A horizontal container styled as a toolbar, with compact padding and spacing. Place buttons, labels, or other controls inside.</p>
<p>Container: Yes</p>
<p>No type-specific properties, events, or methods.</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.treeview">
<h1>TreeView</h1>
<p>VB Equivalent: TreeView -- DVX Widget: treeview</p>
<p>A hierarchical tree of expandable/collapsible nodes. Supports multi-select and drag-to-reorder. Items are accessed by depth-first index (0-based).</p>
<h2>Type-Specific Methods</h2>
<pre> 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.</pre>
<p>Default Event: Click</p>
<h2>Example</h2>
<pre><code>TreeView1.AddItem &quot;Animals&quot;
TreeView1.AddChildItem 0, &quot;Cat&quot;
TreeView1.AddChildItem 0, &quot;Dog&quot;
TreeView1.AddItem &quot;Plants&quot;
TreeView1.AddChildItem 3, &quot;Oak&quot;
TreeView1.SetExpanded 0, True
Print &quot;Items:&quot;; TreeView1.ItemCount()</code></pre>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
<div class="topic" id="ctrl.wrapbox">
<h1>WrapBox</h1>
<p>DVX Extension -- DVX Widget: wrapbox | Name Prefix: WrapBox</p>
<p>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.</p>
<h2>Type-Specific Properties</h2>
<pre> Property Type Description
--------- ---- -------------------------------------------
Alignment Enum Horizontal alignment of items: Left, Center, or Right.</pre>
<p>Container: Yes</p>
<p>Default Event: Click</p>
<p><a href="#ctrl.common.props">Common Properties, Events, and Methods</a></p>
</div>
</main>
</body>
</html>