WinComm/forms/protocol.md
Scott Duensing 3b4d97b0dc Reorganize Properties sections by control type
Replaces the flat per-property layout in protocol.md and README.md
with per-control subsections, each listing its supported properties.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 16:23:49 -06:00

12 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)
SelectCell <col> <row>
SetEditText <col> <row> "text"

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)
StringGrid TStringGrid SelectCell

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), SetEditText (StringGrid), DblClick, KeyDown, KeyUp, Enter, Exit, MouseDown, MouseUp, MouseMove. Menu and RadioGroup components do not support opt-in events.

Properties

Common Properties

Property Applies To Format
Enabled All 0 or 1
Visible All 0 or 1
TabOrder All windowed Integer
PopupMenu Any TControl Integer (ctrlId of PopupMenu)

Label, Button, GroupBox

Property Format
Caption Quoted string

Edit

Property Format
Text Quoted string
MaxLength Integer
ReadOnly 0 or 1

CheckBox, RadioButton

Property Format
Caption Quoted string
Checked 0 or 1

ListBox

Property Format
Items Quoted string (\n-delimited)
ItemIndex Integer (-1 = none)

ComboBox

Property Format
Text Quoted string
Items Quoted string (\n-delimited)
ItemIndex Integer (-1 = none)

Memo

Property Format
Text Quoted string (\n for line breaks)
ReadOnly 0 or 1
ScrollBars 0-3 (ssNone..ssBoth)

Image

Property Format
Picture Quoted string (filename, BMP only)
Stretch 0 or 1
Center 0 or 1
Transparent 0 or 1

File path resolved relative to client's BasePath setting.

Panel

Property Format
Caption Quoted string
BevelOuter 0-2 (bvNone, bvLowered, bvRaised)
BevelInner 0-2 (bvNone, bvLowered, bvRaised)
BorderStyle 0-1 (bsNone, bsSingle)

ScrollBar

Property Format
Kind 0 (sbHorizontal), 1 (sbVertical)
Min Integer
Max Integer
Position Integer
LargeChange Integer
SmallChange Integer

MediaPlayer

Property Format
FileName Quoted string (media file path)
DeviceType Quoted string (e.g., dtWaveAudio)
AutoOpen 0 or 1
Command Quoted string (pseudo-property)

File path resolved relative to client's BasePath setting.

Command triggers a method call rather than setting a value. Valid commands: Open, Play, Stop, Close, Pause, Resume, Rewind, Next, Previous.

MainMenu, PopupMenu

No type-specific properties. One MainMenu per form (auto-attached). PopupMenu is associated with controls via the common PopupMenu property.

MenuItem

Property Format
Caption Quoted string
Parent Integer (ctrlId of parent menu/item)
Checked 0 or 1
ShortCut Integer (Delphi ShortCut value)

RadioGroup

Property Format
Caption Quoted string
Items Quoted string (\n-delimited)
ItemIndex Integer (-1 = none)
Columns Integer

BitBtn

Property Format
Caption Quoted string
Kind 0-10 (bkCustom..bkAll)
Layout 0-3 (blGlyphLeft..blGlyphBottom)
NumGlyphs Integer (1-4)

SpeedButton

Property Format
Caption Quoted string
Layout 0-3 (blGlyphLeft..blGlyphBottom)
NumGlyphs Integer (1-4)
GroupIndex Integer (0 = no group)
Down 0 or 1
AllowAllUp 0 or 1

TabSet, Notebook, TabbedNotebook

Property Format
Items Quoted string (\n-delimited)
ItemIndex Integer (-1 = none)

MaskEdit

Property Format
Text Quoted string
MaxLength Integer
EditMask Quoted string

Outline

Property Format
Items Quoted string (\n-delimited)
OutlineStyle 0-6 (osText..osTreePictureText)

Bevel

Property Format
Shape 0-5 (bsBox..bsRightLine)
Style 0-1 (bsLowered, bsRaised)

Header

Property Format
Items Quoted string (\n-delimited)

ScrollBox

No type-specific properties.

StringGrid

Property Format
ColCount Integer (default 5)
RowCount Integer (default 5)
FixedCols Integer (default 1)
FixedRows Integer (default 1)
DefaultColWidth Integer (pixels)
DefaultRowHeight Integer (pixels)
Options Integer (bitmask, see below)
Cells Quoted string (tab-delimited cols, \n-delimited rows)
Cell Quoted string (col,row,value)

Options is an integer bitmask of TGridOption values:

Bit Value Option
0 0x0001 goFixedVertLine
1 0x0002 goFixedHorzLine
2 0x0004 goVertLine
3 0x0008 goHorzLine
4 0x0010 goRangeSelect
5 0x0020 goDrawFocusSelected
6 0x0040 goRowSizing
7 0x0080 goColSizing
8 0x0100 goRowMoving
9 0x0200 goColMoving
10 0x0400 goEditing
11 0x0800 goTabs
12 0x1000 goThumbTracking

Cells is a bulk-load property: columns are tab-delimited, rows are \n-delimited. Cell is an individual update: "col,row,value".

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 \n within 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.