DVX_GUI/docs/dvxbasic_control_reference.html
2026-04-06 22:25:06 -05:00

1687 lines
57 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="ASCII">
<title>DVX BASIC Control Reference</title>
<style>
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
max-width: 960px;
margin: 0 auto;
padding: 20px;
line-height: 1.6;
color: #222;
background: #fafafa;
}
h1 {
border-bottom: 3px solid #336;
padding-bottom: 10px;
color: #224;
}
h2 {
border-bottom: 2px solid #669;
padding-bottom: 6px;
margin-top: 40px;
color: #336;
}
h3 {
color: #448;
margin-top: 30px;
}
h4 {
color: #558;
margin-top: 20px;
margin-bottom: 8px;
}
table {
border-collapse: collapse;
width: 100%;
margin: 10px 0 20px 0;
background: #fff;
}
th, td {
border: 1px solid #bbb;
padding: 6px 10px;
text-align: left;
vertical-align: top;
}
th {
background: #e0e4f0;
font-weight: bold;
}
tr:nth-child(even) {
background: #f4f6fa;
}
code {
background: #e8e8f0;
padding: 1px 5px;
border-radius: 3px;
font-family: "Consolas", "Courier New", monospace;
font-size: 0.95em;
}
pre {
background: #2a2a3a;
color: #e0e0e0;
padding: 12px 16px;
border-radius: 5px;
overflow-x: auto;
font-family: "Consolas", "Courier New", monospace;
font-size: 0.9em;
line-height: 1.5;
}
.toc {
background: #eef0f8;
border: 1px solid #ccd;
padding: 15px 20px;
border-radius: 5px;
margin: 20px 0;
}
.toc ul {
margin: 5px 0;
padding-left: 20px;
}
.toc li {
margin: 3px 0;
}
.toc a {
text-decoration: none;
color: #336;
}
.toc a:hover {
text-decoration: underline;
}
a {
color: #336;
}
.note {
background: #fffbe6;
border-left: 4px solid #cc9;
padding: 10px 14px;
margin: 15px 0;
}
.ctrl-header {
background: #e0e4f0;
padding: 8px 14px;
border-radius: 4px;
margin-bottom: 10px;
}
.ctrl-header span {
color: #666;
font-size: 0.9em;
}
</style>
</head>
<body>
<h1>DVX BASIC Control Reference</h1>
<p>
This document describes every VB-style control available in DVX BASIC.
Each control maps to an underlying DVX widget loaded dynamically via
<code>.wgt</code> DXE files. Properties and methods are dispatched through
interface descriptors registered by each widget.
</p>
<div class="toc">
<strong>Table of Contents</strong>
<ul>
<li><a href="#common">Common Properties, Events, and Methods</a></li>
<li><a href="#form">Form</a></li>
<li><a href="#commandbutton">CommandButton</a></li>
<li><a href="#label">Label</a></li>
<li><a href="#textbox">TextBox</a></li>
<li><a href="#textarea">TextArea</a></li>
<li><a href="#checkbox">CheckBox</a></li>
<li><a href="#optionbutton">OptionButton</a></li>
<li><a href="#frame">Frame</a></li>
<li><a href="#vbox">VBox</a></li>
<li><a href="#hbox">HBox</a></li>
<li><a href="#listbox">ListBox</a></li>
<li><a href="#combobox">ComboBox</a></li>
<li><a href="#dropdown">DropDown</a></li>
<li><a href="#hscrollbar">HScrollBar</a></li>
<li><a href="#spinbutton">SpinButton</a></li>
<li><a href="#timer">Timer</a></li>
<li><a href="#picturebox">PictureBox</a></li>
<li><a href="#image">Image</a></li>
<li><a href="#imagebutton">ImageButton</a></li>
<li><a href="#progressbar">ProgressBar</a></li>
<li><a href="#listview">ListView</a></li>
<li><a href="#treeview">TreeView</a></li>
<li><a href="#tabstrip">TabStrip</a></li>
<li><a href="#splitter">Splitter</a></li>
<li><a href="#scrollpane">ScrollPane</a></li>
<li><a href="#wrapbox">WrapBox</a></li>
<li><a href="#line">Line</a></li>
<li><a href="#spacer">Spacer</a></li>
<li><a href="#toolbar">Toolbar</a></li>
<li><a href="#statusbar">StatusBar</a></li>
<li><a href="#terminal">Terminal</a></li>
<li><a href="#data">Data</a></li>
<li><a href="#dbgrid">DBGrid</a></li>
<li><a href="#databinding">Data Binding</a></li>
<li><a href="#menus">Menu System</a></li>
<li><a href="#controlarrays">Control Arrays</a></li>
<li><a href="#frm-format">FRM File Format</a></li>
</ul>
</div>
<!-- ============================================================ -->
<h2 id="common">Common Properties, Events, and Methods</h2>
<!-- ============================================================ -->
<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>
<h4>Common Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>R/W</th><th>Description</th></tr>
<tr><td><code>Name</code></td><td>String</td><td>R</td><td>The control's name (e.g. "Command1"). Read-only at runtime.</td></tr>
<tr><td><code>Left</code></td><td>Integer</td><td>R/W</td><td>X position in pixels relative to the parent container.</td></tr>
<tr><td><code>Top</code></td><td>Integer</td><td>R/W</td><td>Y position in pixels relative to the parent container.</td></tr>
<tr><td><code>Width</code></td><td>Integer</td><td>R/W</td><td>Current width in pixels. Setting this changes the minimum width constraint.</td></tr>
<tr><td><code>Height</code></td><td>Integer</td><td>R/W</td><td>Current height in pixels. Setting this changes the minimum height constraint.</td></tr>
<tr><td><code>MinWidth</code></td><td>Integer</td><td>R/W</td><td>Minimum width for layout. Alias for <code>Width</code> in the setter.</td></tr>
<tr><td><code>MinHeight</code></td><td>Integer</td><td>R/W</td><td>Minimum height for layout. Alias for <code>Height</code> in the setter.</td></tr>
<tr><td><code>MaxWidth</code></td><td>Integer</td><td>R/W</td><td>Maximum width cap (0 = no limit, stretch to fill).</td></tr>
<tr><td><code>MaxHeight</code></td><td>Integer</td><td>R/W</td><td>Maximum height cap (0 = no limit, stretch to fill).</td></tr>
<tr><td><code>Weight</code></td><td>Integer</td><td>R/W</td><td>Layout weight. 0 = fixed size, &gt;0 = share extra space proportionally.</td></tr>
<tr><td><code>Visible</code></td><td>Boolean</td><td>R/W</td><td>Whether the control is visible.</td></tr>
<tr><td><code>Enabled</code></td><td>Boolean</td><td>R/W</td><td>Whether the control accepts user input.</td></tr>
<tr><td><code>BackColor</code></td><td>Long</td><td>R/W</td><td>Background color as a 32-bit ARGB value.</td></tr>
<tr><td><code>ForeColor</code></td><td>Long</td><td>R/W</td><td>Foreground (text) color as a 32-bit ARGB value.</td></tr>
<tr><td><code>TabIndex</code></td><td>Integer</td><td>R</td><td>Accepted for VB compatibility but ignored. DVX has no tab order.</td></tr>
</table>
<h4>Common Events</h4>
<p>
These events are wired on every control loaded from a <code>.frm</code>
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
<code>.frm</code> file.
</p>
<table>
<tr><th>Event</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Click</code></td><td>(none)</td><td>Fires when the control is clicked.</td></tr>
<tr><td><code>DblClick</code></td><td>(none)</td><td>Fires when the control is double-clicked.</td></tr>
<tr><td><code>Change</code></td><td>(none)</td><td>Fires when the control's value or text changes.</td></tr>
<tr><td><code>GotFocus</code></td><td>(none)</td><td>Fires when the control receives keyboard focus.</td></tr>
<tr><td><code>LostFocus</code></td><td>(none)</td><td>Fires when the control loses keyboard focus.</td></tr>
<tr><td><code>KeyPress</code></td><td><code>KeyAscii As Integer</code></td><td>Fires when a printable key is pressed. KeyAscii is the ASCII code.</td></tr>
<tr><td><code>KeyDown</code></td><td><code>KeyCode As Integer, Shift As Integer</code></td><td>Fires when any key is pressed down. KeyCode is the scan code; Shift indicates modifier keys.</td></tr>
<tr><td><code>KeyUp</code></td><td><code>KeyCode As Integer, Shift As Integer</code></td><td>Fires when a key is released.</td></tr>
<tr><td><code>MouseDown</code></td><td><code>Button As Integer, X As Integer, Y As Integer</code></td><td>Fires when a mouse button is pressed over the control.</td></tr>
<tr><td><code>MouseUp</code></td><td><code>Button As Integer, X As Integer, Y As Integer</code></td><td>Fires when a mouse button is released over the control.</td></tr>
<tr><td><code>MouseMove</code></td><td><code>Button As Integer, X As Integer, Y As Integer</code></td><td>Fires when the mouse moves over the control.</td></tr>
<tr><td><code>Scroll</code></td><td><code>Delta As Integer</code></td><td>Fires when the control is scrolled (mouse wheel or scrollbar).</td></tr>
</table>
<h4>Common Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>SetFocus</code></td><td>(none)</td><td>Gives keyboard focus to this control.</td></tr>
<tr><td><code>Refresh</code></td><td>(none)</td><td>Forces the control to repaint.</td></tr>
</table>
<!-- ============================================================ -->
<h2 id="form">Form</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Form &nbsp;&nbsp;
<span>DVX Widget: Window + VBox/HBox root</span>
</div>
<p>
The Form is the top-level container representing a DVX window. It is declared
in the <code>.frm</code> file with <code>Begin Form <em>FormName</em></code>.
All controls are children of the form's content box, which uses either VBox
(default) or HBox layout.
</p>
<h4>Form Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Default</th><th>Description</th></tr>
<tr><td><code>Name</code></td><td>String</td><td>"Form1"</td><td>The form's name, used for event dispatch and <code>Load</code> statement.</td></tr>
<tr><td><code>Caption</code></td><td>String</td><td>(same as Name)</td><td>Window title bar text.</td></tr>
<tr><td><code>Width</code></td><td>Integer</td><td>400</td><td>Window width in pixels. Setting this disables AutoSize.</td></tr>
<tr><td><code>Height</code></td><td>Integer</td><td>300</td><td>Window height in pixels. Setting this disables AutoSize.</td></tr>
<tr><td><code>Left</code></td><td>Integer</td><td>0</td><td>Initial X position. Used when Centered is False.</td></tr>
<tr><td><code>Top</code></td><td>Integer</td><td>0</td><td>Initial Y position. Used when Centered is False.</td></tr>
<tr><td><code>Layout</code></td><td>String</td><td>"VBox"</td><td>Content box layout: <code>"VBox"</code> (vertical) or <code>"HBox"</code> (horizontal).</td></tr>
<tr><td><code>AutoSize</code></td><td>Boolean</td><td>True</td><td>When True, the window shrink-wraps to fit its content.</td></tr>
<tr><td><code>Resizable</code></td><td>Boolean</td><td>True</td><td>Whether the user can resize the window at runtime.</td></tr>
<tr><td><code>Centered</code></td><td>Boolean</td><td>True</td><td>When True, the window is centered on screen. When False, Left/Top are used.</td></tr>
</table>
<h4>Form Events</h4>
<table>
<tr><th>Event</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Load</code></td><td>(none)</td><td>Fires after the form and all controls are created. This is the default event.</td></tr>
<tr><td><code>Unload</code></td><td>(none)</td><td>Fires when the form is being closed or unloaded.</td></tr>
<tr><td><code>QueryUnload</code></td><td><code>Cancel As Integer</code></td><td>Fires before Unload. Set <code>Cancel = 1</code> to abort the close.</td></tr>
<tr><td><code>Resize</code></td><td>(none)</td><td>Fires when the window is resized by the user.</td></tr>
<tr><td><code>Activate</code></td><td>(none)</td><td>Fires when the window gains focus.</td></tr>
<tr><td><code>Deactivate</code></td><td>(none)</td><td>Fires when the window loses focus.</td></tr>
</table>
<h4>Form Methods (called on the form object)</h4>
<table>
<tr><th>Statement</th><th>Description</th></tr>
<tr><td><code>Load <em>FormName</em></code></td><td>Load the form (creates the window and controls, fires Load event).</td></tr>
<tr><td><code>Unload <em>FormName</em></code></td><td>Unload the form (fires Unload, destroys window).</td></tr>
<tr><td><code><em>FormName</em>.Show</code></td><td>Make the form visible.</td></tr>
<tr><td><code><em>FormName</em>.Show 1</code></td><td>Show as modal dialog (blocks until closed).</td></tr>
<tr><td><code><em>FormName</em>.Hide</code></td><td>Hide the form without unloading it.</td></tr>
</table>
<h4>Example</h4>
<pre>
Sub Form_Load ()
Form1.Caption = "Hello World"
Print "Form loaded!"
End Sub
Sub Form_QueryUnload (Cancel As Integer)
If MsgBox("Really quit?", 4) &lt;&gt; 6 Then
Cancel = 1
End If
End Sub
Sub Form_Resize ()
Print "Window resized"
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="commandbutton">CommandButton</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> CommandButton &nbsp;&nbsp;
<span>DVX Widget: button | Name Prefix: Command</span>
</div>
<p>
A push button that triggers an action when clicked. Created with
<code>wgtButton(parent, text)</code>.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Caption</code></td><td>String</td><td>The text displayed on the button. Use <code>&amp;</code> for accelerator keys (e.g. "&amp;OK").</td></tr>
</table>
<p>No additional type-specific properties beyond common properties and Caption.</p>
<h4>Default Event: <code>Click</code></h4>
<h4>Example</h4>
<pre>
Begin Form Form1
Caption = "Button Demo"
Begin CommandButton Command1
Caption = "&amp;Click Me!"
End
End
Sub Command1_Click ()
MsgBox "Button was clicked!"
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="label">Label</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Label &nbsp;&nbsp;
<span>DVX Widget: label</span>
</div>
<p>
A static text label. Supports left, center, and right alignment.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Caption</code></td><td>String</td><td>The text displayed by the label.</td></tr>
<tr><td><code>Alignment</code></td><td>Enum</td><td>Text alignment: <code>Left</code> (default), <code>Center</code>, or <code>Right</code>.</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<h4>Example</h4>
<pre>
Begin Label Label1
Caption = "Hello, World!"
Alignment = "Center"
End
</pre>
<!-- ============================================================ -->
<h2 id="textbox">TextBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> TextBox &nbsp;&nbsp;
<span>DVX Widget: textbox (single-line text input, max 256 chars)</span>
</div>
<p>
A single-line text input field. Supports data binding via DataSource
and DataField properties.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Text</code></td><td>String</td><td>The text content of the input field.</td></tr>
<tr><td><code>DataSource</code></td><td>String</td><td>Name of a Data control for data binding.</td></tr>
<tr><td><code>DataField</code></td><td>String</td><td>Column name for data binding.</td></tr>
</table>
<h4>Default Event: <code>Change</code></h4>
<h4>Example</h4>
<pre>
Begin TextBox Text1
Text = "Enter text here"
End
Sub Text1_Change ()
Label1.Caption = "You typed: " &amp; Text1.Text
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="textarea">TextArea</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> TextArea (DVX extension) &nbsp;&nbsp;
<span>DVX Widget: textarea (multi-line text input, max 4096 chars)</span>
</div>
<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 syntax
colorization, line numbers, auto-indent, and find/replace via the C API.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Text</code></td><td>String</td><td>The full text content.</td></tr>
</table>
<h4>Default Event: <code>Change</code></h4>
<!-- ============================================================ -->
<h2 id="checkbox">CheckBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> CheckBox &nbsp;&nbsp;
<span>DVX Widget: checkbox</span>
</div>
<p>
A toggle control with a label. Checked state is exposed as a Boolean.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Caption</code></td><td>String</td><td>The text displayed next to the checkbox.</td></tr>
<tr><td><code>Value</code></td><td>Boolean</td><td>True if checked, False if unchecked.</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<h4>Example</h4>
<pre>
Begin CheckBox Check1
Caption = "Enable feature"
End
Sub Check1_Click ()
If Check1.Value Then
Label1.Caption = "Feature ON"
Else
Label1.Caption = "Feature OFF"
End If
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="optionbutton">OptionButton</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> OptionButton &nbsp;&nbsp;
<span>DVX Widget: radio (radio group + radio button) | Name Prefix: Option</span>
</div>
<p>
A radio button for mutually exclusive choices. DVX uses a radio group
container; individual OptionButtons are children of the group. The
<code>Value</code> property returns the button's index within its group.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Caption</code></td><td>String</td><td>The text displayed next to the radio button.</td></tr>
<tr><td><code>Value</code></td><td>Integer</td><td>The index of this radio button within its group (read-only).</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>SetSelected</code></td><td><code>Index As Integer</code></td><td>Select the radio button at the given index within the group.</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="frame">Frame</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Frame &nbsp;&nbsp;
<span>DVX Widget: frame (titled VBox container)</span>
</div>
<p>
A container with a titled border. Child controls are placed inside the frame
using VBox layout. In the <code>.frm</code> file, nest <code>Begin/End</code>
blocks inside the Frame block.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Caption</code></td><td>String</td><td>The title displayed in the frame border.</td></tr>
</table>
<h4>Container: Yes</h4>
<h4>Default Event: <code>Click</code></h4>
<h4>Example</h4>
<pre>
Begin Frame Frame1
Caption = "Options"
Begin CheckBox Check1
Caption = "Option A"
End
Begin CheckBox Check2
Caption = "Option B"
End
End
</pre>
<!-- ============================================================ -->
<h2 id="vbox">VBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: vbox (vertical layout container)</span>
</div>
<p>
A container that arranges its children vertically, top to bottom. No title
or border. Use <code>Weight</code> on children to distribute extra space.
</p>
<h4>Container: Yes</h4>
<h4>Default Event: <code>Click</code></h4>
<p>No type-specific properties.</p>
<!-- ============================================================ -->
<h2 id="hbox">HBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: hbox (horizontal layout container)</span>
</div>
<p>
A container that arranges its children horizontally, left to right. Use
<code>Weight</code> on children to distribute extra space.
</p>
<h4>Container: Yes</h4>
<h4>Default Event: <code>Click</code></h4>
<p>No type-specific properties.</p>
<!-- ============================================================ -->
<h2 id="listbox">ListBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> ListBox &nbsp;&nbsp;
<span>DVX Widget: listbox</span>
</div>
<p>
A scrollable list of selectable items. Items are managed via methods
(AddItem, RemoveItem, Clear). Supports single and multi-select modes.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>ListIndex</code></td><td>Integer</td><td>Index of the currently selected item (-1 = no selection).</td></tr>
<tr><td><code>ListCount</code></td><td>Integer</td><td>Number of items in the list (read-only).</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>AddItem</code></td><td><code>Text As String</code></td><td>Add an item to the end of the list.</td></tr>
<tr><td><code>RemoveItem</code></td><td><code>Index As Integer</code></td><td>Remove the item at the given index.</td></tr>
<tr><td><code>Clear</code></td><td>(none)</td><td>Remove all items from the list.</td></tr>
<tr><td><code>List</code></td><td><code>Index As Integer</code></td><td>Return the text of the item at the given index.</td></tr>
<tr><td><code>SelectAll</code></td><td>(none)</td><td>Select all items (multi-select mode).</td></tr>
<tr><td><code>ClearSelection</code></td><td>(none)</td><td>Deselect all items.</td></tr>
<tr><td><code>SetMultiSelect</code></td><td><code>Multi As Boolean</code></td><td>Enable or disable multi-select mode.</td></tr>
<tr><td><code>SetReorderable</code></td><td><code>Reorderable As Boolean</code></td><td>Enable or disable drag-to-reorder.</td></tr>
<tr><td><code>IsItemSelected</code></td><td><code>Index As Integer</code></td><td>Returns True if the item at Index is selected.</td></tr>
<tr><td><code>SetItemSelected</code></td><td><code>Index As Integer, Selected As Boolean</code></td><td>Select or deselect a specific item.</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<h4>Example</h4>
<pre>
Sub Form_Load ()
List1.AddItem "Apple"
List1.AddItem "Banana"
List1.AddItem "Cherry"
End Sub
Sub List1_Click ()
Dim idx As Integer
idx = List1.ListIndex
If idx &gt;= 0 Then
Label1.Caption = "Selected: " &amp; List1.List(idx)
End If
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="combobox">ComboBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> ComboBox &nbsp;&nbsp;
<span>DVX Widget: combobox (editable text field + drop-down list, max 256 chars)</span>
</div>
<p>
A combination of a text input and a drop-down list. The user can type
text or select from the list. Supports the same AddItem/RemoveItem/Clear/List
methods as ListBox.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Text</code></td><td>String</td><td>The text in the editable field.</td></tr>
<tr><td><code>ListIndex</code></td><td>Integer</td><td>Index of the currently selected list item (-1 = none).</td></tr>
<tr><td><code>ListCount</code></td><td>Integer</td><td>Number of items in the drop-down list (read-only).</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<p>Same as <a href="#listbox">ListBox</a>: <code>AddItem</code>, <code>RemoveItem</code>, <code>Clear</code>, <code>List</code>.</p>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="dropdown">DropDown</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: dropdown (non-editable drop-down list)</span>
</div>
<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.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>ListIndex</code></td><td>Integer</td><td>Index of the currently selected item.</td></tr>
<tr><td><code>ListCount</code></td><td>Integer</td><td>Number of items (read-only).</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<p>Same as <a href="#listbox">ListBox</a>: <code>AddItem</code>, <code>RemoveItem</code>, <code>Clear</code>, <code>List</code>.</p>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="hscrollbar">HScrollBar</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> HScrollBar &nbsp;&nbsp;
<span>DVX Widget: slider | Name Prefix: HScroll</span>
</div>
<p>
A horizontal slider/scrollbar control. The value ranges between a minimum
and maximum set at creation time (default 0 to 100).
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Value</code></td><td>Integer</td><td>The current slider position (clamped to min/max range).</td></tr>
</table>
<h4>Default Event: <code>Change</code></h4>
<h4>Example</h4>
<pre>
Begin HScrollBar HScroll1
MinWidth = 200
End
Sub HScroll1_Change ()
Label1.Caption = "Value: " &amp; Str$(HScroll1.Value)
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="spinbutton">SpinButton</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: spinner | Name Prefix: Spin</span>
</div>
<p>
A numeric input with up/down buttons. Supports integer mode (default) and
real-number mode with configurable decimal places.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Value</code></td><td>Integer</td><td>Current integer value (in integer mode).</td></tr>
<tr><td><code>RealMode</code></td><td>Boolean</td><td>True to use floating-point mode; False for integer mode.</td></tr>
<tr><td><code>Decimals</code></td><td>Integer</td><td>Number of decimal places shown in real mode.</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>SetRange</code></td><td><code>Min As Integer, Max As Integer</code></td><td>Set the allowed value range.</td></tr>
<tr><td><code>SetStep</code></td><td><code>Step As Integer</code></td><td>Set the increment per button click.</td></tr>
</table>
<h4>Default Event: <code>Change</code></h4>
<!-- ============================================================ -->
<h2 id="timer">Timer</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Timer &nbsp;&nbsp;
<span>DVX Widget: timer (non-visual)</span>
</div>
<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>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Enabled</code></td><td>Boolean</td><td>True to start the timer, False to stop it.</td></tr>
<tr><td><code>Interval</code></td><td>Integer</td><td>Timer interval in milliseconds (write-only from BASIC).</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Start</code></td><td>(none)</td><td>Start the timer.</td></tr>
<tr><td><code>Stop</code></td><td>(none)</td><td>Stop the timer.</td></tr>
</table>
<h4>Type-Specific Events</h4>
<table>
<tr><th>Event</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Timer</code></td><td>(none)</td><td>Fires each time the interval elapses. This is the default event.</td></tr>
</table>
<div class="note">
The Timer control fires the <code>Timer</code> event instead of <code>Change</code>.
The onChange callback on the underlying widget is remapped automatically.
</div>
<h4>Example</h4>
<pre>
Begin Timer Timer1
Interval = 1000
Enabled = True
End
Dim counter As Integer
Sub Timer1_Timer ()
counter = counter + 1
Label1.Caption = "Ticks: " &amp; Str$(counter)
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="picturebox">PictureBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> PictureBox &nbsp;&nbsp;
<span>DVX Widget: canvas | Name Prefix: Picture</span>
</div>
<p>
A drawing surface (canvas). Supports drawing lines, rectangles, circles,
text, and individual pixels. Can save and load BMP images. The default
canvas size is 64x64 pixels.
</p>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Clear</code></td><td><code>Color As Integer</code></td><td>Fill the entire canvas with the specified color.</td></tr>
</table>
<p>
Additional drawing methods (<code>DrawLine</code>, <code>DrawRect</code>,
<code>FillRect</code>, <code>FillCircle</code>, <code>SetPixel</code>,
<code>GetPixel</code>, <code>DrawText</code>, <code>Save</code>,
<code>Load</code>) are available through the C API but not currently
exposed through BASIC interface descriptors.
</p>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="image">Image</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Image &nbsp;&nbsp;
<span>DVX Widget: image</span>
</div>
<p>
A static image display control. Loads BMP images from file. Cannot be
placed via the designer toolbox (requires pixel data at creation time);
typically created in code or loaded via the <code>Picture</code> property.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Picture</code></td><td>String</td><td>Path to a BMP file to load (write-only).</td></tr>
<tr><td><code>ImageWidth</code></td><td>Integer</td><td>Width of the loaded image in pixels (read-only).</td></tr>
<tr><td><code>ImageHeight</code></td><td>Integer</td><td>Height of the loaded image in pixels (read-only).</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="imagebutton">ImageButton</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: imagebutton</span>
</div>
<p>
A button that displays an image instead of text. Like Image, it requires
pixel data at creation time and is typically loaded via the
<code>Picture</code> property.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Picture</code></td><td>String</td><td>Path to a BMP file to load (write-only).</td></tr>
<tr><td><code>ImageWidth</code></td><td>Integer</td><td>Width of the loaded image in pixels (read-only).</td></tr>
<tr><td><code>ImageHeight</code></td><td>Integer</td><td>Height of the loaded image in pixels (read-only).</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="progressbar">ProgressBar</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> ProgressBar &nbsp;&nbsp;
<span>DVX Widget: progressbar</span>
</div>
<p>
A horizontal progress indicator bar.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Value</code></td><td>Integer</td><td>Current progress value (0-100).</td></tr>
</table>
<p>No type-specific events or methods. No default event.</p>
<!-- ============================================================ -->
<h2 id="listview">ListView</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> ListView &nbsp;&nbsp;
<span>DVX Widget: listview</span>
</div>
<p>
A multi-column list with column headers. Supports sorting, multi-select,
and drag-to-reorder. Columns are configured via the C API (SetColumns,
SetData).
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>ListIndex</code></td><td>Integer</td><td>Index of the currently selected row (-1 = none).</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>SelectAll</code></td><td>(none)</td><td>Select all rows.</td></tr>
<tr><td><code>ClearSelection</code></td><td>(none)</td><td>Deselect all rows.</td></tr>
<tr><td><code>SetMultiSelect</code></td><td><code>Multi As Boolean</code></td><td>Enable or disable multi-select.</td></tr>
<tr><td><code>SetReorderable</code></td><td><code>Reorderable As Boolean</code></td><td>Enable or disable row reordering.</td></tr>
<tr><td><code>IsItemSelected</code></td><td><code>Index As Integer</code></td><td>Returns True if the row at Index is selected.</td></tr>
<tr><td><code>SetItemSelected</code></td><td><code>Index As Integer, Selected As Boolean</code></td><td>Select or deselect a specific row.</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="treeview">TreeView</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> TreeView &nbsp;&nbsp;
<span>DVX Widget: treeview</span>
</div>
<p>
A hierarchical tree of expandable/collapsible nodes. Nodes are created
via the C API (<code>wgtTreeItem</code>). Supports multi-select and
drag-to-reorder.
</p>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>SetMultiSelect</code></td><td><code>Multi As Boolean</code></td><td>Enable or disable multi-select mode.</td></tr>
<tr><td><code>SetReorderable</code></td><td><code>Reorderable As Boolean</code></td><td>Enable or disable node reordering.</td></tr>
</table>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="tabstrip">TabStrip</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> TabStrip &nbsp;&nbsp;
<span>DVX Widget: tabcontrol</span>
</div>
<p>
A tabbed container. Each tab page is a separate container that holds
child controls. Switching tabs shows one page and hides others.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>TabIndex</code></td><td>Integer</td><td>Index of the active tab (0-based). <strong>Note:</strong> this property name collides with the common VB-compatibility <code>TabIndex</code> property, which shadows it at runtime. Use the <code>SetActive</code> method instead to switch tabs.</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>SetActive</code></td><td><code>Index As Integer</code></td><td>Switch to the tab at the given index. This is the recommended way to change tabs at runtime (the <code>TabIndex</code> property is shadowed by the common property handler).</td></tr>
</table>
<h4>Container: Yes</h4>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="splitter">Splitter</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: splitter</span>
</div>
<p>
A resizable split pane. Holds exactly two child widgets separated by a
draggable divider. Default orientation is vertical (top/bottom split).
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Position</code></td><td>Integer</td><td>Position of the divider in pixels from the top (or left).</td></tr>
</table>
<h4>Container: Yes</h4>
<p>No default event.</p>
<!-- ============================================================ -->
<h2 id="scrollpane">ScrollPane</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: scrollpane | Name Prefix: Scroll</span>
</div>
<p>
A scrollable container. Place child controls inside and the ScrollPane
automatically provides scrollbars when the content exceeds the visible area.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>NoBorder</code></td><td>Boolean</td><td>When True, suppresses the border around the scroll pane.</td></tr>
</table>
<h4>Container: Yes</h4>
<p>No default event.</p>
<!-- ============================================================ -->
<h2 id="wrapbox">WrapBox</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: wrapbox</span>
</div>
<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
<code>flex-wrap: wrap</code>.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Alignment</code></td><td>Enum</td><td>Horizontal alignment of items: <code>Left</code>, <code>Center</code>, or <code>Right</code>.</td></tr>
</table>
<h4>Container: Yes</h4>
<h4>Default Event: <code>Click</code></h4>
<!-- ============================================================ -->
<h2 id="line">Line</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Line &nbsp;&nbsp;
<span>DVX Widget: separator</span>
</div>
<p>
A visual separator line. The underlying widget supports both horizontal
and vertical orientations. The default (via BASIC) is horizontal.
</p>
<p>No type-specific properties, events, or methods.</p>
<!-- ============================================================ -->
<h2 id="spacer">Spacer</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: spacer</span>
</div>
<p>
An invisible layout spacer. Takes up space in the layout without rendering
anything. Useful for pushing controls apart. Give it a <code>Weight</code>
to absorb extra space.
</p>
<p>No type-specific properties, events, or methods.</p>
<!-- ============================================================ -->
<h2 id="toolbar">Toolbar</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Toolbar &nbsp;&nbsp;
<span>DVX Widget: toolbar</span>
</div>
<p>
A horizontal container styled as a toolbar, with compact padding and
spacing. Place buttons, labels, or other controls inside.
</p>
<h4>Container: Yes</h4>
<p>No type-specific properties, events, or methods.</p>
<!-- ============================================================ -->
<h2 id="statusbar">StatusBar</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> StatusBar &nbsp;&nbsp;
<span>DVX Widget: statusbar</span>
</div>
<p>
A horizontal container styled as a status bar, typically placed at the
bottom of a form. At the C API level it accepts child widgets, but it
is not registered as a container in the form runtime, so child controls
cannot be nested inside it in <code>.frm</code> files. Set its
<code>Caption</code> property to display status text.
</p>
<p>No type-specific properties, events, or methods.</p>
<!-- ============================================================ -->
<h2 id="terminal">Terminal</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>DVX Extension</strong> &nbsp;&nbsp;
<span>DVX Widget: ansiterm (ANSI terminal emulator)</span>
</div>
<p>
A VT100/ANSI terminal emulator widget. Supports ANSI escape sequences,
scrollback buffer, and serial communication. Default size is 80 columns
by 25 rows.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Cols</code></td><td>Integer</td><td>Number of character columns (read-only).</td></tr>
<tr><td><code>Rows</code></td><td>Integer</td><td>Number of character rows (read-only).</td></tr>
<tr><td><code>Scrollback</code></td><td>Integer</td><td>Number of scrollback lines (write-only).</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Clear</code></td><td>(none)</td><td>Clear the terminal screen.</td></tr>
<tr><td><code>Write</code></td><td><code>Text As String</code></td><td>Write text (with ANSI escape processing) to the terminal.</td></tr>
</table>
<p>No default event.</p>
<!-- ============================================================ -->
<h2 id="data">Data</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> Data &nbsp;&nbsp;
<span>DVX Widget: data (database record navigator)</span>
</div>
<p>
A data access control that connects to a SQLite database and provides
record navigation. Other controls can bind to a Data control via their
<code>DataSource</code> and <code>DataField</code> properties.
See the <a href="#databinding">Data Binding</a> section for details.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>R/W</th><th>Description</th></tr>
<tr><td><code>DatabaseName</code></td><td>String</td><td>R/W</td><td>Path to the SQLite database file.</td></tr>
<tr><td><code>RecordSource</code></td><td>String</td><td>R/W</td><td>Table name or SQL SELECT query for the recordset.</td></tr>
<tr><td><code>KeyColumn</code></td><td>String</td><td>R/W</td><td>Primary key column name (used for UPDATE/DELETE operations).</td></tr>
<tr><td><code>Caption</code></td><td>String</td><td>R/W</td><td>Text displayed on the navigator bar.</td></tr>
<tr><td><code>BOF</code></td><td>Boolean</td><td>R</td><td>True if the current position is before the first record (read-only).</td></tr>
<tr><td><code>EOF</code></td><td>Boolean</td><td>R</td><td>True if the current position is past the last record (read-only).</td></tr>
<tr><td><code>MasterSource</code></td><td>String</td><td>R/W</td><td>Name of a master Data control (for master-detail binding).</td></tr>
<tr><td><code>MasterField</code></td><td>String</td><td>R/W</td><td>Column in the master recordset to filter by.</td></tr>
<tr><td><code>DetailField</code></td><td>String</td><td>R/W</td><td>Column in this recordset that matches the master field.</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>MoveFirst</code></td><td>(none)</td><td>Navigate to the first record.</td></tr>
<tr><td><code>MoveLast</code></td><td>(none)</td><td>Navigate to the last record.</td></tr>
<tr><td><code>MoveNext</code></td><td>(none)</td><td>Navigate to the next record.</td></tr>
<tr><td><code>MovePrevious</code></td><td>(none)</td><td>Navigate to the previous record.</td></tr>
<tr><td><code>AddNew</code></td><td>(none)</td><td>Add a new blank record.</td></tr>
<tr><td><code>Delete</code></td><td>(none)</td><td>Delete the current record.</td></tr>
<tr><td><code>Refresh</code></td><td>(none)</td><td>Re-query the database and reload records.</td></tr>
<tr><td><code>Update</code></td><td>(none)</td><td>Write pending changes to the database.</td></tr>
</table>
<h4>Type-Specific Events</h4>
<table>
<tr><th>Event</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Reposition</code></td><td>(none)</td><td>Fires after the current record changes (navigation). This is the default event.</td></tr>
<tr><td><code>Validate</code></td><td><code>Cancel As Integer</code></td><td>Fires before writing a record. Set <code>Cancel = 1</code> to abort.</td></tr>
</table>
<!-- ============================================================ -->
<h2 id="dbgrid">DBGrid</h2>
<!-- ============================================================ -->
<div class="ctrl-header">
<strong>VB Equivalent:</strong> DBGrid &nbsp;&nbsp;
<span>DVX Widget: dbgrid</span>
</div>
<p>
A data-bound grid that displays records from a Data control in a tabular
format. Columns are auto-generated from the query results. Bind it using
the <code>DataSource</code> property.
</p>
<h4>Type-Specific Properties</h4>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>DataSource</code></td><td>String</td><td>Name of the Data control that supplies records.</td></tr>
<tr><td><code>GridLines</code></td><td>Boolean</td><td>Show or hide grid lines between cells.</td></tr>
</table>
<h4>Type-Specific Methods</h4>
<table>
<tr><th>Method</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Refresh</code></td><td>(none)</td><td>Reload and redraw the grid from the Data control.</td></tr>
</table>
<h4>Type-Specific Events</h4>
<table>
<tr><th>Event</th><th>Parameters</th><th>Description</th></tr>
<tr><td><code>Click</code></td><td>(none)</td><td>Fires when a cell is clicked.</td></tr>
<tr><td><code>DblClick</code></td><td>(none)</td><td>Fires when a cell is double-clicked. This is the default event.</td></tr>
</table>
<!-- ============================================================ -->
<h2 id="databinding">Data Binding</h2>
<!-- ============================================================ -->
<p>
DVX BASIC provides VB3-style data binding through three properties that can
be set on most controls:
</p>
<table>
<tr><th>Property</th><th>Set On</th><th>Description</th></tr>
<tr><td><code>DataSource</code></td><td>Any control</td><td>Name of the Data control to bind to (e.g. "Data1").</td></tr>
<tr><td><code>DataField</code></td><td>Any control</td><td>Column name from the Data control's recordset to display.</td></tr>
</table>
<h3>How It Works</h3>
<ol>
<li>Place a <strong>Data</strong> control on the form and set its <code>DatabaseName</code>
and <code>RecordSource</code> properties.</li>
<li>Place one or more display/edit controls (TextBox, Label, etc.) and set
their <code>DataSource</code> to the Data control's name and
<code>DataField</code> 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 <code>Reposition</code> event fires, and the runtime
pushes the current record's field values into all bound controls).</li>
<li>When a bound control loses focus (<code>LostFocus</code>), its current
text is written back to the Data control's record cache, and
<code>Update</code> is called automatically to persist changes.</li>
</ol>
<h3>Master-Detail Binding</h3>
<p>
For hierarchical data (e.g. orders and order items), use two Data controls:
</p>
<ol>
<li>A <strong>master</strong> Data control bound to the parent table.</li>
<li>A <strong>detail</strong> Data control with its <code>MasterSource</code>
set to the master's name, <code>MasterField</code> set to the key column
in the master, and <code>DetailField</code> set to the foreign key column
in the detail table.</li>
</ol>
<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>
<h3>DBGrid Binding</h3>
<p>
Set the DBGrid's <code>DataSource</code> to a Data control name. The grid
auto-populates columns from the query results and refreshes whenever the
Data control refreshes.
</p>
<h4>Example</h4>
<pre>
VERSION DVX 1.00
Begin Form frmData
Caption = "Data Binding Example"
AutoSize = False
Width = 400
Height = 280
Begin Data Data1
DatabaseName = "myapp.db"
RecordSource = "customers"
End
Begin Label lblName
Caption = "Name:"
End
Begin TextBox txtName
DataSource = "Data1"
DataField = "name"
End
Begin Label lblEmail
Caption = "Email:"
End
Begin TextBox txtEmail
DataSource = "Data1"
DataField = "email"
End
End
Sub Data1_Reposition ()
Print "Current record changed"
End Sub
Sub Data1_Validate (Cancel As Integer)
If txtName.Text = "" Then
MsgBox "Name cannot be empty!"
Cancel = 1
End If
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="menus">Menu System</h2>
<!-- ============================================================ -->
<p>
Menus are defined in the <code>.frm</code> file using <code>Begin Menu</code>
blocks. Each menu item has a name, caption, and nesting level. Menu items
fire <code>Click</code> events dispatched as
<code><em>MenuName</em>_Click</code>.
</p>
<h3>FRM Syntax</h3>
<pre>
Begin Form Form1
Caption = "Menu Demo"
Begin Menu mnuFile
Caption = "&amp;File"
Begin Menu mnuOpen
Caption = "&amp;Open"
End
Begin Menu mnuSave
Caption = "&amp;Save"
End
Begin Menu mnuSep1
Caption = "-"
End
Begin Menu mnuExit
Caption = "E&amp;xit"
End
End
Begin Menu mnuEdit
Caption = "&amp;Edit"
Begin Menu mnuCopy
Caption = "&amp;Copy"
End
Begin Menu mnuPaste
Caption = "&amp;Paste"
End
End
End
</pre>
<h3>Menu Item Properties</h3>
<table>
<tr><th>Property</th><th>Type</th><th>Description</th></tr>
<tr><td><code>Caption</code></td><td>String</td><td>The text displayed. Use <code>&amp;</code> for accelerator key. Set to <code>"-"</code> for a separator.</td></tr>
<tr><td><code>Checked</code></td><td>Boolean</td><td>Whether the menu item shows a checkmark.</td></tr>
<tr><td><code>Enabled</code></td><td>Boolean</td><td>Whether the menu item is enabled (default True).</td></tr>
</table>
<h3>Nesting</h3>
<p>
Menu items are nested by placing <code>Begin Menu</code> blocks inside
other <code>Begin Menu</code> blocks:
</p>
<ul>
<li>Level 0: top-level menu bar headers (e.g. "File", "Edit").</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>
<h3>Event Dispatch</h3>
<p>
Each clickable menu item (not headers, not separators) receives a unique
numeric ID at load time. When clicked, the form's <code>onMenu</code>
handler maps the ID to the menu item's name and fires
<code><em>MenuName</em>_Click</code>.
</p>
<pre>
Sub mnuOpen_Click ()
MsgBox "Open was clicked"
End Sub
Sub mnuExit_Click ()
Unload Form1
End Sub
</pre>
<!-- ============================================================ -->
<h2 id="controlarrays">Control Arrays</h2>
<!-- ============================================================ -->
<p>
DVX BASIC supports VB-style control arrays. Multiple controls can share
the same name, differentiated by an <code>Index</code> property. When an
event fires on a control array element, the element's index is passed as
the first parameter.
</p>
<h3>Defining Control Arrays in FRM</h3>
<pre>
Begin CommandButton Command1
Caption = "Button A"
Index = 0
End
Begin CommandButton Command1
Caption = "Button B"
Index = 1
End
Begin CommandButton Command1
Caption = "Button C"
Index = 2
End
</pre>
<h3>Event Handler Convention</h3>
<p>
When a control has an <code>Index</code> property (>= 0), the event handler
receives <code>Index As Integer</code> as the first parameter, before any
event-specific parameters.
</p>
<pre>
Sub Command1_Click (Index As Integer)
Select Case Index
Case 0
MsgBox "Button A clicked"
Case 1
MsgBox "Button B clicked"
Case 2
MsgBox "Button C clicked"
End Select
End Sub
</pre>
<h3>Accessing Array Elements in Code</h3>
<p>
Use the indexed form <code><em>ControlName</em>(Index)</code> to access
a specific element:
</p>
<pre>
Command1(0).Caption = "New Text"
Command1(1).Enabled = False
</pre>
<div class="note">
Control array elements share the same event handler Sub. The runtime
prepends the Index argument automatically. If you define parameters on
the Sub, Index comes first, followed by the event's own parameters
(e.g. <code>KeyPress</code> would be
<code>Sub Ctrl1_KeyPress (Index As Integer, KeyAscii As Integer)</code>).
</div>
<!-- ============================================================ -->
<h2 id="frm-format">FRM File Format</h2>
<!-- ============================================================ -->
<p>
The <code>.frm</code> 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>
<h3>Structure</h3>
<pre>
VERSION DVX 1.00
Begin Form FormName
<em>form-level properties...</em>
Begin Menu mnuFile
Caption = "&amp;File"
Begin Menu mnuOpen
Caption = "&amp;Open"
End
End
Begin <em>TypeName</em> <em>ControlName</em>
<em>property = value</em>
...
End
Begin Frame Frame1
Caption = "Group"
Begin <em>TypeName</em> <em>ChildName</em>
...
End
End
End
<em>BASIC code follows...</em>
Sub FormName_Load ()
...
End Sub
</pre>
<h3>Rules</h3>
<ul>
<li>The <code>VERSION</code> line is optional. <code>VERSION DVX 1.00</code> marks a native DVX form.
VB forms with version &lt;= 2.0 are accepted for import.</li>
<li>The form block begins with <code>Begin Form <em>Name</em></code> and ends with <code>End</code>.</li>
<li>Controls are nested with <code>Begin <em>TypeName</em> <em>Name</em></code> / <code>End</code>.</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 <code>Key = Value</code>. String values are optionally quoted.</li>
<li>Everything after the form's closing <code>End</code> is BASIC source code.</li>
<li>Comments in the form section use <code>'</code> (single quote).</li>
<li>Blank lines are ignored in the form section.</li>
</ul>
<h3>Common FRM Properties</h3>
<table>
<tr><th>Property</th><th>Applies To</th><th>Description</th></tr>
<tr><td><code>Caption</code></td><td>Form, controls</td><td>Display text or window title.</td></tr>
<tr><td><code>Text</code></td><td>TextBox, ComboBox</td><td>Initial text content.</td></tr>
<tr><td><code>MinWidth</code> / <code>Width</code></td><td>Controls</td><td>Minimum width. Both names are accepted.</td></tr>
<tr><td><code>MinHeight</code> / <code>Height</code></td><td>Controls</td><td>Minimum height. Both names are accepted.</td></tr>
<tr><td><code>MaxWidth</code></td><td>Controls</td><td>Maximum width (0 = no cap).</td></tr>
<tr><td><code>MaxHeight</code></td><td>Controls</td><td>Maximum height (0 = no cap).</td></tr>
<tr><td><code>Weight</code></td><td>Controls</td><td>Layout weight for flexible sizing.</td></tr>
<tr><td><code>Left</code></td><td>Form, controls</td><td>X position (used by Form when Centered=False; informational for controls).</td></tr>
<tr><td><code>Top</code></td><td>Form, controls</td><td>Y position.</td></tr>
<tr><td><code>Index</code></td><td>Controls</td><td>Control array index (-1 or absent = not in array).</td></tr>
<tr><td><code>Visible</code></td><td>Controls</td><td>Initial visibility.</td></tr>
<tr><td><code>Enabled</code></td><td>Controls</td><td>Initial enabled state.</td></tr>
<tr><td><code>Layout</code></td><td>Form</td><td>"VBox" or "HBox".</td></tr>
<tr><td><code>AutoSize</code></td><td>Form</td><td>Auto-fit window to content.</td></tr>
<tr><td><code>Resizable</code></td><td>Form</td><td>Allow runtime resizing.</td></tr>
<tr><td><code>Centered</code></td><td>Form</td><td>Center window on screen.</td></tr>
<tr><td><code>DatabaseName</code></td><td>Data</td><td>SQLite database file path.</td></tr>
<tr><td><code>RecordSource</code></td><td>Data</td><td>Table name or SQL query.</td></tr>
<tr><td><code>DataSource</code></td><td>Bound controls</td><td>Name of the Data control.</td></tr>
<tr><td><code>DataField</code></td><td>Bound controls</td><td>Column name in the recordset.</td></tr>
</table>
<hr>
<p style="color: #888; font-size: 0.85em; margin-top: 30px;">
DVX BASIC Control Reference -- Generated from source code analysis of
formrt.c, ideProperties.c, ideDesigner.c, and widget DXE interface descriptors.
</p>
</body>
</html>