Completes the Delphi 1.0 Standard, Additional, and Win31 component palettes. DFM parser maps Tabs/Lines/Pages/Sections.Strings to Items and TabIndex/PageIndex to ItemIndex. Kind extended with bk* idents for BitBtn. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
10 KiB
Remote Forms Protocol
Overview
Text-based protocol for remote GUI. A C server on Linux sends form/control commands over a transport layer; a Delphi 1.0 client on Windows 3.1 creates native controls and sends user events back.
Message Format
- One command per message.
- Transport delivers whole messages (today: newline-delimited over serial).
- Strings are double-quoted with escapes:
\"\\\n\r\t. - Bare tokens (IDs, numbers, type names) are whitespace-delimited.
- IDs are positive integers assigned by the server.
Server → Client Commands
FORM.CREATE
FORM.CREATE <formId> <width> <height> "<title>"
Create a new form with the given dimensions and title. The form is not shown until FORM.SHOW is sent.
FORM.SHOW
FORM.SHOW <formId>
FORM.HIDE
FORM.HIDE <formId>
FORM.DESTROY
FORM.DESTROY <formId>
Free the form and all its controls.
CTRL.CREATE
CTRL.CREATE <formId> <ctrlId> <type> <left> <top> <width> <height> [Key="val" ...]
Create a control on the specified form. Inline key/value properties are applied immediately after creation. See Control Types and Properties below.
CTRL.SET
CTRL.SET <formId> <ctrlId> Key="val" [Key="val" ...]
Update one or more properties on an existing control.
EVENT.BIND
EVENT.BIND <formId> <ctrlId> <eventName>
Wire an opt-in event handler. Auto-wired events do not need explicit binding.
EVENT.UNBIND
EVENT.UNBIND <formId> <ctrlId> <eventName>
Remove an event handler.
Client → Server Events
EVENT <formId> <ctrlId> <eventName> [<data>]
Event data varies by event type:
| Event | Data |
|---|---|
| Click | (none), or <itemIndex> (RadioGroup) |
| DblClick | (none) |
| Change | "new text", <position> (ScrollBar), or <index> (TabSet, TabbedNotebook) |
| Select | <index> "selected text" |
| KeyDown | <vkCode> |
| KeyUp | <vkCode> |
| MouseDown | <x> <y> <button> |
| MouseUp | <x> <y> <button> |
| MouseMove | <x> <y> <button> |
| Enter | (none) |
| Exit | (none) |
| Close | (none) |
| Notify | (none) |
Control Types
| Type | Delphi Class | Auto-wired Events |
|---|---|---|
| Label | TLabel | (none) |
| Edit | TEdit | Change |
| Button | TButton | Click |
| CheckBox | TCheckBox | Click |
| ListBox | TListBox | Select |
| ComboBox | TComboBox | Select, Change |
| Memo | TMemo | Change |
| Image | TImage | (none) |
| GroupBox | TGroupBox | (none) |
| RadioButton | TRadioButton | Click |
| Panel | TPanel | (none) |
| ScrollBar | TScrollBar | Change |
| MediaPlayer | TMediaPlayer | (none) |
| MainMenu | TMainMenu | (none) |
| PopupMenu | TPopupMenu | (none) |
| MenuItem | TMenuItem | Click |
| RadioGroup | TRadioGroup | Click |
| BitBtn | TBitBtn | Click |
| SpeedButton | TSpeedButton | Click |
| TabSet | TTabSet | Change |
| Notebook | TNotebook | (none) |
| TabbedNotebook | TTabbedNotebook | Change |
| MaskEdit | TMaskEdit | Change |
| Outline | TOutline | (none) |
| Bevel | TBevel | (none) |
| Header | THeader | (none) |
| ScrollBox | TScrollBox | (none) |
MainMenu and PopupMenu use 0 0 0 0 geometry (non-visual). MenuItem
uses 0 0 0 0 geometry and requires a Parent property to specify its
parent menu or menu item. One MainMenu per form (auto-attached).
PopupMenu is associated with any control via the PopupMenu property.
GroupBox and Panel are cosmetic containers (flat parent model — no child containment in the protocol). RadioButtons are all in one group per form.
Opt-in events (require EVENT.BIND): Click (Image, GroupBox, Panel), Notify (MediaPlayer), DblClick, KeyDown, KeyUp, Enter, Exit, MouseDown, MouseUp, MouseMove. Menu and RadioGroup components do not support opt-in events.
Properties
| Property | Applies To | Value Format |
|---|---|---|
| Caption | Label, Button, CheckBox, GroupBox, RadioButton, Panel, MenuItem, RadioGroup, BitBtn, SpeedButton | Quoted string |
| Text | Edit, ComboBox, Memo, MaskEdit | Quoted string (\n for line breaks) |
| Items | ListBox, ComboBox, RadioGroup, TabSet, Notebook, TabbedNotebook, Outline, Header | Quoted string (\n-delimited) |
| Checked | CheckBox, RadioButton, MenuItem | 0 or 1 |
| Enabled | All | 0 or 1 |
| Visible | All | 0 or 1 |
| MaxLength | Edit, MaskEdit | Integer |
| ReadOnly | Edit, Memo | 0 or 1 |
| ScrollBars | Memo | 0-3 (ssNone..ssBoth) |
| ItemIndex | ListBox, ComboBox, RadioGroup, TabSet, Notebook, TabbedNotebook | Integer (-1 = none) |
| TabOrder | All windowed controls | Integer |
| Stretch | Image | 0 or 1 |
| Center | Image | 0 or 1 |
| Transparent | Image | 0 or 1 |
| Picture | Image | Quoted string (filename, BMP only) |
| BevelOuter | Panel | 0-2 (bvNone, bvLowered, bvRaised) |
| BevelInner | Panel | 0-2 (bvNone, bvLowered, bvRaised) |
| BorderStyle | Panel | 0-1 (bsNone, bsSingle) |
| Kind | ScrollBar, BitBtn | Integer (see below) |
| Min | ScrollBar | Integer |
| Max | ScrollBar | Integer |
| Position | ScrollBar | Integer |
| LargeChange | ScrollBar | Integer |
| SmallChange | ScrollBar | Integer |
| FileName | MediaPlayer | Quoted string (media file path) |
| DeviceType | MediaPlayer | Quoted string (e.g., dtWaveAudio) |
| AutoOpen | MediaPlayer | 0 or 1 |
| Command | MediaPlayer | Quoted string (pseudo-property, see below) |
| Parent | MenuItem | Integer (ctrlId of parent menu/item) |
| Columns | RadioGroup | Integer (number of columns) |
| ShortCut | MenuItem | Integer (Delphi ShortCut value) |
| PopupMenu | Any TControl | Integer (ctrlId of PopupMenu) |
| Layout | BitBtn, SpeedButton | 0-3 (blGlyphLeft..blGlyphBottom) |
| NumGlyphs | BitBtn, SpeedButton | Integer (1-4) |
| GroupIndex | SpeedButton | Integer (0 = no group) |
| Down | SpeedButton | 0 or 1 |
| AllowAllUp | SpeedButton | 0 or 1 |
| EditMask | MaskEdit | Quoted string |
| OutlineStyle | Outline | 0-6 (osText..osTreePictureText) |
| Shape | Bevel | 0-5 (bsBox..bsRightLine) |
| Style | Bevel | 0-1 (bsLowered, bsRaised) |
File path properties (Picture, FileName) are resolved relative to the
client's BasePath setting. Subdirectories are allowed (e.g.,
Picture="images\logo.bmp" with BasePath=C:\MYAPP resolves to
C:\MYAPP\images\logo.bmp).
Command is a pseudo-property that triggers a method call on the
MediaPlayer rather than setting a value. Valid commands: Open,
Play, Stop, Close, Pause, Resume, Rewind, Next,
Previous.
String Encoding
- Strings in the protocol are always double-quoted.
- Escape sequences:
\"(literal quote),\\(literal backslash),\n(newline),\r(carriage return),\t(tab). - Multi-line values (Memo text, ListBox items) use
\nwithin a single quoted string.
Transport Layer
The protocol is transport-agnostic. Messages are delivered via:
int ReadMessage(char *buf, int maxLen); // returns bytes read, 0 = none
void WriteMessage(const char *buf); // sends complete message
Current transport: newline-delimited serial (messages terminated by CR+LF). The transport handles framing; protocol layer never sees delimiters.