From f942f8d64a3a15918101dc61889b5b89ea38773c Mon Sep 17 00:00:00 2001 From: Kuba Sunderland-Ober Date: Wed, 13 May 2026 16:00:27 +0200 Subject: [PATCH 1/4] Update the WIP before documenting the CustomControls package. --- WIP.md | 188 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 182 insertions(+), 6 deletions(-) diff --git a/WIP.md b/WIP.md index e9948b9f..c5c84d24 100644 --- a/WIP.md +++ b/WIP.md @@ -12,7 +12,8 @@ Status: - **VBRUN package** — done. - **VB package** — done. - **WebView2Package** — done. -- **Assert package** — in progress. +- **Assert package** — done. +- **CustomControls / CustomControlsPackage** — in progress. ## Where things live @@ -23,6 +24,7 @@ Status: - `docs/Reference/VB//index.md` — folder-style class page when sub-pages may follow (e.g. [`CheckMark/index.md`](docs/Reference/VB/CheckMark/index.md)). - `docs/Reference/VB/todo.md` — backlog tracker for the VB package; see [Backlog discovery](#backlog-discovery). - `docs/Reference/WebView2/` — WebView2 package: the **WebView2** control class plus its small wrapper classes (request / response / headers / environment options) and the `wv2…` enumerations. +- `docs/Reference/CustomControls/` — CustomControls package: the eight **Waynes…** custom controls, their shared `Styles/` helper classes (`Fill`, `Borders`, `Corners`, `TextRendering`, …), the `Framework/` DESIGNER surface (interfaces, CoClasses, the `Canvas` / `SerializeInfo` UDTs), and the `Enumerations/` (`CornerShape`, `FillPattern`, `DockMode`, …). - `docs/Reference/Statements.md` — alphabetical index of language statements. - `docs/Reference/Procedures and Functions.md` — alphabetical index of procedures/functions. - `docs/_includes/footer_custom.html` — overrides the theme's footer slot; renders the copyright line and, when `vba_attribution: true` is set in a page's frontmatter, an additional CC-BY-4.0 attribution line beneath it. @@ -51,6 +53,8 @@ All of twinbasic's package sources are at: ..\tb-export\NewProject\Packages\VBRUN\Sources\ ..\tb-export\NewProject\Packages\WebView2Package\Sources\ ..\tb-export\NewProject\Packages\Assert\Sources\ +..\tb-export\NewProject\Packages\CustomControls\Sources\ +..\tb-export\NewProject\Packages\CustomControlsPackage\Sources\ etc. ``` @@ -169,6 +173,138 @@ That's 4 pages total. (If a future release of the package adds more modules or n **No backlog file** — three modules listed in this section are the entire backlog. +### CustomControls / CustomControlsPackage + +Two source-side packages, **one** doc-side package. They always ship together and are co-versioned with twinBASIC — `CustomControlsPackage` lists `CustomControls` as a `isCompilerPackage` reference in its `Settings`, and neither is usable without the other. Document the union as `docs/Reference/CustomControls/`. + +The split on the source side is by *role*: + +- `..\tb-export\NewProject\Packages\CustomControls\Sources\CustomControls.twin` — the **DESIGNER** framework. A single file with `Module Constants` (the enums + the `SerializeInfo` / `Canvas` UDTs) plus the abstract surface a custom control hooks into (`ICustomControl`, `ICustomForm` interfaces; `CustomControlContext`, `CustomFormContext`, `CustomControlTimer`, `CustomControlsCollection` CoClasses). Project `appTitle` is `"CustomControls DESIGNER Package"`. +- `..\tb-export\NewProject\Packages\CustomControlsPackage\Sources\` — the **runtime**: eight concrete `Waynes…` controls plus `zTemporarySupport.twin`, a bag of shared appearance helpers and three mixin base classes. Project `appTitle` is `"Custom Controls Package"`. + +Public user-facing surface, grouped by role. + +#### Concrete controls (`CustomControlsPackage\Sources\Waynes*.twin`) + +Each is `Class ` (no `Public` modifier — implicitly public), tagged `[CustomControl("/miscellaneous/frm.png")]` (designer icon) and `[COMCreatable(False)]` (cannot be `New`'d through COM; instantiated by the designer). + +| Control | Implements | Co-located public types | +|------------------|-----------------------------------------------------------|--------------------------------------------------| +| `WaynesButton` | `ICustomControl` + `BaseControlFocusable` (mixin) | `WaynesButtonState` (private, but exposed) | +| `WaynesForm` | `ICustomControl` + `BaseForm` (mixin) | — (uses `WindowsFormOptions` from support file) | +| `WaynesFrame` | `ICustomControl` + `BaseControl` (mixin) | — | +| `WaynesGrid` | `ICustomControl` + `BaseControlFocusable` (mixin) | `Column`, `CellRenderingOptions` | +| `WaynesLabel` | `ICustomControl` + `BaseControl` (mixin) | — | +| `WaynesSlider` | `ICustomControl` + `BaseControlFocusable` (mixin) | `WaynesSliderState`, `SliderDirection` & `SliderDisplayValueFormat` (nested enums) | +| `WaynesTextBox` | `ICustomControl` + `BaseControlFocusable` (mixin) | `WaynesTextBoxState` | +| `WaynesTimer` | `ICustomControl` + `BaseControl` (mixin) | — | + +The "mixin" base classes (`BaseControl`, `BaseControlFocusable`, `BaseForm`) are declared `Private Class` in `zTemporarySupport.twin` and pulled into each control via the twinBASIC `Implements Via _BaseControl = New ` syntax. The base classes themselves get **no doc page** (they're private and never named by user code), but the inherited members **must be folded into each control's Properties listing** the same way VB-package controls list their inherited surface. The visible inherited surface, by mixin: + +- `BaseControl` → `Name`, `Left`, `Top`, `Width`, `Height`, `Anchors`, `Dock`, `Visible`. +- `BaseControlFocusable` → all of `BaseControl` + `TabIndex`, `TabStop`. +- `BaseForm` → `FormDesignerId`, `Name`, `Left`, `Top`, `Width`, `Height`, `Controls`. + +The state-holder classes (`WaynesButtonState`, `WaynesSliderState`, `WaynesTextBoxState`) and `WindowsFormOptions` are declared `Private Class` but are exposed on the parent control via `Public WithEvents NormalState As WaynesButtonState` (etc.). Same situation as `WebView2EnvironmentOptions` — document them as **sub-pages** of the parent control using the folder-style layout. + +#### Shared appearance helpers (`CustomControlsPackage\Sources\zTemporarySupport.twin`) + +Every helper in this file is `Private Class`, but the ones below are reachable through `Public WithEvents …` properties on one or more of the eight controls and **must be documented**: + +| Class | Reached as | +|-----------------|-------------------------------------------------------------------------------------| +| `Anchors` | `.Anchors` (via the mixin base) | +| `Corners` | `.Corners`, `CellRenderingOptions.Corners`, `.BackgroundCorners`, `BlockCorners` | +| `Corner` | `Corners.TopLeft` / `.TopRight` / `.BottomLeft` / `.BottomRight` | +| `Borders` | `.Borders`, `CellRenderingOptions.Borders`, `.BackgroundBorders`, `BlockBorders` | +| `Border` | element of `Borders.Elements()`; also `TextRendering.Outlines()` | +| `Fill` | `.BackgroundFill`, `.BlockFill`, `CellRenderingOptions.Fill`, `Border.Fill`, `Line.Fill`, `TextRendering.Fill` | +| `FillColorPoint` | element of `FillColorPoints.Values()` | +| `FillColorPoints` | `Fill.ColorPoints` | +| `Line` | `WaynesGrid.VerticalLineOptions` / `.HorizontalLineOptions` / `.ResizerBar` | +| `Padding` | `TextRendering.Padding` | +| `TextRendering` | `.TextRendering`, `WaynesLabel.TextRendering`, `CellRenderingOptions.TextRendering` | +| `FontStyle` | `TextRendering.Font` | +| `WindowsFormOptions` | `WaynesForm.WindowsOptions` (only one consumer) | + +Document these under `docs/Reference/CustomControls/Styles/`. Pair small helpers with their containers on a single page (the pairings happen to be self-evident from the table — `Corner` inlines under `Corners.md`, `Border` under `Borders.md`, `FillColorPoint` and `FillColorPoints` under `Fill.md`, `FontStyle` under `TextRendering.md`). `WindowsFormOptions` is the exception: it has exactly one consumer (`WaynesForm`), so put it as a sub-page of `WaynesForm/` (folder-style), parallel to how WebView2 carries `EnvironmentOptions`. + +The remaining `Private Class` / `Private Module` content in `zTemporarySupport.twin` is implementation-detail and gets **no doc page**: + +- `TextDecorator`, `TextDecorators` — used only inside `ElementDescriptor`, not surfaced on any control property. +- `UDTs` — a wrapper class whose `Public Type` declarations (`MouseEvent`, `KeyEvent`, `FocusEvent`, `ElementDescriptor`) and `Public Enum` declarations (`CaretPosition`, `SpecialKeyCodes`) only matter to someone writing a *new* custom control (they're passed to `AddressOf`-registered callbacks on `ElementDescriptor`). Defer documenting these until / unless an "authoring a custom control" tutorial calls for them. +- `BaseControl`, `BaseControlFocusable`, `BaseForm` — the mixin bases (covered above; members surface on each control, but the bases themselves are private). +- `Private Module MathSupport` / `Private Module ColorSupport` — internal. + +#### DESIGNER framework surface (`CustomControls\Sources\CustomControls.twin`) + +The framework half — what a *control author* writes against. Document at `docs/Reference/CustomControls/Framework/`: + +| Symbol | Kind | Role | +|------------------------------|---------------------|---------------------------------------------------------------------------------------| +| `ICustomControl` | `Interface` | what every concrete control implements: `Initialize(Context)`, `Destroy()`, `Paint(Canvas)` | +| `ICustomForm` | `Interface` | analogous surface for form-class custom controls | +| `CustomControlContext` | `CoClass` | passed to `ICustomControl.Initialize`; offers `GetSerializer()`, `Repaint()`, `CreateTimer()`, `ChangeFocusedElement()` | +| `CustomFormContext` | `CoClass` | extends `CustomControlContext` with `Show()` / `Close()` | +| `CustomControlTimer` | `CoClass` | returned by `CustomControlContext.CreateTimer()`; `Interval`, `Enabled`, `OnTimer` event | +| `CustomControlsCollection` | `CoClass` | the `Controls` collection on a form — `Count`, `Item`, `Add`, `Remove`, `_NewEnum` | +| `SerializeInfo` | UDT | obtained from `Context.GetSerializer()`; exposes `RuntimeUISrz*` operations (deserialize, mode flags, …) | +| `Canvas` | UDT | parameter to `ICustomControl.Paint`; exposes `RuntimeUICCCanvasAddElement` + DPI / size getters | + +Both UDTs follow a pattern unique to twinBASIC: a `Pointer As LongPtr` field plus `Public DeclareWide PtrSafe Function/Sub … Lib "" Alias "#N"` pseudo-DLL declarations bound directly into the type. From a *caller* perspective these read as instance methods on the UDT (`Canvas.RuntimeUICCCanvasAddElement(descriptor)`); document them as methods, and **do not** surface the `Lib "<…>"` / `Alias "#N"` / `PreserveSig` / `DLLStackCheck` decoration (same treatment as Assert's pseudo-DLL plumbing). The verbose `RuntimeUISrz*` / `RuntimeUICC*` names are unfortunate but they *are* the public API — keep them as-is. + +The two underscore-prefixed default interfaces of each CoClass (`_CustomControlTimer`, `_CustomControlContext`, `_CustomFormContext`, `_CustomControlsCollection`, `_CustomControlTimerEvents`) are an implementation detail of the COM `[Default]`/`[Default, Source]` pattern — fold their members onto the CoClass page, **don't** give the interfaces their own pages. + +#### Enumerations (`CustomControls.twin`, module `Constants`) + +Public enums to surface, one page each, under `docs/Reference/CustomControls/Enumerations/`: + +- `CornerShape`, `FillPattern`, `TextAlignment`, `TextOverflowMode`, `DockMode`, `FontWeight`, `StartupPosition`, `BorderStyle`, `WindowState` — straightforward value enums. +- `Customtate` — **probable typo** for `CustomState`. Has the same three members as `WindowState` (`tbNormal` / `tbMinimized` / `tbMaximized`) and isn't referenced anywhere else in the package. Document it (since it's `Public`), but add a `> [!NOTE]` callout flagging the typo and pointing readers to `WindowState`. +- `ColorRGBA`, `PixelCount`, `PointSize` — these are declared as `Enum` only because twinBASIC doesn't yet have a `Type Foo = Long` alias syntax. Each carries a `FIXME` comment ("Substitute for an ALIAS to Long") and a single `[_MAX] = 0` placeholder member. Document them as **typedefs for `Long`** (the underlying storage type), not as real enums. Note in each that the alias is what user code actually sees on `Public Width As CustomControls.PixelCount` (etc.) — when the alias syntax lands, these enum stand-ins go away. + +Plus the two enums nested inside `WaynesSlider`: `SliderDirection` and `SliderDisplayValueFormat`. Document them on the `WaynesSlider/index.md` page rather than under `Enumerations/` (they're locally scoped to the slider). + +#### Doc-side layout (folders / files) + +Compact form: + +``` +docs/Reference/CustomControls/ + index.md ← package landing; intro + role split + cross-links to the four groups + WaynesButton/index.md, WaynesButton/WaynesButtonState.md + WaynesForm/index.md, WaynesForm/WindowsFormOptions.md + WaynesFrame.md + WaynesGrid/index.md, WaynesGrid/Column.md, WaynesGrid/CellRenderingOptions.md + WaynesLabel.md + WaynesSlider/index.md, WaynesSlider/WaynesSliderState.md + WaynesTextBox/index.md, WaynesTextBox/WaynesTextBoxState.md + WaynesTimer.md + Styles/index.md, Styles/Anchors.md, Styles/Borders.md, Styles/Corners.md, + Styles/Fill.md, Styles/Line.md, Styles/Padding.md, Styles/TextRendering.md + Framework/index.md, Framework/Canvas.md, Framework/CustomControlContext.md, + Framework/CustomControlsCollection.md, Framework/CustomControlTimer.md, + Framework/CustomFormContext.md, Framework/ICustomControl.md, + Framework/ICustomForm.md, Framework/SerializeInfo.md + Enumerations/index.md, Enumerations/BorderStyle.md, Enumerations/ColorRGBA.md, + Enumerations/CornerShape.md, Enumerations/Customtate.md, Enumerations/DockMode.md, + Enumerations/FillPattern.md, Enumerations/FontWeight.md, Enumerations/PixelCount.md, + Enumerations/PointSize.md, Enumerations/StartupPosition.md, Enumerations/TextAlignment.md, + Enumerations/TextOverflowMode.md, Enumerations/WindowState.md +``` + +**Naming:** + +- Folder / URL segment: `CustomControls/` (drops the "Package" suffix; collapses the two source packages, same simplification WebView2 used). +- Index title: `CustomControls Package` — the ` Package` convention. +- Permalinks: `/tB/Packages/CustomControls/` for the landing; `/tB/Packages/CustomControls/` and `/tB/Packages/CustomControls//` for single-file vs folder-style controls; `/tB/Packages/CustomControls/Styles/`, `/tB/Packages/CustomControls/Framework/`, `/tB/Packages/CustomControls/Enumerations/` for the three sub-groups. +- `parent: CustomControls Package` on every child page (matching the index `title:`). +- The `Styles/`, `Framework/`, `Enumerations/` index pages set `parent: CustomControls Package` and `has_children: true`; their children set `parent: ` (the grouped-page pattern). Mirror exactly the structure WebView2 uses for its `Enumerations/`. + +**License:** MIT (copyright Wayne Phillips T/A iTech Masters, 2022) — same situation as WebView2Package and Assert. Pages are fully original; **omit** the `vba_attribution: true` flag. + +**No backlog file** — the eight controls + the three sub-groups enumerated above are the entire backlog; track inline here. + ## Page template Match the existing style. Worked examples to imitate: @@ -242,6 +378,10 @@ The URL prefixes are *not* uniform across packages — VBA pages live one segmen - WebView2 class → `/tB/Packages/WebView2/` (or `/tB/Packages/WebView2//` for folder-style — used by `WebView2/`) - WebView2 enumeration → `/tB/Packages/WebView2/Enumerations/` (one segment deeper than a class, parallel to VBRUN's `Constants/`) - Assert module → `/tB/Packages/Assert/` (single-page-per-module; same depth as a single-file VB class) +- CustomControls control → `/tB/Packages/CustomControls/` (single-file) or `/tB/Packages/CustomControls//` (folder-style — used by `WaynesButton/`, `WaynesForm/`, `WaynesGrid/`, `WaynesSlider/`, `WaynesTextBox/`) +- CustomControls style helper → `/tB/Packages/CustomControls/Styles/` +- CustomControls framework symbol → `/tB/Packages/CustomControls/Framework/` +- CustomControls enumeration → `/tB/Packages/CustomControls/Enumerations/` Common patterns: @@ -278,11 +418,30 @@ Common patterns: | Assert `Packages/Assert/` | VBRUN `Packages/VBRUN//Y` | `[Y](../VBRUN//Y)` | | Assert `Packages/Assert/` | VBA `Modules//Y` | `[Y](../../Modules//Y)` | | Assert `Packages/Assert/` | `Core/Y` | `[Y](../../Core/Y)` | +| CC `Packages/CustomControls/X` (single-file) | sibling `Packages/CustomControls/Y` | `[Y](Y)` | +| CC `Packages/CustomControls/X` (single-file) | `Packages/CustomControls/Styles/Y` | `[Y](Styles/Y)` | +| CC `Packages/CustomControls/X` (single-file) | `Packages/CustomControls/Framework/Y` | `[Y](Framework/Y)` | +| CC `Packages/CustomControls/X` (single-file) | `Packages/CustomControls/Enumerations/Y` | `[Y](Enumerations/Y)` | +| CC `Packages/CustomControls/X` (single-file) | VB `Packages/VB/Y` | `[Y](../VB/Y)` | +| CC `Packages/CustomControls/X` (single-file) | `Core/Y` | `[Y](../../Core/Y)` | +| CC `Packages/CustomControls//index` | sibling `Packages/CustomControls/Y` | `[Y](../Y)` | +| CC `Packages/CustomControls//index` | `Packages/CustomControls/Styles/Y` | `[Y](../Styles/Y)` | +| CC `Packages/CustomControls//index` | `Packages/CustomControls/Enumerations/Y` | `[Y](../Enumerations/Y)` | +| CC `Packages/CustomControls//index` | `Core/Y` | `[Y](../../../Core/Y)` | +| CC `Packages/CustomControls/Styles/X` | sibling `Styles/Y` | `[Y](Y)` | +| CC `Packages/CustomControls/Styles/X` | `Packages/CustomControls/` (single-file) | `[Y](../)` | +| CC `Packages/CustomControls/Styles/X` | `Packages/CustomControls/Enumerations/Y` | `[Y](../Enumerations/Y)` | +| CC `Packages/CustomControls/Styles/X` | `Core/Y` | `[Y](../../../Core/Y)` | +| CC `Packages/CustomControls/Framework/X` | sibling `Framework/Y` | `[Y](Y)` | +| CC `Packages/CustomControls/Framework/X` | `Packages/CustomControls/` (single-file) | `[Y](../)` | +| CC `Packages/CustomControls/Enumerations/X` | sibling `Enumerations/Y` | `[Y](Y)` | +| CC `Packages/CustomControls/Enumerations/X` | `Packages/CustomControls/` (single-file) | `[Y](../)` | | `Core/X` | VBA `Modules//Y` | `[Y](../Modules//Y)` | | `Core/X` | VBRUN `Packages/VBRUN//Y` | `[Y](../Packages/VBRUN//Y)` | | `Core/X` | VB `Packages/VB/Y` | `[Y](../Packages/VB/Y)` | | `Core/X` | WebView2 `Packages/WebView2/Y` | `[Y](../Packages/WebView2/Y)` | | `Core/X` | Assert `Packages/Assert/` | `[Y](../Packages/Assert/)` | +| `Core/X` | CC `Packages/CustomControls/Y` | `[Y](../Packages/CustomControls/Y)` | | `Core/X` | `Core/Y` (sibling) | `[Y](Y)` | Always link to the **canonical** location (the page's `permalink:`), not to a `redirect_from` alias. Pages that have moved out of `Core/` retain a `redirect_from: /tB/Core/` so legacy links still work, but forward-style links should point at the new home. @@ -294,6 +453,7 @@ Always link to the **canonical** location (the page's `permalink:`), not to a `r - VB control classes → `..\tb-export\NewProject\Packages\VB\Sources\CONTROLS\STANDARD\.twin` (and the relevant `BASE/Base*.twin` files for inherited members). - WebView2Package items → `..\tb-export\NewProject\Packages\WebView2Package\Sources\Classes\.twin`, with enumerations in `Support\Enumerations.twin` and the one user-type in `Support\Types.twin`. Ignore everything under `Abstract\` (private COM interfaces). - Assert package → `..\tb-export\NewProject\Packages\Assert\Sources\.twin` (one file per module — `Exact.twin`, `Strict.twin`, `Permissive.twin`). + - CustomControls — framework half: `..\tb-export\NewProject\Packages\CustomControls\Sources\CustomControls.twin` (a single file with `Module Constants`, the interfaces, and the CoClasses). Runtime half: `..\tb-export\NewProject\Packages\CustomControlsPackage\Sources\Waynes.twin` for each control + `zTemporarySupport.twin` for the shared style helpers and the mixin base classes. 2. **Decide placement**: - Pure language keyword (parsed by the compiler, no runtime call) → `docs/Reference/Core/`. - Runtime function/property → `docs/Reference///`. Add `redirect_from: /tB/Core/` so legacy `tB/Core/` links still work. @@ -302,6 +462,10 @@ Always link to the **canonical** location (the page's `permalink:`), not to a `r - WebView2 enumeration → `docs/Reference/WebView2/Enumerations/.md`, mirroring `docs/Reference/VBRUN/Constants/`. - WebView2 user-type → `docs/Reference/WebView2/Types/.md`. - Assert module → `docs/Reference/Assert/.md` — one single-file page per module, with all 15 members listed inline under `## ` headings. **Do not** create per-member sub-pages; the three modules share an identical API and per-member duplication would add noise. + - CustomControls concrete control → `docs/Reference/CustomControls/.md` (single-file, e.g. `WaynesFrame`, `WaynesLabel`, `WaynesTimer`) or `docs/Reference/CustomControls//index.md` (folder-style — required when the control has a state-holder or options sub-page, i.e. `WaynesButton/`, `WaynesForm/`, `WaynesGrid/`, `WaynesSlider/`, `WaynesTextBox/`). + - CustomControls shared style helper → `docs/Reference/CustomControls/Styles/.md`. Pair small helpers with their containers on a single page (`Corner` inline under `Corners.md`, `Border` under `Borders.md`, `FillColorPoint` + `FillColorPoints` under `Fill.md`, `FontStyle` under `TextRendering.md`). + - CustomControls framework symbol (interface, CoClass, UDT) → `docs/Reference/CustomControls/Framework/.md`. + - CustomControls enumeration → `docs/Reference/CustomControls/Enumerations/.md` (mirrors `WebView2/Enumerations/` and `VBRUN/Constants/`). The three `Long`-alias enums (`ColorRGBA`, `PixelCount`, `PointSize`) live here too, even though they're really typedefs. - Pick `` from VBA's grouping (Information, Interaction, Strings, FileSystem, DateTime, Math, Financial, Conversion, ...) and the existing folders under `Reference//`. 3. **Adapt content** (VBA-Docs sources): - Strip MS frontmatter (`ms.assetid`, `f1_keywords`, `keywords`, `ms.date`, `ms.localizationpriority`). @@ -324,11 +488,23 @@ Always link to the **canonical** location (the page's `permalink:`), not to a `r - **Do not** surface the `Lib ""`, `Alias "#N"`, `PreserveSig`, `UseGetLastError`, `DeclareWide PtrSafe Sub` decoration on the page — that's internal pseudo-DLL plumbing. Show each member as if it were an ordinary `Sub`: `Sub AreEqual(Expected, Actual, [Message])`. - **Do** mention `[DebugOnly(True)]` (assertions compile out of release builds) and `[MustBeQualified(True)]` (callers must write the module name, e.g. `Strict.IsTrue(x)`). - Omit the `vba_attribution: true` frontmatter flag — these pages are fully original (the Assert package is MIT-licensed). -7. **Flag tB deviations** with a `> [!NOTE]` callout (see next section). -8. **Update the parent index** (`//index.md`, `docs/Reference/VB/index.md`, `docs/Reference/WebView2/index.md`, `docs/Reference/Assert/index.md`, `Reference/Statements.md`, or `Reference/Procedures and Functions.md`) — turn an unlinked bullet into a link with a short blurb. Match the existing style of the page. -9. **Remove the symbol's path from `docs/Reference/VB/todo.md`** `redirect_from:` array (VB controls only — VBA/VBRUN backlogs are closed; WebView2Package and Assert have small enough backlogs to track inline in this file rather than via a `todo.md`). -10. **Add the page** to `Reference/Statements.md` or `Reference/Procedures and Functions.md` if it's a statement or callable and not already listed there. -11. **Run the [site integrity check](#site-integrity-check)** after the batch and before committing. +7. **Adapt content** (CustomControls `.twin` sources): + - For each concrete control: walk the `Implements Via _BaseControl = New ` mixin to know which inherited members surface on the control. The base classes are `Private Class` in `zTemporarySupport.twin` and never get their own doc page; their public members fold into the control's Properties listing. The visible inherited surface is small and fixed — see the "Concrete controls" sub-section above for the exact lists per base. + - List own + inherited members alphabetically within Properties / Methods / Events sections (mirror VB-package control pages like `CheckBox.md`). + - State-holder classes (`WaynesButtonState`, `WaynesSliderState`, `WaynesTextBoxState`) and `WindowsFormOptions` are declared `Private Class` but are reachable through `Public WithEvents …` properties — document them as **sub-pages** of the parent control (folder-style layout, parallel to `WebView2/EnvironmentOptions.md`). + - For shared style helpers in `zTemporarySupport.twin` (`Corners`, `Fill`, `Borders`, `TextRendering`, `Anchors`, `Padding`, `Line`): list `Public` fields in source order, grouped into Properties / Methods. They have no `Property Get`/`Property Let` pairs — they're bare-field UDT-style classes that raise an `OnChanged` event when any field is set. Document the fields as properties; mention the `OnChanged` event once at the end. + - For the DESIGNER framework: fold the underscore-prefixed default interface (`_CustomControlTimer`, `_CustomControlContext`, …) onto the CoClass page — don't give the `_…` interfaces their own pages. The `[Default]` / `[Default, Source]` decoration is COM detail; show members as if they were declared directly on the CoClass. + - For the `SerializeInfo` and `Canvas` UDTs: each carries a `Pointer As LongPtr` field plus `Public DeclareWide PtrSafe Function/Sub … Lib "<…>" Alias "#N"` pseudo-DLL members. Document those members as instance methods on the UDT (`Canvas.RuntimeUICCCanvasAddElement(descriptor)`); **do not** surface the `Lib` / `Alias` / `PreserveSig` / `DLLStackCheck` / `SimplerByVals` decoration (same treatment as Assert). + - The `[Description("…")]` attribute on `Public` fields / properties / events gives the user-visible one-liner from the IDE — use it as the basis for the page's description, then expand. + - For the three `Long`-alias enums (`ColorRGBA`, `PixelCount`, `PointSize`): document each as a typedef for `Long` (the underlying storage is `Long`), with a callout that they're currently declared as empty `Enum` blocks pending real alias support — the carrying `FIXME` comment confirms this is transitional. + - For `Customtate`: document the enum, but include a `> [!NOTE]` callout flagging the typo (the name appears to be a slip for `CustomState`) and pointing readers to the active `WindowState` enum, which carries identical members. + - For `BaseControl` / `BaseControlFocusable` / `BaseForm`, `TextDecorator(s)`, the `UDTs` wrapper class (`MouseEvent`, `KeyEvent`, `FocusEvent`, `ElementDescriptor`, `CaretPosition`, `SpecialKeyCodes`), and `MathSupport` / `ColorSupport` modules: **no doc page** — implementation-detail private content. The mixin bases' members surface on the controls; the UDT-class members only matter for someone authoring a *new* custom control and can wait for an "authoring tutorial" pass. + - Omit the `vba_attribution: true` frontmatter flag — these pages are fully original (both source packages are MIT-licensed). +8. **Flag tB deviations** with a `> [!NOTE]` callout (see next section). +9. **Update the parent index** (`//index.md`, `docs/Reference/VB/index.md`, `docs/Reference/WebView2/index.md`, `docs/Reference/Assert/index.md`, `docs/Reference/CustomControls/index.md` (and its `Styles/`, `Framework/`, `Enumerations/` sub-indices), `Reference/Statements.md`, or `Reference/Procedures and Functions.md`) — turn an unlinked bullet into a link with a short blurb. Match the existing style of the page. Also extend `docs/Reference/Packages.md` to list the new package once the landing page exists. +10. **Remove the symbol's path from `docs/Reference/VB/todo.md`** `redirect_from:` array (VB controls only — VBA/VBRUN backlogs are closed; WebView2Package, Assert, and CustomControls have small enough backlogs to track inline in this file rather than via a `todo.md`). +11. **Add the page** to `Reference/Statements.md` or `Reference/Procedures and Functions.md` if it's a statement or callable and not already listed there. +12. **Run the [site integrity check](#site-integrity-check)** after the batch and before committing. ## twinBASIC deviations from VBA to flag From e4f7b0f3e2701a57dbfb7db1d3be5b634bc9fd9d Mon Sep 17 00:00:00 2001 From: Kuba Sunderland-Ober Date: Wed, 13 May 2026 16:52:30 +0200 Subject: [PATCH 2/4] Clarify that the logical operators are really bitwise operators. --- docs/Reference/Core/And.md | 4 ++-- docs/Reference/Core/Eqv.md | 4 ++-- docs/Reference/Core/Imp.md | 4 ++-- docs/Reference/Core/Not.md | 4 ++-- docs/Reference/Core/Or.md | 4 ++-- docs/Reference/Core/Xor.md | 4 ++-- docs/Reference/Operators.md | 18 +++++++++--------- docs/Reference/Packages.md | 1 + 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/docs/Reference/Core/And.md b/docs/Reference/Core/And.md index 39ef687a..ba6b038e 100644 --- a/docs/Reference/Core/And.md +++ b/docs/Reference/Core/And.md @@ -8,7 +8,7 @@ vba_attribution: true # And operator {: .no_toc } -Used to perform a logical conjunction on two expressions. +Used to perform a bitwise conjunction on two expressions. Syntax: > *result* **=** *expression1* **And** *expression2* @@ -33,7 +33,7 @@ If both expressions evaluate to **True**, *result* is **True**. If either expres | **Null** | **False** | **False** | | **Null** | **Null** | **Null** | -The **And** operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: +The **And** operator performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: | If bit in *expression1* is | And bit in *expression2* is | The *result* is | |:-----:|:-----:|:-----:| diff --git a/docs/Reference/Core/Eqv.md b/docs/Reference/Core/Eqv.md index 71b9bcfb..a9efcf6b 100644 --- a/docs/Reference/Core/Eqv.md +++ b/docs/Reference/Core/Eqv.md @@ -8,7 +8,7 @@ vba_attribution: true # Eqv operator {: .no_toc } -Used to perform a logical equivalence on two expressions — the logical inverse of [**Xor**](Xor). +Used to perform a bitwise equivalence on two expressions — the logical inverse of [**Xor**](Xor). Syntax: > *result* **=** *expression1* **Eqv** *expression2* @@ -28,7 +28,7 @@ If either expression is **Null**, *result* is also **Null**. When neither expres | **False** | **True** | **False** | | **False** | **False** | **True** | -The **Eqv** operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: +The **Eqv** operator performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: | If bit in *expression1* is | And bit in *expression2* is | The *result* is | |:-----:|:-----:|:-----:| diff --git a/docs/Reference/Core/Imp.md b/docs/Reference/Core/Imp.md index a8593f55..2ee21477 100644 --- a/docs/Reference/Core/Imp.md +++ b/docs/Reference/Core/Imp.md @@ -8,7 +8,7 @@ vba_attribution: true # Imp operator {: .no_toc } -Used to perform a logical implication on two expressions. *expression1* **Imp** *expression2* is **False** only when *expression1* is **True** and *expression2* is **False**; in every other non-**Null** case the result is **True**. +Used to perform a bitwise implication on two expressions. *expression1* **Imp** *expression2* is **False** only when *expression1* is **True** and *expression2* is **False**; in every other non-**Null** case the result is **True**. Syntax: > *result* **=** *expression1* **Imp** *expression2* @@ -33,7 +33,7 @@ The following table illustrates how *result* is determined: | **Null** | **False** | **Null** | | **Null** | **Null** | **Null** | -The **Imp** operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: +The **Imp** operator performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: | If bit in *expression1* is | And bit in *expression2* is | The *result* is | |:-----:|:-----:|:-----:| diff --git a/docs/Reference/Core/Not.md b/docs/Reference/Core/Not.md index 992c1687..988d5d66 100644 --- a/docs/Reference/Core/Not.md +++ b/docs/Reference/Core/Not.md @@ -8,7 +8,7 @@ vba_attribution: true # Not operator {: .no_toc } -Used to perform logical negation on an expression. +Used to perform bitwise negation on an expression. Syntax: > *result* **=** **Not** *expression* @@ -27,7 +27,7 @@ The following table illustrates how *result* is determined: | **False** | **True** | | **Null** | **Null** | -In addition, the **Not** operator inverts the bit values of its operand and sets the corresponding bit in *result* according to the following table: +The **Not** operator inverts the bit values of its operand and sets the corresponding bit in *result* according to the following table: | If bit in *expression* is | Then bit in *result* is | |:-----:|:-----:| diff --git a/docs/Reference/Core/Or.md b/docs/Reference/Core/Or.md index 63522a6f..5de51192 100644 --- a/docs/Reference/Core/Or.md +++ b/docs/Reference/Core/Or.md @@ -8,7 +8,7 @@ vba_attribution: true # Or operator {: .no_toc } -Used to perform a logical disjunction on two expressions. +Used to perform a bitwise disjunction on two expressions. Syntax: > *result* **=** *expression1* **Or** *expression2* @@ -33,7 +33,7 @@ If either or both expressions evaluate to **True**, *result* is **True**. The fo | **Null** | **False** | **Null** | | **Null** | **Null** | **Null** | -The **Or** operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: +The **Or** operator performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: | If bit in *expression1* is | And bit in *expression2* is | Then *result* is | |:-----:|:-----:|:-----:| diff --git a/docs/Reference/Core/Xor.md b/docs/Reference/Core/Xor.md index e6b85854..f34b61dd 100644 --- a/docs/Reference/Core/Xor.md +++ b/docs/Reference/Core/Xor.md @@ -8,7 +8,7 @@ vba_attribution: true # Xor operator {: .no_toc } -Used to perform a logical exclusion (exclusive-or) on two expressions. +Used to perform a bitwise exclusion (exclusive-or) on two expressions. Syntax: > *result* **=** *expression1* **Xor** *expression2* @@ -28,7 +28,7 @@ If one — and only one — of the expressions evaluates to **True**, *result* i | **False** | **True** | **True** | | **False** | **False** | **False** | -The **Xor** operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: +The **Xor** operator performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in *result* according to the following table: | If bit in *expression1* is | And bit in *expression2* is | Then *result* is | |:-----:|:-----:|:-----:| diff --git a/docs/Reference/Operators.md b/docs/Reference/Operators.md index de6e130e..4345e1ed 100644 --- a/docs/Reference/Operators.md +++ b/docs/Reference/Operators.md @@ -31,18 +31,18 @@ Operators built into the twinBASIC language. They are understood by the compiler - [Is](../tB/Core/Is) -- compares two object references for identity - [IsNot](../tB/Core/IsNot) -- (twinBASIC) the logical inverse of **Is** -## Logical and Bitwise +## Bitwise -Both operands are always evaluated. +Both operands are always evaluated. Booleans are treated as integers: True = -1, False = 0. -- [And](../tB/Core/And) -- logical or bitwise conjunction -- [Or](../tB/Core/Or) -- logical or bitwise disjunction -- [Not](../tB/Core/Not) -- logical or bitwise negation -- [Xor](../tB/Core/Xor) -- logical or bitwise exclusive-or -- [Eqv](../tB/Core/Eqv) -- logical or bitwise equivalence -- [Imp](../tB/Core/Imp) -- logical or bitwise implication +- [And](../tB/Core/And) -- bitwise conjunction +- [Or](../tB/Core/Or) -- bitwise disjunction +- [Not](../tB/Core/Not) -- bitwise negation +- [Xor](../tB/Core/Xor) -- bitwise exclusive-or +- [Eqv](../tB/Core/Eqv) -- bitwise equivalence +- [Imp](../tB/Core/Imp) -- bitwise implication -## Logical (Short-Circuit) +## Logical Short-Circuit The right operand is evaluated only when the left operand does not already determine the result. diff --git a/docs/Reference/Packages.md b/docs/Reference/Packages.md index 6c894677..91febe3a 100644 --- a/docs/Reference/Packages.md +++ b/docs/Reference/Packages.md @@ -23,4 +23,5 @@ These packages are included in every project by default. These packages are built into twinBASIC and are always available, even offline. To use them, add them to Project → References (Ctrl-T) → Available Packages. - [Assert Package](Assert/) -- assertion functions for unit tests — three modules (**Exact**, **Strict**, **Permissive**) sharing the same fifteen-member API with different comparison strictness +- [CustomControls Package](CustomControls/) -- owner-drawn `Waynes…` custom controls (button, form, frame, grid, label, slider, textbox, timer), the shared `Styles/` helpers that paint them, and the DESIGNER framework (interfaces, callback objects, **Canvas**, **SerializeInfo**) for authoring new custom controls - [WebView2 Package](WebView2/) -- the **WebView2** control wrapping the Microsoft Edge runtime, plus its surrounding wrapper objects (request / response / headers / environment options) and the `wv2…` enumerations From afea9103c25f107080ee6e43b5d1f3acd919b2a4 Mon Sep 17 00:00:00 2001 From: Kuba Sunderland-Ober Date: Wed, 13 May 2026 16:53:10 +0200 Subject: [PATCH 3/4] Document the CustomControls package. --- .../Enumerations/BorderStyle.md | 21 ++ .../CustomControls/Enumerations/ColorRGBA.md | 19 ++ .../Enumerations/CornerShape.md | 16 ++ .../CustomControls/Enumerations/Customtate.md | 19 ++ .../CustomControls/Enumerations/DockMode.md | 19 ++ .../Enumerations/FillPattern.md | 36 +++ .../CustomControls/Enumerations/FontWeight.md | 22 ++ .../CustomControls/Enumerations/PixelCount.md | 15 ++ .../CustomControls/Enumerations/PointSize.md | 13 ++ .../Enumerations/StartupPosition.md | 17 ++ .../Enumerations/TextAlignment.md | 24 ++ .../Enumerations/TextOverflowMode.md | 17 ++ .../Enumerations/WindowState.md | 16 ++ .../CustomControls/Enumerations/index.md | 26 +++ .../CustomControls/Framework/Canvas.md | 73 ++++++ .../Framework/CustomControlContext.md | 65 ++++++ .../Framework/CustomControlTimer.md | 60 +++++ .../Framework/CustomControlsCollection.md | 81 +++++++ .../Framework/CustomFormContext.md | 42 ++++ .../Framework/ICustomControl.md | 70 ++++++ .../CustomControls/Framework/ICustomForm.md | 43 ++++ .../CustomControls/Framework/SerializeInfo.md | 92 ++++++++ .../CustomControls/Framework/index.md | 55 +++++ .../CustomControls/Styles/Anchors.md | 52 +++++ .../CustomControls/Styles/Borders.md | 94 ++++++++ .../CustomControls/Styles/Corners.md | 85 +++++++ docs/Reference/CustomControls/Styles/Fill.md | 173 ++++++++++++++ docs/Reference/CustomControls/Styles/Line.md | 38 ++++ .../CustomControls/Styles/Padding.md | 48 ++++ .../CustomControls/Styles/TextRendering.md | 99 ++++++++ docs/Reference/CustomControls/Styles/index.md | 24 ++ .../WaynesButton/WaynesButtonState.md | 67 ++++++ .../CustomControls/WaynesButton/index.md | 200 ++++++++++++++++ .../WaynesForm/WindowsFormOptions.md | 71 ++++++ .../CustomControls/WaynesForm/index.md | 123 ++++++++++ docs/Reference/CustomControls/WaynesFrame.md | 66 ++++++ .../WaynesGrid/CellRenderingOptions.md | 62 +++++ .../CustomControls/WaynesGrid/Column.md | 38 ++++ .../CustomControls/WaynesGrid/index.md | 213 ++++++++++++++++++ docs/Reference/CustomControls/WaynesLabel.md | 83 +++++++ .../WaynesSlider/WaynesSliderState.md | 76 +++++++ .../CustomControls/WaynesSlider/index.md | 161 +++++++++++++ .../WaynesTextBox/WaynesTextBoxState.md | 98 ++++++++ .../CustomControls/WaynesTextBox/index.md | 110 +++++++++ docs/Reference/CustomControls/WaynesTimer.md | 91 ++++++++ docs/Reference/CustomControls/index.md | 91 ++++++++ docs/Reference/WebView2/index.md | 2 +- 47 files changed, 3025 insertions(+), 1 deletion(-) create mode 100644 docs/Reference/CustomControls/Enumerations/BorderStyle.md create mode 100644 docs/Reference/CustomControls/Enumerations/ColorRGBA.md create mode 100644 docs/Reference/CustomControls/Enumerations/CornerShape.md create mode 100644 docs/Reference/CustomControls/Enumerations/Customtate.md create mode 100644 docs/Reference/CustomControls/Enumerations/DockMode.md create mode 100644 docs/Reference/CustomControls/Enumerations/FillPattern.md create mode 100644 docs/Reference/CustomControls/Enumerations/FontWeight.md create mode 100644 docs/Reference/CustomControls/Enumerations/PixelCount.md create mode 100644 docs/Reference/CustomControls/Enumerations/PointSize.md create mode 100644 docs/Reference/CustomControls/Enumerations/StartupPosition.md create mode 100644 docs/Reference/CustomControls/Enumerations/TextAlignment.md create mode 100644 docs/Reference/CustomControls/Enumerations/TextOverflowMode.md create mode 100644 docs/Reference/CustomControls/Enumerations/WindowState.md create mode 100644 docs/Reference/CustomControls/Enumerations/index.md create mode 100644 docs/Reference/CustomControls/Framework/Canvas.md create mode 100644 docs/Reference/CustomControls/Framework/CustomControlContext.md create mode 100644 docs/Reference/CustomControls/Framework/CustomControlTimer.md create mode 100644 docs/Reference/CustomControls/Framework/CustomControlsCollection.md create mode 100644 docs/Reference/CustomControls/Framework/CustomFormContext.md create mode 100644 docs/Reference/CustomControls/Framework/ICustomControl.md create mode 100644 docs/Reference/CustomControls/Framework/ICustomForm.md create mode 100644 docs/Reference/CustomControls/Framework/SerializeInfo.md create mode 100644 docs/Reference/CustomControls/Framework/index.md create mode 100644 docs/Reference/CustomControls/Styles/Anchors.md create mode 100644 docs/Reference/CustomControls/Styles/Borders.md create mode 100644 docs/Reference/CustomControls/Styles/Corners.md create mode 100644 docs/Reference/CustomControls/Styles/Fill.md create mode 100644 docs/Reference/CustomControls/Styles/Line.md create mode 100644 docs/Reference/CustomControls/Styles/Padding.md create mode 100644 docs/Reference/CustomControls/Styles/TextRendering.md create mode 100644 docs/Reference/CustomControls/Styles/index.md create mode 100644 docs/Reference/CustomControls/WaynesButton/WaynesButtonState.md create mode 100644 docs/Reference/CustomControls/WaynesButton/index.md create mode 100644 docs/Reference/CustomControls/WaynesForm/WindowsFormOptions.md create mode 100644 docs/Reference/CustomControls/WaynesForm/index.md create mode 100644 docs/Reference/CustomControls/WaynesFrame.md create mode 100644 docs/Reference/CustomControls/WaynesGrid/CellRenderingOptions.md create mode 100644 docs/Reference/CustomControls/WaynesGrid/Column.md create mode 100644 docs/Reference/CustomControls/WaynesGrid/index.md create mode 100644 docs/Reference/CustomControls/WaynesLabel.md create mode 100644 docs/Reference/CustomControls/WaynesSlider/WaynesSliderState.md create mode 100644 docs/Reference/CustomControls/WaynesSlider/index.md create mode 100644 docs/Reference/CustomControls/WaynesTextBox/WaynesTextBoxState.md create mode 100644 docs/Reference/CustomControls/WaynesTextBox/index.md create mode 100644 docs/Reference/CustomControls/WaynesTimer.md create mode 100644 docs/Reference/CustomControls/index.md diff --git a/docs/Reference/CustomControls/Enumerations/BorderStyle.md b/docs/Reference/CustomControls/Enumerations/BorderStyle.md new file mode 100644 index 00000000..5c3720b7 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/BorderStyle.md @@ -0,0 +1,21 @@ +--- +title: BorderStyle +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/BorderStyle +--- +# BorderStyle +{: .no_toc } + +The Win32 frame style used by a [**WaynesForm**](../WaynesForm/) window. Determines whether the window has a thick or thin border, whether it can be resized by dragging an edge, and whether it shows a normal title bar or the smaller tool-window title bar. Carried by [**WindowsFormOptions.BorderStyle**](../WaynesForm/WindowsFormOptions#borderstyle). + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbNone**{: #tbNone } | 0 | No border at all — the form is a borderless, captionless rectangle. | +| **tbFixedSingle**{: #tbFixedSingle } | 1 | Thin single-line border; size is fixed at run time. | +| **tbFixedSizable**{: #tbFixedSizable } | 2 | Standard resizable border with a normal title bar. The default for newly-constructed [**WindowsFormOptions**](../WaynesForm/WindowsFormOptions). | +| **tbFixedDialog**{: #tbFixedDialog } | 3 | Dialog-frame border; size is fixed and the system menu offers only **Move** / **Close**. | +| **tbFixedToolWindow**{: #tbFixedToolWindow } | 4 | Tool-window border with the smaller title bar; size is fixed. | +| **tbSizableToolWindow**{: #tbSizableToolWindow } | 5 | Tool-window border with the smaller title bar; the window is resizable. | + +Most border styles cannot be combined with **MinimizeButton** or **MaximizeButton** — only **tbFixedSizable** shows full sizing controls. Setting [**MinimizeButton**](../WaynesForm/WindowsFormOptions#minimizebutton) or [**MaximizeButton**](../WaynesForm/WindowsFormOptions#maximizebutton) to **True** on a window style that does not include them has no effect. diff --git a/docs/Reference/CustomControls/Enumerations/ColorRGBA.md b/docs/Reference/CustomControls/Enumerations/ColorRGBA.md new file mode 100644 index 00000000..061824e7 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/ColorRGBA.md @@ -0,0 +1,19 @@ +--- +title: ColorRGBA +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/ColorRGBA +--- +# ColorRGBA +{: .no_toc } + +> [!NOTE] +> **ColorRGBA** is declared as an empty `Enum` block (with a placeholder `[_MAX] = 0` member) only because twinBASIC has not yet exposed a type-alias syntax such as `Type ColorRGBA = Long`. The source carries a `FIXME` comment noting the stand-in. Treat **ColorRGBA** as a **Long**-compatible type alias rather than as an enumeration with named members; when alias syntax becomes available, the enum stand-in will be replaced. + +A **Long**-compatible type alias used wherever a 32-bit ABGR colour value is expected. The high byte is the alpha channel — `&HFF000000` is fully opaque, `&H00000000` is fully transparent — and the low three bytes follow the standard `vbBlue`/`vbGreen`/`vbRed` order used by the [**ColorConstants**](../../VBRUN/Constants/ColorConstants) `Long`-coloured constants. Carried by [**FillColorPoint.Color**](../Styles/Fill#color) and by the **RGBA** parameter of [**FillColorPoints.SetSolidColorRGBA**](../Styles/Fill#setsolidcolorrgba) / [**Borders.SetSimpleBorderRGBA**](../Styles/Borders#setsimpleborderrgba). + +To write a fully-opaque colour, OR-in the opaque alpha mask: `&HFF000000 Or vbBlue`. The convenience setters [**FillColorPoints.SetSolidColor**](../Styles/Fill#setsolidcolor) and [**Borders.SetSimpleBorder**](../Styles/Borders#setsimpleborder) take a normal three-byte **Long** colour and apply the opaque mask for you; only the `*RGBA` variants take a raw **ColorRGBA**. + +```tb +Dim translucentRed As ColorRGBA = &H800000FF& ' 50% alpha, full red +``` diff --git a/docs/Reference/CustomControls/Enumerations/CornerShape.md b/docs/Reference/CustomControls/Enumerations/CornerShape.md new file mode 100644 index 00000000..a10b3734 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/CornerShape.md @@ -0,0 +1,16 @@ +--- +title: CornerShape +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/CornerShape +--- +# CornerShape +{: .no_toc } + +Determines how a single corner of a control is shaped. Carried by [**Corner.Shape**](../Styles/Corners#shape), which is set independently for each of the four corners of any control that exposes a [**Corners**](../Styles/Corners) style object. The numeric value of the radius is supplied separately by [**Corner.Radius**](../Styles/Corners#radius). + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbCurve**{: #tbCurve } | 0 | Quarter-circle round corner; the radius gives the curve. | +| **tbNotched**{: #tbNotched } | 1 | Diagonal notch across the corner; the radius gives the cut depth. | +| **tbCutOut**{: #tbCutOut } | 2 | Inverse round-corner — the corner area is carved *out* of the control. | diff --git a/docs/Reference/CustomControls/Enumerations/Customtate.md b/docs/Reference/CustomControls/Enumerations/Customtate.md new file mode 100644 index 00000000..9e77cfcf --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/Customtate.md @@ -0,0 +1,19 @@ +--- +title: Customtate +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/Customtate +--- +# Customtate +{: .no_toc } + +> [!NOTE] +> The name **Customtate** appears to be a typo for "CustomState" preserved from an early draft of the package. The enum is not referenced by any of the eight concrete `Waynes…` controls; the actual minimized / normal / maximized state of a [**WaynesForm**](../WaynesForm/) is driven by the parallel [**WindowState**](WindowState) enum, which carries identical members. Treat **Customtate** as reserved. + +A reserved enumeration with the same three members as [**WindowState**](WindowState). Defined in `Module Constants` of the **CustomControls DESIGNER** library, exported as **Public**, but otherwise unused inside the package. + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbNormal**{: #tbNormal } | 0 | Same value as [**WindowState.tbNormal**](WindowState#tbNormal). | +| **tbMinimized**{: #tbMinimized } | 1 | Same value as [**WindowState.tbMinimized**](WindowState#tbMinimized). | +| **tbMaximized**{: #tbMaximized } | 2 | Same value as [**WindowState.tbMaximized**](WindowState#tbMaximized). | diff --git a/docs/Reference/CustomControls/Enumerations/DockMode.md b/docs/Reference/CustomControls/Enumerations/DockMode.md new file mode 100644 index 00000000..6ae547eb --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/DockMode.md @@ -0,0 +1,19 @@ +--- +title: DockMode +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/DockMode +--- +# DockMode +{: .no_toc } + +How a control is positioned relative to its container — pinned to one edge, filling the whole client area, or not docked at all (positioned absolutely by [**Left**](../#controls) / [**Top**](../#controls) / [**Width**](../#controls) / [**Height**](../#controls)). Carried by the **Dock** property that every concrete custom control inherits. + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbDockNone**{: #tbDockNone } | 0 | Not docked. The control's **Left**, **Top**, **Width**, and **Height** are used directly, modulated by the control's [**Anchors**](../Styles/Anchors) when the container resizes. | +| **tbDockLeft**{: #tbDockLeft } | 1 | Pinned to the container's left edge. Width is preserved; height is stretched to the container's client area. | +| **tbDockTop**{: #tbDockTop } | 2 | Pinned to the container's top edge. Height is preserved; width is stretched. | +| **tbDockRight**{: #tbDockRight } | 3 | Pinned to the container's right edge. Width is preserved; height is stretched. | +| **tbDockBottom**{: #tbDockBottom } | 4 | Pinned to the container's bottom edge. Height is preserved; width is stretched. | +| **tbDockFill**{: #tbDockFill } | 5 | Fills the entire remaining client area, after other docked siblings have claimed their edges. | diff --git a/docs/Reference/CustomControls/Enumerations/FillPattern.md b/docs/Reference/CustomControls/Enumerations/FillPattern.md new file mode 100644 index 00000000..7ed6215c --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/FillPattern.md @@ -0,0 +1,36 @@ +--- +title: FillPattern +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/FillPattern +--- +# FillPattern +{: .no_toc } + +Identifies how the colour table held by a [**Fill**](../Styles/Fill) is applied across the area being painted. The same colour stops produce very different results depending on the pattern — a north-to-south gradient with two stops paints a top-to-bottom transition, while a corner gradient with the same stops paints from one corner outward. Carried by [**Fill.Pattern**](../Styles/Fill#pattern). + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbPatternNone**{: #tbPatternNone } | 0 | No fill — leaves the region transparent. | +| **tbGradientNorthToSouth**{: #tbGradientNorthToSouth } | 1 | Linear gradient from the top edge down to the bottom edge. | +| **tbGradientSouthToNorth**{: #tbGradientSouthToNorth } | 2 | Linear gradient from the bottom edge up to the top edge. | +| **tbGradientWestToEast**{: #tbGradientWestToEast } | 3 | Linear gradient from the left edge across to the right edge. | +| **tbGradientEastToWest**{: #tbGradientEastToWest } | 4 | Linear gradient from the right edge across to the left edge. | +| **tbGradientNorthWestToSouthEast**{: #tbGradientNorthWestToSouthEast } | 5 | Linear diagonal gradient from the top-left corner to the bottom-right. | +| **tbGradientNorthWestToSouthEastAlt**{: #tbGradientNorthWestToSouthEastAlt } | 6 | Alternate diagonal: same axis as **tbGradientNorthWestToSouthEast** but with the stops mirrored about the centre. | +| **tbGradientNorthEastToSouthWest**{: #tbGradientNorthEastToSouthWest } | 7 | Linear diagonal gradient from the top-right corner to the bottom-left. | +| **tbGradientNorthEastToSouthWestAlt**{: #tbGradientNorthEastToSouthWestAlt } | 8 | Alternate diagonal: same axis as **tbGradientNorthEastToSouthWest** but mirrored. | +| **tbGradientSouthWestToNorthEast**{: #tbGradientSouthWestToNorthEast } | 9 | Linear diagonal gradient from the bottom-left corner to the top-right. | +| **tbGradientSouthWestToNorthEastAlt**{: #tbGradientSouthWestToNorthEastAlt } | 10 | Alternate diagonal: same axis as **tbGradientSouthWestToNorthEast** but mirrored. | +| **tbGradientSouthEastToNorthWest**{: #tbGradientSouthEastToNorthWest } | 11 | Linear diagonal gradient from the bottom-right corner to the top-left. | +| **tbGradientSouthEastToNorthWestAlt**{: #tbGradientSouthEastToNorthWestAlt } | 12 | Alternate diagonal: same axis as **tbGradientSouthEastToNorthWest** but mirrored. | +| **tbGradientCornerTopLeft**{: #tbGradientCornerTopLeft } | 13 | Radial-style gradient emanating from the top-left corner outward. | +| **tbGradientCornerTopRight**{: #tbGradientCornerTopRight } | 14 | Radial-style gradient emanating from the top-right corner outward. | +| **tbGradientCornerBottomLeft**{: #tbGradientCornerBottomLeft } | 15 | Radial-style gradient emanating from the bottom-left corner outward. | +| **tbGradientCornerBottomRight**{: #tbGradientCornerBottomRight } | 16 | Radial-style gradient emanating from the bottom-right corner outward. | +| **tbGradientCornerTopLeftAlt**{: #tbGradientCornerTopLeftAlt } | 17 | Alternate top-left corner gradient with the stops mirrored. | +| **tbGradientCornerTopRightAlt**{: #tbGradientCornerTopRightAlt } | 18 | Alternate top-right corner gradient with the stops mirrored. | +| **tbGradientCornerBottomLeftAlt**{: #tbGradientCornerBottomLeftAlt } | 19 | Alternate bottom-left corner gradient with the stops mirrored. | +| **tbGradientCornerBottomRightAlt**{: #tbGradientCornerBottomRightAlt } | 20 | Alternate bottom-right corner gradient with the stops mirrored. | + +The colour table itself comes from the array of [**FillColorPoint**](../Styles/Fill#fillcolorpoint-class) values inside [**Fill.ColorPoints**](../Styles/Fill#colorpoints), interpolated to the configured [**Granularity**](../Styles/Fill#granularity). diff --git a/docs/Reference/CustomControls/Enumerations/FontWeight.md b/docs/Reference/CustomControls/Enumerations/FontWeight.md new file mode 100644 index 00000000..ed2fb508 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/FontWeight.md @@ -0,0 +1,22 @@ +--- +title: FontWeight +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/FontWeight +--- +# FontWeight +{: .no_toc } + +The weight of a font face, on the standard 100 – 900 scale used by OpenType's `wght` axis and by CSS's `font-weight`. Carried by [**FontStyle.Weight**](../Styles/TextRendering#weight); availability of each weight depends on which faces are installed for the chosen font family. + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbThin**{: #tbThin } | 100 | The thinnest weight (also called Hairline). | +| **tbExtraLight**{: #tbExtraLight } | 200 | Also known as Ultra Light. | +| **tbLight**{: #tbLight } | 300 | A noticeably thinner stroke than the regular weight. | +| **tbNormal**{: #tbNormal } | 400 | The default weight. Also known as Regular. Newly-constructed [**FontStyle**](../Styles/TextRendering) objects start here. | +| **tbMedium**{: #tbMedium } | 500 | Slightly heavier than **tbNormal**. | +| **tbSemiBold**{: #tbSemiBold } | 600 | Heavier still; also known as Demi Bold. | +| **tbBold**{: #tbBold } | 700 | The standard bold weight. | +| **tbExtraBold**{: #tbExtraBold } | 800 | Also known as Ultra Bold. | +| **tbHeavy**{: #tbHeavy } | 900 | The heaviest weight. Also known as Black. | diff --git a/docs/Reference/CustomControls/Enumerations/PixelCount.md b/docs/Reference/CustomControls/Enumerations/PixelCount.md new file mode 100644 index 00000000..fafa96bf --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/PixelCount.md @@ -0,0 +1,15 @@ +--- +title: PixelCount +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/PixelCount +--- +# PixelCount +{: .no_toc } + +> [!NOTE] +> **PixelCount** is declared as an empty `Enum` block (with a placeholder `[_MAX] = 0` member) only because twinBASIC has not yet exposed a type-alias syntax such as `Type PixelCount = Long`. The source carries a `FIXME` comment noting the stand-in. Treat **PixelCount** as a **Long**-compatible type alias rather than as an enumeration with named members; when alias syntax becomes available, the enum stand-in will be replaced. + +A **Long**-compatible type alias used wherever a measurement in pixels is expected. Used pervasively across the package — every control's inherited **Left**, **Top**, **Width**, **Height** are typed as **PixelCount**, as are [**Corner.Radius**](../Styles/Corners#radius), [**Padding**](../Styles/Padding) fields, [**Border.StrokeSize**](../Styles/Borders#strokesize), and many more. + +The package treats one **PixelCount** as one *unscaled* pixel; the design-time canvas is at 96 DPI. The runtime scales the value for the active monitor's DPI when painting, so a 15-pixel corner radius looks the same on a 96-DPI and a 192-DPI display. Inside an [**ICustomControl.Paint**](../Framework/ICustomControl#paint) implementation, the scale factor is available through [**Canvas.RuntimeUICCGetDpiScaleFactor**](../Framework/Canvas#runtimeuiccgetdpiscalefactor). diff --git a/docs/Reference/CustomControls/Enumerations/PointSize.md b/docs/Reference/CustomControls/Enumerations/PointSize.md new file mode 100644 index 00000000..c8bfe0c6 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/PointSize.md @@ -0,0 +1,13 @@ +--- +title: PointSize +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/PointSize +--- +# PointSize +{: .no_toc } + +> [!NOTE] +> **PointSize** is declared as an empty `Enum` block (with a placeholder `[_MAX] = 0` member) only because twinBASIC has not yet exposed a type-alias syntax such as `Type PointSize = Long`. The source carries a `FIXME` comment noting the stand-in. Treat **PointSize** as a **Long**-compatible type alias rather than as an enumeration with named members; when alias syntax becomes available, the enum stand-in will be replaced. + +A **Long**-compatible type alias for a font size, expressed in *typographic points* (a point is 1⁄72 of an inch). Used by [**FontStyle.Size**](../Styles/TextRendering#size). New [**FontStyle**](../Styles/TextRendering) objects default to 12 points. diff --git a/docs/Reference/CustomControls/Enumerations/StartupPosition.md b/docs/Reference/CustomControls/Enumerations/StartupPosition.md new file mode 100644 index 00000000..435ca2fc --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/StartupPosition.md @@ -0,0 +1,17 @@ +--- +title: StartupPosition +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/StartupPosition +--- +# StartupPosition +{: .no_toc } + +The initial position of a form's window when it is first shown. Carried by [**WindowsFormOptions.StartUpPosition**](../WaynesForm/WindowsFormOptions#startupposition). Honoured once, at the form's first display; subsequent moves are at the user's discretion or controlled by code. + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbStartUpManual**{: #tbStartUpManual } | 0 | The form uses its design-time **Left** and **Top** values. | +| **tbStartUpCenterOwner**{: #tbStartUpCenterOwner } | 1 | The form is centred over its owner window. Falls back to **tbStartUpCenterScreen** if the form has no owner. | +| **tbStartUpCenterScreen**{: #tbStartUpCenterScreen } | 2 | The form is centred on the screen. | +| **tbStartUpWindowsDefault**{: #tbStartUpWindowsDefault } | 3 | Windows chooses the position using the same cascade-from-top-left logic the OS applies to new windows. The default for newly-constructed [**WindowsFormOptions**](../WaynesForm/WindowsFormOptions). | diff --git a/docs/Reference/CustomControls/Enumerations/TextAlignment.md b/docs/Reference/CustomControls/Enumerations/TextAlignment.md new file mode 100644 index 00000000..57bbdf89 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/TextAlignment.md @@ -0,0 +1,24 @@ +--- +title: TextAlignment +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/TextAlignment +--- +# TextAlignment +{: .no_toc } + +Horizontal and vertical alignment of text drawn inside a control's bounding rectangle. Carried by [**TextRendering.Alignment**](../Styles/TextRendering#alignment); each member combines one of three vertical positions (top, middle, bottom) with one of three horizontal positions (left, centre, right). + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbAlignTopLeft**{: #tbAlignTopLeft } | 0 | Top edge, left-aligned. | +| **tbAlignTopCenter**{: #tbAlignTopCenter } | 1 | Top edge, horizontally centred. | +| **tbAlignTopRight**{: #tbAlignTopRight } | 2 | Top edge, right-aligned. | +| **tbAlignMiddleLeft**{: #tbAlignMiddleLeft } | 3 | Vertically centred, left-aligned. | +| **tbAlignMiddleCenter**{: #tbAlignMiddleCenter } | 4 | Vertically centred, horizontally centred. The default for newly-constructed [**TextRendering**](../Styles/TextRendering) objects. | +| **tbAlignMiddleRight**{: #tbAlignMiddleRight } | 5 | Vertically centred, right-aligned. | +| **tbAlignBottomLeft**{: #tbAlignBottomLeft } | 6 | Bottom edge, left-aligned. | +| **tbAlignBottomCenter**{: #tbAlignBottomCenter } | 7 | Bottom edge, horizontally centred. | +| **tbAlignBottomRight**{: #tbAlignBottomRight } | 8 | Bottom edge, right-aligned. | + +The padding added around the text by [**TextRendering.Padding**](../Styles/TextRendering#padding) is applied first; the alignment then positions the text inside the padded region. diff --git a/docs/Reference/CustomControls/Enumerations/TextOverflowMode.md b/docs/Reference/CustomControls/Enumerations/TextOverflowMode.md new file mode 100644 index 00000000..7f394ba0 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/TextOverflowMode.md @@ -0,0 +1,17 @@ +--- +title: TextOverflowMode +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/TextOverflowMode +--- +# TextOverflowMode +{: .no_toc } + +Controls how text that does not fit inside the available rectangle is truncated. Carried by [**TextRendering.OverflowMode**](../Styles/TextRendering#overflowmode). + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbAllowPartialChars**{: #tbAllowPartialChars } | 0 | Truncate at the available width, allowing the final glyph to be clipped mid-character. | +| **tbDisallowPartialChars**{: #tbDisallowPartialChars } | 1 | Truncate at the last fully-visible character; no half-glyph at the edge. Used by [**WaynesTextBox**](../WaynesTextBox/) so the caret never falls between glyphs of a surrogate pair. | +| **tbAppendEllipsis**{: #tbAppendEllipsis } | 2 | Truncate at the last fully-visible character and append `…` if any characters were dropped. The default for newly-constructed [**TextRendering**](../Styles/TextRendering) objects. | +| **tbShrinkToFit**{: #tbShrinkToFit } | 3 | Reduce the rendered font size until the entire string fits without truncation. Used by [**WaynesTimer**](../WaynesTimer) so its design-time clock glyph scales with the control. | diff --git a/docs/Reference/CustomControls/Enumerations/WindowState.md b/docs/Reference/CustomControls/Enumerations/WindowState.md new file mode 100644 index 00000000..f7b396eb --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/WindowState.md @@ -0,0 +1,16 @@ +--- +title: WindowState +parent: Enumerations +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/WindowState +--- +# WindowState +{: .no_toc } + +The window state of a [**WaynesForm**](../WaynesForm/) — minimized, restored to normal size, or maximized to fill its monitor. Carried by [**WindowsFormOptions.WindowState**](../WaynesForm/WindowsFormOptions#windowstate); honoured once when the form is first shown. + +| Constant | Value | Description | +|----------|-------|-------------| +| **tbNormal**{: #tbNormal } | 0 | The window is shown at its design-time size. The default for newly-constructed [**WindowsFormOptions**](../WaynesForm/WindowsFormOptions). | +| **tbMinimized**{: #tbMinimized } | 1 | The window is minimized to the taskbar on first display. | +| **tbMaximized**{: #tbMaximized } | 2 | The window is maximized to fill its monitor on first display. | diff --git a/docs/Reference/CustomControls/Enumerations/index.md b/docs/Reference/CustomControls/Enumerations/index.md new file mode 100644 index 00000000..a6cc8557 --- /dev/null +++ b/docs/Reference/CustomControls/Enumerations/index.md @@ -0,0 +1,26 @@ +--- +title: Enumerations +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Enumerations/ +has_toc: false +--- + +# Enumerations + +The enumerations used by the **CustomControls** package's properties and style objects. All live in `Module Constants` inside the **CustomControls DESIGNER** library, with the exception of the [**SliderDirection**](../WaynesSlider/#sliderdirection) and [**SliderDisplayValueFormat**](../WaynesSlider/#sliderdisplayvalueformat) enums nested inside the **WaynesSlider** control. + +| Enumeration | Used by | +|-------------|---------| +| [BorderStyle](BorderStyle) | [**WindowsFormOptions.BorderStyle**](../WaynesForm/WindowsFormOptions#borderstyle) | +| [ColorRGBA](ColorRGBA) | [**FillColorPoint.Color**](../Styles/Fill#color); `Long`-compatible type alias for ABGR colours | +| [CornerShape](CornerShape) | [**Corner.Shape**](../Styles/Corners#shape) | +| [Customtate](Customtate) | reserved; duplicate of [**WindowState**](WindowState) | +| [DockMode](DockMode) | the inherited **Dock** property of every control | +| [FillPattern](FillPattern) | [**Fill.Pattern**](../Styles/Fill#pattern) | +| [FontWeight](FontWeight) | [**FontStyle.Weight**](../Styles/TextRendering#weight) | +| [PixelCount](PixelCount) | size, position, padding, stroke widths, radii; `Long`-compatible type alias | +| [PointSize](PointSize) | [**FontStyle.Size**](../Styles/TextRendering#size); `Long`-compatible type alias | +| [StartupPosition](StartupPosition) | [**WindowsFormOptions.StartUpPosition**](../WaynesForm/WindowsFormOptions#startupposition) | +| [TextAlignment](TextAlignment) | [**TextRendering.Alignment**](../Styles/TextRendering#alignment) | +| [TextOverflowMode](TextOverflowMode) | [**TextRendering.OverflowMode**](../Styles/TextRendering#overflowmode) | +| [WindowState](WindowState) | [**WindowsFormOptions.WindowState**](../WaynesForm/WindowsFormOptions#windowstate) | diff --git a/docs/Reference/CustomControls/Framework/Canvas.md b/docs/Reference/CustomControls/Framework/Canvas.md new file mode 100644 index 00000000..2353888c --- /dev/null +++ b/docs/Reference/CustomControls/Framework/Canvas.md @@ -0,0 +1,73 @@ +--- +title: Canvas +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/Canvas +has_toc: false +--- + +# Canvas type (UDT) +{: .no_toc } + +The drawing surface a custom control paints onto. Passed to [**ICustomControl.Paint**](ICustomControl#paint) on every redraw pass and used exclusively from inside that method — its lifetime is the duration of the single paint pass. + +A custom control builds up one or more `ElementDescriptor` records describing the rectangles it wants to draw — each carrying a position, size, fill, borders, corners, text, cursor, tab-index, and a set of `AddressOf`-registered input callbacks — and hands each descriptor to [**RuntimeUICCCanvasAddElement**](#runtimeuicccanvasaddelement). The framework rasterises the descriptor, routes hit-testing to the registered callbacks, and (where the descriptor opts in) tracks keyboard tab order and focus. + +```tb +Private Sub OnPaint(ByVal Canvas As CustomControls.Canvas) _ + Implements CustomControls.ICustomControl.Paint + + Dim descriptor As ElementDescriptor + With descriptor + .Left = 0 + .Top = 0 + .Width = Canvas.RuntimeUICCGetWidth() + .Height = Canvas.RuntimeUICCGetHeight() + Set .BackgroundFill = Me.NormalState.BackgroundFill + .Text = Me.Caption + Set .TextRenderingOptions = Me.NormalState.TextRendering + .OnClick = AddressOf BtnClick + Canvas.RuntimeUICCCanvasAddElement(descriptor) + End With +End Sub +``` + +## Methods + +### RuntimeUICCCanvasAddElement +{: .no_toc } + +Adds an `ElementDescriptor` to the canvas. Each element becomes one painted rectangle plus its input-handling region. Descriptors are rendered in the order they are added, so later elements paint on top of earlier ones. + +Syntax: *Canvas*.**RuntimeUICCCanvasAddElement** *ElementDescriptor* + +*ElementDescriptor* +: *required* A `ByRef` reference to the populated `ElementDescriptor` UDT. The framework copies the values it needs out of the record; the caller can reuse the variable for the next element. + +### RuntimeUICCGetDpi +{: .no_toc } + +Returns the DPI of the monitor the control is currently displayed on, as an integer (the standard 96 / 120 / 144 / … values). + +Syntax: *Canvas*.**RuntimeUICCGetDpi** ( ) **As Long** + +### RuntimeUICCGetDpiScaleFactor +{: .no_toc } + +Returns the DPI scale factor — `RuntimeUICCGetDpi / 96` — as a **Double**. Multiply [**PixelCount**](../Enumerations/PixelCount)-typed measurements by this value to convert from design-time pixels to device pixels at paint time. + +Syntax: *Canvas*.**RuntimeUICCGetDpiScaleFactor** ( ) **As Double** + +### RuntimeUICCGetHeight +{: .no_toc } + +Returns the height of the canvas in device pixels. + +Syntax: *Canvas*.**RuntimeUICCGetHeight** ( ) **As Long** + +### RuntimeUICCGetWidth +{: .no_toc } + +Returns the width of the canvas in device pixels. + +Syntax: *Canvas*.**RuntimeUICCGetWidth** ( ) **As Long** diff --git a/docs/Reference/CustomControls/Framework/CustomControlContext.md b/docs/Reference/CustomControls/Framework/CustomControlContext.md new file mode 100644 index 00000000..5afa1c9e --- /dev/null +++ b/docs/Reference/CustomControls/Framework/CustomControlContext.md @@ -0,0 +1,65 @@ +--- +title: CustomControlContext +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/CustomControlContext +has_toc: false +--- + +# CustomControlContext class +{: .no_toc } + +The callback object handed to a custom control's [**Initialize**](ICustomControl#initialize). Holds the connection back into the framework — used to deserialize designer-set property values, request repaints, create timers, and move the keyboard focus between elements the control has drawn. + +Custom controls store the **CustomControlContext** in a private field (typically called **ControlContext**) so that they can call back into the framework at any point after **Initialize** has returned. The form-class counterpart [**CustomFormContext**](CustomFormContext) extends this surface with **Show** and **Close**. + +```tb +Private Sub OnInitialize(ByVal Ctx As CustomControls.CustomControlContext) _ + Implements CustomControls.ICustomControl.Initialize + + ' Load any serialized property values + If Not Ctx.GetSerializer.RuntimeUISrzDeserialize(Me, False) Then + InitializeDefaultValues + End If + + ' Remember the context for later + Set Me.ControlContext = Ctx +End Sub +``` + +## Methods + +### ChangeFocusedElement +{: .no_toc } + +Asks the framework to move the keyboard focus to a particular `ElementTabIndex` value, as if the user had pressed **TAB** until it landed there. Used by [**WaynesGrid**](../WaynesGrid/) when a cell is selected programmatically — the grid changes its **SelectedCellX** / **SelectedCellY** and then calls this method so that the form-level focus tracking matches. + +Syntax: *object*.**ChangeFocusedElement** *ElementTabIndex* + +*ElementTabIndex* +: *required* A **Long** matching the **ElementTabIndex** of an element that was added to the canvas in the most recent paint pass. + +### CreateTimer +{: .no_toc } + +Returns a new [**CustomControlTimer**](CustomControlTimer) bound to this control's lifetime. The timer is **Disabled** on creation; the caller sets [**Interval**](CustomControlTimer#interval), subscribes to the timer's **OnTimer** event, and sets [**Enabled**](CustomControlTimer#enabled) to **True** to start it. + +Syntax: *object*.**CreateTimer** ( ) **As stdole.IUnknown** + +The framework returns the timer typed as **stdole.IUnknown**; cast with `CType(Of CustomControlTimer)(…)` to get a strongly-typed reference. [**WaynesTimer**](../WaynesTimer) and [**WaynesSlider**](../WaynesSlider/) both use this pattern. + +### GetSerializer +{: .no_toc } + +Returns the [**SerializeInfo**](SerializeInfo) handle for this control instance. The serializer surfaces the deserialization entry point and the run-time / design-time mode flags. + +Syntax: *object*.**GetSerializer** ( ) **As SerializeInfo** + +### Repaint +{: .no_toc } + +Tells the framework that the control's appearance has changed and that the canvas should be repainted at the next opportunity. The framework eventually calls back into [**ICustomControl.Paint**](ICustomControl#paint); calling **Repaint** multiple times in quick succession produces at most one paint. + +Syntax: *object*.**Repaint** ( ) + +Every concrete `Waynes…` control hooks the **OnChanged** events on its state and style sub-objects, and calls **Repaint** from the handler — so a runtime assignment like `btn.NormalState.BackgroundFill.ColorPoints.SetSolidColor vbBlue` triggers an automatic redraw. diff --git a/docs/Reference/CustomControls/Framework/CustomControlTimer.md b/docs/Reference/CustomControls/Framework/CustomControlTimer.md new file mode 100644 index 00000000..8e28ca4c --- /dev/null +++ b/docs/Reference/CustomControls/Framework/CustomControlTimer.md @@ -0,0 +1,60 @@ +--- +title: CustomControlTimer +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/CustomControlTimer +has_toc: false +--- + +# CustomControlTimer class +{: .no_toc } + +A timer created by [**CustomControlContext.CreateTimer**](CustomControlContext#createtimer) and owned by the control that created it. The timer raises [**OnTimer**](#ontimer) at the rate given by [**Interval**](#interval), once it has been started by setting [**Enabled**](#enabled) to **True**. + +The framework returns timers typed as **stdole.IUnknown**; cast to **CustomControlTimer** with `CType(Of CustomControlTimer)(…)` before storing. The control should also declare the field with `WithEvents` so that the **OnTimer** event can be handled. + +```tb +Private WithEvents InternalTimer As CustomControlTimer + +Private Sub OnInitialize(ByVal Ctx As CustomControls.CustomControlContext) _ + Implements CustomControls.ICustomControl.Initialize + + Set Me.ControlContext = Ctx + Set Me.InternalTimer = CType(Of CustomControlTimer)(Ctx.CreateTimer()) + Me.InternalTimer.Interval = 250 + Me.InternalTimer.Enabled = True +End Sub + +Private Sub OnTimer() Handles InternalTimer.OnTimer + ' fire every 250ms +End Sub +``` + +[**WaynesTimer**](../WaynesTimer) wraps a single **CustomControlTimer** and re-exposes its **Interval** / **Enabled** as designer-visible properties. [**WaynesSlider**](../WaynesSlider/) uses one as an internal mouse-down auto-repeat timer. + +## Properties + +### Enabled +{: .no_toc } + +Whether the timer is currently running. Setting to **True** starts it; setting to **False** stops it. **Boolean**. + +Syntax: *object*.**Enabled** [ = *value* ] + +### Interval +{: .no_toc } + +The number of milliseconds between successive [**OnTimer**](#ontimer) events. **Long**. A timer with an interval of 0 never fires. + +Syntax: *object*.**Interval** [ = *value* ] + +Changing **Interval** while the timer is enabled takes effect on the next tick. + +## Events + +### OnTimer +{: .no_toc } + +Raised every [**Interval**](#interval) milliseconds while the timer is enabled. + +Syntax: *object*\_**OnTimer**( ) diff --git a/docs/Reference/CustomControls/Framework/CustomControlsCollection.md b/docs/Reference/CustomControls/Framework/CustomControlsCollection.md new file mode 100644 index 00000000..371ad4e9 --- /dev/null +++ b/docs/Reference/CustomControls/Framework/CustomControlsCollection.md @@ -0,0 +1,81 @@ +--- +title: CustomControlsCollection +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/CustomControlsCollection +has_toc: false +--- + +# CustomControlsCollection class +{: .no_toc } + +The collection of controls hosted on a custom form. Reached as the **Controls** property of a [**WaynesForm**](../WaynesForm/). Supports indexed access by integer or name, enumeration with **For Each**, and runtime add / remove of controls. + +```tb +Dim ctl As Object +For Each ctl In MyForm.Controls + Debug.Print ctl.Name +Next +``` + +## Properties + +### Count +{: .no_toc } + +The number of controls in the collection. **Long**. Read-only. + +Syntax: *object*.**Count** + +### Item +{: .no_toc } + +Returns the control at the given index or with the given name. The **Default property** — the **Controls** ( *…* ) shorthand calls **Item**. + +Syntax: *object*.**Item** ( *IndexOrName* ) **As Object** + +*IndexOrName* +: *required* A **Variant** that is either a **Long** zero-based index or a **String** matching the control's [**Name**](../#controls). + +## Methods + +### Add +{: .no_toc } + +Adds a new control to the collection by class **ProgID**, gives it a name, and attaches it to a container. + +Syntax: *object*.**Add** ( *ProgId*, *ControlName*, *Container* ) **As Object** + +*ProgId* +: *required* A **String** holding the class **ProgID** of the control to create. + +*ControlName* +: *required* A **String** giving the **Name** to assign to the new control. + +*Container* +: *required* An **Object** reference to the form, frame, or other container that will host the new control. + +The newly-created control is returned, typed as **Object**. + +### Remove +{: .no_toc } + +Removes the control at the given index or with the given name from the collection. + +Syntax: *object*.**Remove** *IndexOrName* + +*IndexOrName* +: *required* A **Variant** that is either a **Long** zero-based index or a **String** matching the control's [**Name**](../#controls). + +## Iteration + +A `For Each` loop over the collection produces every hosted control in turn: + +```tb +Dim ctl As Object +For Each ctl In MyForm.Controls + ' … +Next +``` + +The hidden member that drives this is `_NewEnum`; application code does not call it directly. diff --git a/docs/Reference/CustomControls/Framework/CustomFormContext.md b/docs/Reference/CustomControls/Framework/CustomFormContext.md new file mode 100644 index 00000000..d9952aa0 --- /dev/null +++ b/docs/Reference/CustomControls/Framework/CustomFormContext.md @@ -0,0 +1,42 @@ +--- +title: CustomFormContext +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/CustomFormContext +has_toc: false +--- + +# CustomFormContext class +{: .no_toc } + +The form-class counterpart to [**CustomControlContext**](CustomControlContext). Extends the base context with **Show** and **Close** — the operations a top-level form needs that an embedded control does not. + +[**WaynesForm**](../WaynesForm/) receives its context as a [**CustomControlContext**](CustomControlContext) (because it implements [**ICustomControl**](ICustomControl)) and casts it to **CustomFormContext** internally so that it can call **Show** from its own **Show** method and **Close** from its **Close** method. + +```tb +Private Sub OnInitialize(ByVal Ctx As CustomControls.CustomControlContext) _ + Implements CustomControls.ICustomControl.Initialize + + Set Me.ControlContext = CType(Of CustomFormContext)(Ctx) +End Sub +``` + +## Inherited + +A **CustomFormContext** carries every member from [**CustomControlContext**](CustomControlContext) — [**ChangeFocusedElement**](CustomControlContext#changefocusedelement), [**CreateTimer**](CustomControlContext#createtimer), [**GetSerializer**](CustomControlContext#getserializer), and [**Repaint**](CustomControlContext#repaint) — and adds the two form-specific members below. + +## Methods + +### Close +{: .no_toc } + +Closes the underlying window. Equivalent to the user clicking the title-bar close button. Application code typically calls [**WaynesForm.Close**](../WaynesForm/#close), which in turn calls into this method. + +Syntax: *object*.**Close** ( ) + +### Show +{: .no_toc } + +Shows the underlying window. Application code typically calls [**WaynesForm.Show**](../WaynesForm/#show), which in turn calls into this method. + +Syntax: *object*.**Show** ( ) diff --git a/docs/Reference/CustomControls/Framework/ICustomControl.md b/docs/Reference/CustomControls/Framework/ICustomControl.md new file mode 100644 index 00000000..d2fb56c4 --- /dev/null +++ b/docs/Reference/CustomControls/Framework/ICustomControl.md @@ -0,0 +1,70 @@ +--- +title: ICustomControl +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/ICustomControl +has_toc: false +--- + +# ICustomControl interface +{: .no_toc } + +The interface every custom control implements. The framework calls **Initialize** once after the control has been instantiated and its serialized property values have been deserialized, **Paint** every time the framework needs to redraw the control's area, and **Destroy** once when the control is being released. + +The eight concrete `Waynes…` classes in the package all implement this interface, alongside an inherited mixin base class for the standard layout / name members. + +```tb +Class MyControl + Implements CustomControls.ICustomControl + + Private Sub OnInitialize(ByVal Context As CustomControls.CustomControlContext) _ + Implements CustomControls.ICustomControl.Initialize + ' … + End Sub + + Private Sub OnDestroy() _ + Implements CustomControls.ICustomControl.Destroy + ' … + End Sub + + Private Sub OnPaint(ByVal Canvas As CustomControls.Canvas) _ + Implements CustomControls.ICustomControl.Paint + ' … + End Sub +End Class +``` + +## Methods + +### Destroy +{: .no_toc } + +Called once when the control is being released. The implementation should drop any references it holds to objects that themselves hold references back to it, so that the reference graph can collapse cleanly. + +Syntax: *object*.**Destroy** ( ) + +### Initialize +{: .no_toc } + +Called once after the framework has constructed the control and deserialized any designer-set property values from the form's `.frm` data into the new instance. + +Syntax: *object*.**Initialize** ( *Context* ) + +*Context* +: *required* The [**CustomControlContext**](CustomControlContext) for this control instance. Store it (typically as a class field named **ControlContext**) — it is the only way to request repaints, create timers, or check the runtime mode after **Initialize** returns. + +A common implementation calls **Context.GetSerializer().RuntimeUISrzDeserialize(Me, False)** to load designer-set property values into the instance; if the call returns **False**, no serialized data was found and the control should apply its own defaults. + +### Paint +{: .no_toc } + +Called every time the framework needs to redraw the control's client area. The implementation builds one or more `ElementDescriptor` records describing the rectangles to draw and hands each to *Canvas*. **RuntimeUICCCanvasAddElement**. + +Syntax: *object*.**Paint** ( *Canvas* ) + +*Canvas* +: *required* The [**Canvas**](Canvas) drawing surface for this paint pass. Its **RuntimeUICCGetWidth**, **RuntimeUICCGetHeight**, and **RuntimeUICCGetDpiScaleFactor** methods supply the size and DPI of the area being painted, in device pixels. + +A descriptor may carry event callbacks (`OnClick`, `OnMouseDown`, …) as `AddressOf` pointers; the framework dispatches input back through those pointers without the control needing to subscribe explicitly to anything. + +A control should request additional repaints by calling [**CustomControlContext.Repaint**](CustomControlContext#repaint), not by calling **Paint** directly — the framework decides when to issue the actual paint pass. diff --git a/docs/Reference/CustomControls/Framework/ICustomForm.md b/docs/Reference/CustomControls/Framework/ICustomForm.md new file mode 100644 index 00000000..9dca2372 --- /dev/null +++ b/docs/Reference/CustomControls/Framework/ICustomForm.md @@ -0,0 +1,43 @@ +--- +title: ICustomForm +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/ICustomForm +has_toc: false +--- + +# ICustomForm interface +{: .no_toc } + +The form-class counterpart to [**ICustomControl**](ICustomControl). Custom *form* classes — top-level windows that host other custom controls — implement this interface instead. The shape is identical to **ICustomControl** except that the **Initialize** callback receives a [**CustomFormContext**](CustomFormContext) (which extends [**CustomControlContext**](CustomControlContext) with **Show** and **Close**) rather than a plain **CustomControlContext**. + +[**WaynesForm**](../WaynesForm/), the package's only concrete form class, does in fact implement [**ICustomControl**](ICustomControl) and cast its context to **CustomFormContext** internally — the **ICustomForm** interface is published for parity with **ICustomControl** but is not currently consumed by any class shipped with the package. + +## Methods + +### Destroy +{: .no_toc } + +Called once when the form is being released. See [**ICustomControl.Destroy**](ICustomControl#destroy). + +Syntax: *object*.**Destroy** ( ) + +### Initialize +{: .no_toc } + +Called once after the framework has constructed the form and deserialized any designer-set property values into it. + +Syntax: *object*.**Initialize** ( *Context* ) + +*Context* +: *required* The [**CustomFormContext**](CustomFormContext) for this form instance. + +### Paint +{: .no_toc } + +Called every time the framework needs to redraw the form's client area. See [**ICustomControl.Paint**](ICustomControl#paint). + +Syntax: *object*.**Paint** ( *Canvas* ) + +*Canvas* +: *required* The [**Canvas**](Canvas) drawing surface for this paint pass. diff --git a/docs/Reference/CustomControls/Framework/SerializeInfo.md b/docs/Reference/CustomControls/Framework/SerializeInfo.md new file mode 100644 index 00000000..69646729 --- /dev/null +++ b/docs/Reference/CustomControls/Framework/SerializeInfo.md @@ -0,0 +1,92 @@ +--- +title: SerializeInfo +parent: Framework +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/SerializeInfo +has_toc: false +--- + +# SerializeInfo type (UDT) +{: .no_toc } + +The per-instance serializer for a custom control, returned by [**CustomControlContext.GetSerializer**](CustomControlContext#getserializer). The main entry point is [**RuntimeUISrzDeserialize**](#runtimeuisrzdeserialize) — called from a control's [**Initialize**](ICustomControl#initialize) to load the designer-set property values that were saved into the form's serialized data. The remaining members expose framework state — design-mode flag, runtime / report mode, owner window handle — that a control may need while initializing. + +```tb +Private Sub OnInitialize(ByVal Ctx As CustomControls.CustomControlContext) _ + Implements CustomControls.ICustomControl.Initialize + + With Ctx.GetSerializer + If Not .RuntimeUISrzDeserialize(Me, False) Then + InitializeDefaultValues + End If + + Me.IsDesignMode = .RuntimeUISrzIsDesignMode() + End With + + Set Me.ControlContext = Ctx +End Sub +``` + +## Methods + +### RuntimeUISrzDeserialize +{: .no_toc } + +Loads the serialized property values for this control instance into *Object*. Returns **True** if serialized data was present and was applied, or **False** if no data was found — in which case the control should apply its own defaults. + +Syntax: *SerializeInfo*.**RuntimeUISrzDeserialize** ( *Object*, *UseOuterOwner* ) **As Boolean** + +*Object* +: *required* The custom control instance whose properties should be populated. From inside an **Initialize** implementation this is **Me**. + +*UseOuterOwner* +: *required* A **Boolean** flag for advanced use; pass **False** in normal cases. + +### RuntimeUISrzGetFormHWND +{: .no_toc } + +Returns the **HWND** of the parent form's underlying Win32 window. + +Syntax: *SerializeInfo*.**RuntimeUISrzGetFormHWND** ( ) **As LongPtr** + +### RuntimeUISrzGetOrientationHint +{: .no_toc } + +Returns a hint indicating the orientation of the parent form. **Long**. + +Syntax: *SerializeInfo*.**RuntimeUISrzGetOrientationHint** ( ) **As Long** + +### RuntimeUISrzGetRootCLSID +{: .no_toc } + +Returns the CLSID of the form class that owns this control, as a **String**. + +Syntax: *SerializeInfo*.**RuntimeUISrzGetRootCLSID** ( ) **As String** + +### RuntimeUISrzGetRootClassDispatch +{: .no_toc } + +Returns the form-class instance that owns this control, typed as an **Object**. + +Syntax: *SerializeInfo*.**RuntimeUISrzGetRootClassDispatch** ( ) **As Object** + +### RuntimeUISrzIsDesignMode +{: .no_toc } + +Returns **True** if the control is being created at design time (inside the form designer) rather than at run time. Controls that want to render a placeholder at design time only — like [**WaynesTimer**](../WaynesTimer), which draws its 🕑 glyph only when **IsDesignMode** is **True** — read this flag during **Initialize**. + +Syntax: *SerializeInfo*.**RuntimeUISrzIsDesignMode** ( ) **As Boolean** + +### RuntimeUISrzIsReportMode +{: .no_toc } + +Returns **True** if the control is being created as part of a report-rendering pass. + +Syntax: *SerializeInfo*.**RuntimeUISrzIsReportMode** ( ) **As Boolean** + +### RuntimeUISrzIsRuntimeAdded +{: .no_toc } + +Returns **True** if the control was added at run time (via [**CustomControlsCollection.Add**](CustomControlsCollection#add)) rather than placed in the form designer. + +Syntax: *SerializeInfo*.**RuntimeUISrzIsRuntimeAdded** ( ) **As Boolean** diff --git a/docs/Reference/CustomControls/Framework/index.md b/docs/Reference/CustomControls/Framework/index.md new file mode 100644 index 00000000..a215ecfb --- /dev/null +++ b/docs/Reference/CustomControls/Framework/index.md @@ -0,0 +1,55 @@ +--- +title: Framework +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Framework/ +has_toc: false +--- + +# Framework + +The framework half of the [**CustomControls**](..) package — the interfaces, callback objects, and drawing primitives an *author* of a custom control writes against. The eight concrete `Waynes…` controls in the package are themselves built on this surface; the same pieces are available to user code that needs to implement an entirely new custom control. + +A custom control: + +1. Implements [**ICustomControl**](ICustomControl) (or [**ICustomForm**](ICustomForm) for a form-class custom control). +2. Stores the [**CustomControlContext**](CustomControlContext) handed to it on **Initialize** and uses it to request repaints, create timers, or change the focused element. +3. Inside **Paint**, builds one or more `ElementDescriptor` records and hands them to the [**Canvas**](Canvas) via **RuntimeUICCCanvasAddElement** — the framework rasterises them, handles input routing, and dispatches events back through the descriptor's `AddressOf`-registered callbacks. + +```tb +Class MyControl + Implements CustomControls.ICustomControl + + Private Context As CustomControls.CustomControlContext + + Private Sub OnInitialize(ByVal Ctx As CustomControls.CustomControlContext) _ + Implements CustomControls.ICustomControl.Initialize + Set Me.Context = Ctx + End Sub + + Private Sub OnDestroy() _ + Implements CustomControls.ICustomControl.Destroy + End Sub + + Private Sub OnPaint(ByVal Canvas As CustomControls.Canvas) _ + Implements CustomControls.ICustomControl.Paint + ' build ElementDescriptor records and call Canvas.RuntimeUICCCanvasAddElement + End Sub +End Class +``` + +## Interfaces + +- [ICustomControl](ICustomControl) -- the interface implemented by every concrete custom control: **Initialize**, **Destroy**, **Paint** +- [ICustomForm](ICustomForm) -- the analogous interface for custom form classes + +## Callback objects + +- [CustomControlContext](CustomControlContext) -- the callback object passed to **Initialize**; **GetSerializer**, **Repaint**, **CreateTimer**, **ChangeFocusedElement** +- [CustomFormContext](CustomFormContext) -- a **CustomControlContext** extended with **Show** and **Close**, passed to a custom form's **Initialize** +- [CustomControlTimer](CustomControlTimer) -- the timer returned by **CustomControlContext.CreateTimer**; **Interval**, **Enabled**, **OnTimer** event +- [CustomControlsCollection](CustomControlsCollection) -- the **Controls** collection on a [**WaynesForm**](../WaynesForm/) or any other custom form + +## Drawing primitives + +- [Canvas](Canvas) -- the drawing surface passed to **Paint**; **RuntimeUICCCanvasAddElement**, plus size and DPI accessors +- [SerializeInfo](SerializeInfo) -- the per-instance serializer reached via **CustomControlContext.GetSerializer**; **RuntimeUISrzDeserialize**, design-mode flags, owner handle, runtime mode diff --git a/docs/Reference/CustomControls/Styles/Anchors.md b/docs/Reference/CustomControls/Styles/Anchors.md new file mode 100644 index 00000000..7eb6ef35 --- /dev/null +++ b/docs/Reference/CustomControls/Styles/Anchors.md @@ -0,0 +1,52 @@ +--- +title: Anchors +parent: Styles +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/Anchors +has_toc: false +--- + +# Anchors class +{: .no_toc } + +Determines which sides of a control are pinned to its parent container when the container is resized. A control with both **Left** and **Right** set to **True**, for example, keeps its left and right edges at the same distance from the container's edges, stretching horizontally as the container grows. Controls receive this object through their inherited **Anchors** property. + +The default is **Left**=**True**, **Top**=**True**, **Right**=**False**, **Bottom**=**False** — the control stays at the same offset from the upper-left corner of the container and does not resize. To make a control fill the bottom of its container as the form is resized, anchor it to **Left**, **Right**, and **Bottom**. + +```tb +With txtNotes.Anchors + .Left = True + .Top = True + .Right = True + .Bottom = True +End With +``` + +## Properties + +### Bottom +{: .no_toc } + +When **True**, the control's bottom edge stays at the same distance from the container's bottom edge. **Boolean**, default **False**. + +### Left +{: .no_toc } + +When **True**, the control's left edge stays at the same distance from the container's left edge. **Boolean**, default **True**. + +### Right +{: .no_toc } + +When **True**, the control's right edge stays at the same distance from the container's right edge. **Boolean**, default **False**. + +### Top +{: .no_toc } + +When **True**, the control's top edge stays at the same distance from the container's top edge. **Boolean**, default **True**. + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the four anchor flags is assigned. The hosting control listens for this event and re-applies the docking layout. Application code does not normally subscribe directly. diff --git a/docs/Reference/CustomControls/Styles/Borders.md b/docs/Reference/CustomControls/Styles/Borders.md new file mode 100644 index 00000000..22c43abc --- /dev/null +++ b/docs/Reference/CustomControls/Styles/Borders.md @@ -0,0 +1,94 @@ +--- +title: Borders +parent: Styles +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/Borders +has_toc: false +--- + +# Borders class +{: .no_toc } + +The collection of border strokes drawn around a region. Each stroke is an independent [**Border**](#border-class) sub-object with its own thickness, fill, and blending behaviour, layered in source order. A single thin black outline is a one-element collection — easiest constructed by calling [**SetSimpleBorder**](#setsimpleborder). + +Reached as `.Borders`, [**CellRenderingOptions.Borders**](../WaynesGrid/CellRenderingOptions#borders), and the slider's `.BackgroundBorders` / `BlockBorders`. The array of [**Border**](#border-class) sub-objects on a [**TextRendering**](TextRendering)'s **Outlines** member uses the same element type. + +```tb +btnGo.NormalState.Borders.SetSimpleBorder StrokeSize:=1, ColorRGB:=vbBlack +``` + +* TOC +{:toc} + +## Properties + +### Elements +{: .no_toc } + +The array of [**Border**](#border-class) sub-objects, drawn in order from index 0 outward. Read-write but in practice populated through [**SetSimpleBorder**](#setsimpleborder) or [**SetSimpleBorderRGBA**](#setsimpleborderrgba). + +## Methods + +### SetSimpleBorder +{: .no_toc } + +Replaces the [**Elements**](#elements) array with a single border stroke of the given thickness and fully-opaque colour. + +Syntax: *object*.**SetSimpleBorder** *StrokeSize*, *ColorRGB* + +*StrokeSize* +: *required* A **Long** giving the stroke thickness in pixels. + +*ColorRGB* +: *required* A **Long** RGB colour for the stroke fill. + +### SetSimpleBorderRGBA +{: .no_toc } + +Replaces the [**Elements**](#elements) array with a single border stroke whose alpha is taken from the supplied [**ColorRGBA**](../Enumerations/ColorRGBA) rather than forced opaque. Useful for transparent borders that are present only as visual padding (the slider uses a fully transparent border on the **BlockBorders** to indent the block inside the background). + +Syntax: *object*.**SetSimpleBorderRGBA** *StrokeSize*, *ColorRGBA* + +*StrokeSize* +: *required* A **Long** giving the stroke thickness in pixels. + +*ColorRGBA* +: *required* A [**ColorRGBA**](../Enumerations/ColorRGBA) value for the stroke fill. + +## Events + +### OnChanged +{: .no_toc } + +Raised when the [**Elements**](#elements) array is reassigned, or when any single [**Border**](#border-class) element raises its own **OnChanged**. + +## Border class + +A single border stroke. Elements of [**Borders.Elements**](#elements), and also of [**TextRendering.Outlines**](TextRendering#outlines). + +### BlendWithBackgroundFill +{: .no_toc } + +When **True**, the border's colour alpha-blends with the control's **BackgroundFill** rather than with whatever is painted underneath the control. Lets a translucent border colour pick up the background tint instead of the form's. **Boolean**. Default: **False**. + +### Fill +{: .no_toc } + +The [**Fill**](Fill) that supplies the colour or gradient used to stroke the border. Newly-constructed [**Border**](#border-class) objects pre-set this to a solid black fill. + +### StrokeSize +{: .no_toc } + +The stroke thickness in pixels. [**PixelCount**](../Enumerations/PixelCount). Default: 1. + +### New +{: .no_toc } + +Constructs a [**Border**](#border-class) with a default solid-black [**Fill**](#fill). + +Syntax: **New Border** + +### OnChanged +{: .no_toc } + +Raised when [**StrokeSize**](#strokesize), [**Fill**](#fill), or [**BlendWithBackgroundFill**](#blendwithbackgroundfill) is assigned, or when the contained [**Fill**](#fill) raises its own **OnChanged**. diff --git a/docs/Reference/CustomControls/Styles/Corners.md b/docs/Reference/CustomControls/Styles/Corners.md new file mode 100644 index 00000000..ea942e6e --- /dev/null +++ b/docs/Reference/CustomControls/Styles/Corners.md @@ -0,0 +1,85 @@ +--- +title: Corners +parent: Styles +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/Corners +has_toc: false +--- + +# Corners class +{: .no_toc } + +The four corners of a rendered region. Each corner is an independent [**Corner**](#corner-class) sub-object — the shape and radius can vary corner by corner — letting a control round one corner while notching another. Reached as `.Corners`, [**CellRenderingOptions.Corners**](../WaynesGrid/CellRenderingOptions#corners), and the slider's `.BackgroundCorners` / `BlockCorners`. + +```tb +With btnGo.NormalState.Corners + .SetAll tbCurve, 12 ' all four corners 12px rounded + .TopRight.Shape = tbNotched +End With +``` + +* TOC +{:toc} + +## Properties + +### BottomLeft +{: .no_toc } + +The [**Corner**](#corner-class) sub-object that controls the bottom-left corner. + +### BottomRight +{: .no_toc } + +The [**Corner**](#corner-class) sub-object that controls the bottom-right corner. + +### TopLeft +{: .no_toc } + +The [**Corner**](#corner-class) sub-object that controls the top-left corner. + +### TopRight +{: .no_toc } + +The [**Corner**](#corner-class) sub-object that controls the top-right corner. + +## Methods + +### SetAll +{: .no_toc } + +Sets all four corners to the same shape and radius in a single call. Equivalent to assigning the same values to each of [**TopLeft**](#topleft), [**TopRight**](#topright), [**BottomLeft**](#bottomleft), and [**BottomRight**](#bottomright). + +Syntax: *object*.**SetAll** *Shape*, *Radius* + +*Shape* +: *required* A member of [**CornerShape**](../Enumerations/CornerShape). + +*Radius* +: *required* A [**PixelCount**](../Enumerations/PixelCount) giving the curve / notch / cut-out radius. + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the four corner sub-objects changes — either through a direct property set on the **Corners** object or through a propagated **OnChanged** from one of the **Corner** sub-objects. + +## Corner class + +A single corner of a [**Corners**](#) object. Has a [**Shape**](#shape) (curve, notch, or cut-out) and a [**Radius**](#radius) (in pixels). + +### Radius +{: .no_toc } + +The corner's radius in pixels. The interpretation depends on [**Shape**](#shape): for **tbCurve** it is the radius of the quarter-circle, for **tbNotched** the cut depth, and for **tbCutOut** the depth of the carved-out region. [**PixelCount**](../Enumerations/PixelCount). Default: 0 (a sharp 90° corner regardless of **Shape**). + +### Shape +{: .no_toc } + +How the corner is drawn. A member of [**CornerShape**](../Enumerations/CornerShape): **tbCurve** (default), **tbNotched**, or **tbCutOut**. + +### OnChanged +{: .no_toc } + +Raised when either [**Shape**](#shape) or [**Radius**](#radius) is assigned. The parent [**Corners**](#) listens for this event and re-raises its own. diff --git a/docs/Reference/CustomControls/Styles/Fill.md b/docs/Reference/CustomControls/Styles/Fill.md new file mode 100644 index 00000000..d3502673 --- /dev/null +++ b/docs/Reference/CustomControls/Styles/Fill.md @@ -0,0 +1,173 @@ +--- +title: Fill +parent: Styles +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/Fill +has_toc: false +--- + +# Fill class +{: .no_toc } + +The colour or gradient that paints a region — background of a control, body of a border, fill of a grid line, foreground of text. A **Fill** has two parts: a [**Pattern**](#pattern) that picks the gradient direction (or `tbPatternNone` for transparent), and a [**ColorPoints**](#colorpoints) collection of one or more colour stops that supply the actual colours. + +A single solid colour is just a one-stop fill: call [**ColorPoints.SetSolidColor**](#setsolidcolor) with a `Long` colour, or [**SetSimplePattern**](#setsimplepattern) on the parent **Fill** for a two-colour gradient. + +```tb +btnGo.NormalState.BackgroundFill.ColorPoints.SetSolidColor vbBlue +btnGo.HoverState.BackgroundFill.SetSimplePattern vbBlue, vbWhite, _ + Pattern:=tbGradientNorthToSouth +``` + +* TOC +{:toc} + +## Properties + +### ColorPoints +{: .no_toc } + +The [**FillColorPoints**](#fillcolorpoints-class) collection holding the gradient stops. Always present and pre-allocated; assigning new stops is done by calling methods on this object rather than replacing the collection. + +### Pattern +{: .no_toc } + +How the colours in [**ColorPoints**](#colorpoints) are mapped across the region. A member of [**FillPattern**](../Enumerations/FillPattern). Default: **tbGradientNorthToSouth**. Use **tbPatternNone** to make the **Fill** transparent. + +## Methods + +### SetSimplePattern +{: .no_toc } + +Replaces the colour stops with a two-stop gradient between two solid colours, optionally adjusting the [**Granularity**](#granularity) and [**Pattern**](#pattern) at the same time. The colours are given as ordinary `Long` values (the `vb…` colour constants or a hex literal); the opaque alpha mask is OR-ed in automatically. + +Syntax: *object*.**SetSimplePattern** *Value1RGB*, *Value2RGB* [, *Granularity* [, *Pattern* ] ] + +*Value1RGB* +: *required* A **Long** RGB colour for the first gradient stop (position 0). + +*Value2RGB* +: *required* A **Long** RGB colour for the second gradient stop (position 100). + +*Granularity* +: *optional* The colour-table size assigned to [**Granularity**](#granularity). Default: 100. + +*Pattern* +: *optional* A member of [**FillPattern**](../Enumerations/FillPattern). Default: **tbGradientNorthToSouth**. + +### SetSimplePatternRGBA +{: .no_toc } + +Same as [**SetSimplePattern**](#setsimplepattern) but accepts raw 32-bit [**ColorRGBA**](../Enumerations/ColorRGBA) values with their own alpha channels rather than three-byte RGB colours. + +Syntax: *object*.**SetSimplePatternRGBA** *Value1RGBA*, *Value2RGBA* [, *Granularity* [, *Pattern* ] ] + +*Value1RGBA* +: *required* A [**ColorRGBA**](../Enumerations/ColorRGBA) (ABGR) value for the first gradient stop. + +*Value2RGBA* +: *required* A [**ColorRGBA**](../Enumerations/ColorRGBA) (ABGR) value for the second gradient stop. + +*Granularity* +: *optional* The colour-table size assigned to [**Granularity**](#granularity). Default: 100. + +*Pattern* +: *optional* A member of [**FillPattern**](../Enumerations/FillPattern). Default: **tbGradientNorthToSouth**. + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever [**Pattern**](#pattern) is assigned or the [**ColorPoints**](#colorpoints) collection raises its own **OnChanged**. + +## FillColorPoints class + +The collection of [**FillColorPoint**](#fillcolorpoint-class) stops that drive a [**Fill**](#)'s colour gradient. Reached as [**Fill.ColorPoints**](#colorpoints). Internally an array of **FillColorPoint** plus a [**Granularity**](#granularity) integer. + +### Granularity +{: .no_toc } + +The size of the generated colour table that interpolates the stops. Higher values give smoother gradients; a value of 2 produces a hard transition between just two colours regardless of how many stops the collection holds. **Long**. Default: 100. + +### Values +{: .no_toc } + +The array of [**FillColorPoint**](#fillcolorpoint-class) gradient stops. Read-write, but in practice you populate it through the [**SetSolidColor**](#setsolidcolor), [**SetSolidColorRGBA**](#setsolidcolorrgba), [**SetColorPoints**](#setcolorpoints), or [**SetColorPointsArray**](#setcolorpointsarray) methods rather than assigning the array directly. + +### SetSolidColor +{: .no_toc } + +Replaces the stop array with a single fully-opaque stop. Takes a three-byte `Long` colour and OR-s in the opaque alpha mask. + +Syntax: *object*.**SetSolidColor** *ValueRGB* + +*ValueRGB* +: *required* A **Long** RGB colour. + +### SetSolidColorRGBA +{: .no_toc } + +Replaces the stop array with a single stop whose alpha is taken from the supplied value rather than forced opaque. + +Syntax: *object*.**SetSolidColorRGBA** *ValueRGBA* + +*ValueRGBA* +: *required* A [**ColorRGBA**](../Enumerations/ColorRGBA) (ABGR) value. + +### SetColorPoints +{: .no_toc } + +Replaces the stop array with the supplied [**FillColorPoint**](#fillcolorpoint-class) values, in order. + +Syntax: *object*.**SetColorPoints** *ColorPoint1* [, *ColorPoint2*, … ] + +*ColorPoint1*, *ColorPoint2*, … +: *required* One or more [**FillColorPoint**](#fillcolorpoint-class) objects, passed as **Variant**s through a `ParamArray`. + +### SetColorPointsArray +{: .no_toc } + +Replaces the stop array with the contents of an existing array of [**FillColorPoint**](#fillcolorpoint-class). + +Syntax: *object*.**SetColorPointsArray** *ColorPoints* ( ) + +*ColorPoints* +: *required* An array of [**FillColorPoint**](#fillcolorpoint-class). Uninitialised or empty arrays leave the collection unchanged. + +### OnChanged +{: .no_toc } + +Raised when the array of stops is reassigned or when any single stop raises its own **OnChanged**, or when [**Granularity**](#granularity) is assigned. The parent [**Fill**](#) listens for this event and re-raises its own. + +## FillColorPoint class + +A single gradient stop — a colour together with the position (0–100 %) at which the colour applies along the gradient. Elements of the [**FillColorPoints.Values**](#values) array. + +### Color +{: .no_toc } + +The stop's colour as a 32-bit ABGR value. [**ColorRGBA**](../Enumerations/ColorRGBA). + +### PositionPercent +{: .no_toc } + +The stop's position along the gradient, as a percentage from 0 to 100. **Double**. A two-stop gradient typically has stops at 0 and 100; intermediate stops at 25 / 50 / 75 produce smooth multi-colour transitions. + +### New +{: .no_toc } + +Constructs a [**FillColorPoint**](#fillcolorpoint-class). The parameterless overload sets neither field; the two-argument overload sets both. + +Syntax: **New FillColorPoint** [ ( *ColorRGBA*, *PositionPercent* ) ] + +*ColorRGBA* +: *optional* A [**ColorRGBA**](../Enumerations/ColorRGBA) value to assign to [**Color**](#color). + +*PositionPercent* +: *optional* A **Double** to assign to [**PositionPercent**](#positionpercent). + +### OnChanged +{: .no_toc } + +Raised when either [**Color**](#color) or [**PositionPercent**](#positionpercent) is assigned. The parent [**FillColorPoints**](#fillcolorpoints-class) listens for this event. diff --git a/docs/Reference/CustomControls/Styles/Line.md b/docs/Reference/CustomControls/Styles/Line.md new file mode 100644 index 00000000..c8016300 --- /dev/null +++ b/docs/Reference/CustomControls/Styles/Line.md @@ -0,0 +1,38 @@ +--- +title: Line +parent: Styles +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/Line +has_toc: false +--- + +# Line class +{: .no_toc } + +A single stroke used to draw a grid line, divider, or resizer bar — simpler than a full [**Border**](Borders#border-class) (no blend-with-background flag, no surrounding **Elements** array). Reached as [**WaynesGrid.VerticalLineOptions**](../WaynesGrid/#verticallineoptions), [**HorizontalLineOptions**](../WaynesGrid/#horizontallineoptions), and [**ResizerBar**](../WaynesGrid/#resizerbar). + +```tb +With WaynesGrid1.VerticalLineOptions + .StrokeSize = 1 + .Fill.ColorPoints.SetSolidColor &HD0D0D0 ' pale grey +End With +``` + +## Properties + +### Fill +{: .no_toc } + +The [**Fill**](Fill) that supplies the colour or gradient used to draw the line. + +### StrokeSize +{: .no_toc } + +The stroke thickness in pixels. [**PixelCount**](../Enumerations/PixelCount). Default: 0 (the line is not drawn until you assign a non-zero size). + +## Events + +### OnChanged +{: .no_toc } + +Raised when [**StrokeSize**](#strokesize) or [**Fill**](#fill) is assigned, or when the contained [**Fill**](#fill) raises its own **OnChanged**. diff --git a/docs/Reference/CustomControls/Styles/Padding.md b/docs/Reference/CustomControls/Styles/Padding.md new file mode 100644 index 00000000..a4d89f92 --- /dev/null +++ b/docs/Reference/CustomControls/Styles/Padding.md @@ -0,0 +1,48 @@ +--- +title: Padding +parent: Styles +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/Padding +has_toc: false +--- + +# Padding class +{: .no_toc } + +Per-side padding, in pixels, applied around the text inside a [**TextRendering**](TextRendering). Reached as [**TextRendering.Padding**](TextRendering#padding). The padded region is what the text [**Alignment**](TextRendering#alignment) is applied to — adding 5 pixels of left padding moves left-aligned text 5 pixels to the right, and shrinks the available area by 5 pixels at the left edge. + +```tb +With txtNotes.NormalState.TextRendering.Padding + .Left = 5 + .Right = 5 +End With +``` + +## Properties + +### Bottom +{: .no_toc } + +Padding inserted at the bottom edge, in pixels. [**PixelCount**](../Enumerations/PixelCount). Default: 0. + +### Left +{: .no_toc } + +Padding inserted at the left edge, in pixels. [**PixelCount**](../Enumerations/PixelCount). Default: 0. + +### Right +{: .no_toc } + +Padding inserted at the right edge, in pixels. [**PixelCount**](../Enumerations/PixelCount). Default: 0. + +### Top +{: .no_toc } + +Padding inserted at the top edge, in pixels. [**PixelCount**](../Enumerations/PixelCount). Default: 0. + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the four padding values is assigned. The containing [**TextRendering**](TextRendering) re-raises its own **OnChanged** in response, which in turn drives a repaint on the hosting control. diff --git a/docs/Reference/CustomControls/Styles/TextRendering.md b/docs/Reference/CustomControls/Styles/TextRendering.md new file mode 100644 index 00000000..e7b19813 --- /dev/null +++ b/docs/Reference/CustomControls/Styles/TextRendering.md @@ -0,0 +1,99 @@ +--- +title: TextRendering +parent: Styles +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/TextRendering +has_toc: false +--- + +# TextRendering class +{: .no_toc } + +Aggregates everything needed to draw a piece of text inside a control: the font, the padding, the fill that supplies the text colour, an optional array of outlines, the alignment within the available area, and the overflow behaviour. Reached as `.TextRendering`, [**WaynesLabel.TextRendering**](../WaynesLabel#textrendering), and [**CellRenderingOptions.TextRendering**](../WaynesGrid/CellRenderingOptions#textrendering). + +A newly-constructed **TextRendering** pre-sets its [**Fill**](#fill) to solid black so that text is immediately visible. + +```tb +With lblTitle.TextRendering + .Font.Size = 18 + .Font.Weight = tbBold + .Alignment = tbAlignMiddleCenter + .Fill.ColorPoints.SetSolidColor vbWhite +End With +``` + +* TOC +{:toc} + +## Properties + +### Alignment +{: .no_toc } + +How the text is positioned horizontally and vertically within the available area (after [**Padding**](#padding) is applied). A member of [**TextAlignment**](../Enumerations/TextAlignment). Default: **tbAlignMiddleCenter**. + +### Fill +{: .no_toc } + +The [**Fill**](Fill) that supplies the text colour or gradient. Pre-set to a solid black fill on construction. + +### Font +{: .no_toc } + +The [**FontStyle**](#fontstyle-class) sub-object that gives the font size, weight, italic / underline / strikeout flags. + +### OverflowMode +{: .no_toc } + +How text longer than the available width is truncated. A member of [**TextOverflowMode**](../Enumerations/TextOverflowMode). Default: **tbAppendEllipsis**. + +### Outlines +{: .no_toc } + +An array of [**Border**](Borders#border-class) elements describing one or more outlines that are stroked around the rendered glyphs. Read-write; an uninitialised array means no outline. + +### Padding +{: .no_toc } + +The [**Padding**](Padding) sub-object holding per-side padding inserted around the text inside its bounding rectangle. The [**Alignment**](#alignment) is applied to the padded region. + +## Events + +### OnChanged +{: .no_toc } + +Raised when [**Alignment**](#alignment) or [**OverflowMode**](#overflowmode) is assigned, when [**Outlines**](#outlines) is replaced or any of its elements raises **OnChanged**, or when [**Font**](#font), [**Padding**](#padding), or [**Fill**](#fill) raise their own **OnChanged**. + +## FontStyle class + +The font metrics that drive how [**TextRendering**](#) lays out text. Reached as [**TextRendering.Font**](#font). + +### Italic +{: .no_toc } + +When **True**, glyphs are rendered with italic styling. **Boolean**. Default: **False**. + +### Size +{: .no_toc } + +The font size in typographic points. [**PointSize**](../Enumerations/PointSize). Default: 12. + +### Strikeout +{: .no_toc } + +When **True**, a horizontal line is drawn through the middle of each glyph. **Boolean**. Default: **False**. + +### Underline +{: .no_toc } + +When **True**, an underline is drawn beneath each glyph. **Boolean**. Default: **False**. + +### Weight +{: .no_toc } + +The font weight on the OpenType `wght` scale. A member of [**FontWeight**](../Enumerations/FontWeight). Default: **tbNormal**. + +### OnChanged +{: .no_toc } + +Raised when any of the five font-style fields is assigned. The parent [**TextRendering**](#) listens for this event and re-raises its own. diff --git a/docs/Reference/CustomControls/Styles/index.md b/docs/Reference/CustomControls/Styles/index.md new file mode 100644 index 00000000..b313f856 --- /dev/null +++ b/docs/Reference/CustomControls/Styles/index.md @@ -0,0 +1,24 @@ +--- +title: Styles +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/Styles/ +has_toc: false +--- + +# Styles + +The shared appearance helper classes used by the [**CustomControls**](..) package's concrete `Waynes…` controls. Each is a small container of related visual settings — a [**Fill**](Fill) is a colour or gradient, a [**Borders**](Borders) is an array of border strokes, a [**Corners**](Corners) is the shape and radius of each corner, and so on. Controls compose them through `Public WithEvents …` properties: a [**WaynesButton**](../WaynesButton/) holds four [**WaynesButtonState**](../WaynesButton/WaynesButtonState) sub-objects (Normal / Hover / Focused / Pressed), each of which carries its own [**BackgroundFill**](../WaynesButton/WaynesButtonState#backgroundfill), [**Borders**](../WaynesButton/WaynesButtonState#borders), [**Corners**](../WaynesButton/WaynesButtonState#corners), and [**TextRendering**](../WaynesButton/WaynesButtonState#textrendering). + +Every style object raises an **OnChanged** event whenever any of its public fields is assigned. The hosting control listens for that event on each of its sub-objects and asks the framework to repaint, so style changes made at runtime are reflected immediately. + +| Class | Role | +|-------|------| +| [Anchors](Anchors) | which sides of a control are pinned to the container when it resizes | +| [Borders](Borders) | an array of border strokes drawn around a region; carries the per-stroke `Border` sub-object | +| [Corners](Corners) | the four corner shapes / radii of a region; carries the per-corner `Corner` sub-object | +| [Fill](Fill) | the colour or gradient that paints a region; carries the `FillColorPoint` and `FillColorPoints` sub-objects that hold the gradient stops | +| [Line](Line) | a single grid- or resizer-line stroke; a thinner shape than a full border | +| [Padding](Padding) | per-side padding around text inside a [**TextRendering**](TextRendering) | +| [TextRendering](TextRendering) | font, padding, fill, outlines, alignment, and overflow for text; carries the `FontStyle` sub-object that holds the font metrics | + +The style classes are declared `Private Class` in the **CustomControlsPackage** source — they cannot be created with `New` from outside the package, and a variable cannot be typed as e.g. `Dim x As Fill` from a referencing project. Application code reaches every style object exclusively through the property chain that hangs off a concrete control. diff --git a/docs/Reference/CustomControls/WaynesButton/WaynesButtonState.md b/docs/Reference/CustomControls/WaynesButton/WaynesButtonState.md new file mode 100644 index 00000000..c85d17f4 --- /dev/null +++ b/docs/Reference/CustomControls/WaynesButton/WaynesButtonState.md @@ -0,0 +1,67 @@ +--- +title: WaynesButtonState +parent: WaynesButton +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesButton/WaynesButtonState +has_toc: false +--- + +# WaynesButtonState class +{: .no_toc } + +A bundle of the four style objects that describe a single visual state of a [**WaynesButton**](.) — its corners, background fill, borders, and text rendering. Each button carries four parallel instances reachable as [**NormalState**](.#normalstate), [**HoverState**](.#hoverstate), [**FocusedState**](.#focusedstate), and [**PressedState**](.#pressedstate); the button picks one at each repaint depending on the mouse / focus state. + +Newly-constructed **WaynesButtonState** objects pre-set their **BackgroundFill** to a solid mid-blue and all four corners to a 15-pixel curve. Override per-state to give the button a different look in each state. + +The type itself is `Private Class` — you reach instances only through the **WaynesButton.…State** properties and cannot declare a variable typed as **WaynesButtonState** from outside the package. + +```tb +With btnGo.NormalState + .BackgroundFill.ColorPoints.SetSolidColor vbBlue + .TextRendering.Fill.ColorPoints.SetSolidColor vbWhite +End With + +With btnGo.HoverState + .BackgroundFill.SetSimplePattern vbBlue, &HE0E0FF, _ + Pattern:=tbGradientNorthToSouth + .Borders.SetSimpleBorder StrokeSize:=2, ColorRGB:=vbBlue +End With +``` + +## Properties + +### BackgroundFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the button's background. + +### Borders +{: .no_toc } + +The [**Borders**](../Styles/Borders) that draws the button's border strokes. + +### Corners +{: .no_toc } + +The [**Corners**](../Styles/Corners) that controls the per-corner shape and radius. + +### TextRendering +{: .no_toc } + +The [**TextRendering**](../Styles/TextRendering) that controls how the button's [**Caption**](.#caption) is drawn. + +## Methods + +### InitializeDefaults +{: .no_toc } + +Resets the state object to the package's defaults — solid mid-blue **BackgroundFill** and 15-pixel curved corners. Called automatically the first time the parent button is initialized, if no serialized data was loaded. + +Syntax: *object*.**InitializeDefaults** + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the four contained style objects raises its own **OnChanged**. The parent [**WaynesButton**](.) listens for this and requests a repaint. diff --git a/docs/Reference/CustomControls/WaynesButton/index.md b/docs/Reference/CustomControls/WaynesButton/index.md new file mode 100644 index 00000000..2922d0d9 --- /dev/null +++ b/docs/Reference/CustomControls/WaynesButton/index.md @@ -0,0 +1,200 @@ +--- +title: WaynesButton +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesButton/ +has_toc: false +--- + +# WaynesButton class +{: .no_toc } + +An owner-drawn push-button. Renders a configurable rectangle (with optional gradient fill, borders, rounded / notched / cut-out corners) and a centred [**Caption**](#caption), in one of four visual states — normal, hovered, focused, or pressed — driven by four parallel [**WaynesButtonState**](WaynesButtonState) sub-objects. + +The button raises a [**Click**](#click) event when clicked, plus the standard set of mouse, focus, and keyboard events. By default the four state objects are pre-set with a solid mid-blue ([**WAYNESCOLOR_BLUE**](#) — `&HAC7220`) background and 15-pixel curved corners. + +```tb +Private Sub Form_Load() + btnGo.Caption = "Continue" + btnGo.NormalState.BackgroundFill.ColorPoints.SetSolidColor vbBlue + btnGo.HoverState.BackgroundFill.SetSimplePattern vbBlue, vbWhite + btnGo.NormalState.Corners.SetAll tbCurve, 12 +End Sub + +Private Sub btnGo_Click() + MsgBox "Hello" +End Sub +``` + +* TOC +{:toc} + +## Visual states + +The button paints in one of four states, chosen at each repaint: + +| State | When | +|------------------------------------|---------------------------------------------------------------------------------| +| [**PressedState**](#pressedstate) | The mouse is held down inside the button. | +| [**HoverState**](#hoverstate) | The mouse is held down outside the button, but began inside; or the mouse is hovering without being pressed. | +| [**FocusedState**](#focusedstate) | The control has the keyboard focus and the mouse is not hovering or pressing. | +| [**NormalState**](#normalstate) | None of the above. | + +Each state is a [**WaynesButtonState**](WaynesButtonState) — a small bundle of [**Corners**](../Styles/Corners), [**BackgroundFill**](../Styles/Fill), [**Borders**](../Styles/Borders), and [**TextRendering**](../Styles/TextRendering). + +## Properties + +### Anchors +{: .no_toc } + +Which sides of the control are pinned to its container during resize. [**Anchors**](../Styles/Anchors). Inherited. + +### Caption +{: .no_toc } + +The text shown centred on the button. **String**. Default: `"Button"`. + +Syntax: *object*.**Caption** [ = *string* ] + +### Dock +{: .no_toc } + +How the control is docked inside its container. A member of [**DockMode**](../Enumerations/DockMode). Inherited. + +### FocusedState +{: .no_toc } + +The [**WaynesButtonState**](WaynesButtonState) used when the control has the keyboard focus but is not being hovered or pressed. + +### Height +{: .no_toc } + +The control's height in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### HoverState +{: .no_toc } + +The [**WaynesButtonState**](WaynesButtonState) used when the mouse is hovering over the button without being pressed (or when the mouse has been pressed and dragged off the button). + +### Left +{: .no_toc } + +The horizontal offset of the control's left edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Name +{: .no_toc } + +The unique design-time name of the control on its parent form. **String**. Inherited. + +### NormalState +{: .no_toc } + +The [**WaynesButtonState**](WaynesButtonState) used when the button is at rest — not hovered, not focused, not pressed. + +### PressedState +{: .no_toc } + +The [**WaynesButtonState**](WaynesButtonState) used when the mouse is held down on the button. + +### TabIndex +{: .no_toc } + +The position of the control in the form's TAB-key navigation order. **Long**. Inherited. + +### TabStop +{: .no_toc } + +Whether the user can reach the control by pressing **TAB**. **Boolean**. Inherited. Default: **True**. + +### Top +{: .no_toc } + +The vertical offset of the control's top edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Visible +{: .no_toc } + +Whether the control is currently displayed. **Boolean**. Inherited. Default: **True**. + +### Width +{: .no_toc } + +The control's width in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +## Events + +### Click +{: .no_toc } + +Raised when the user clicks the button (mouse down + mouse up inside the control). + +Syntax: *object*\_**Click**( ) + +### GotFocus +{: .no_toc } + +Raised when the control receives the keyboard focus. + +Syntax: *object*\_**GotFocus**( ) + +### KeyDown +{: .no_toc } + +Raised when the user presses a key while the control has focus. + +Syntax: *object*\_**KeyDown**( *KeyCode* **As Integer**, *Shift* **As Integer** ) + +### KeyPress +{: .no_toc } + +Raised when the user types a character key while the control has focus. + +Syntax: *object*\_**KeyPress**( *KeyCode* **As Integer** ) + +### KeyUp +{: .no_toc } + +Raised when the user releases a key while the control has focus. + +Syntax: *object*\_**KeyUp**( *KeyCode* **As Integer**, *Shift* **As Integer** ) + +### LostFocus +{: .no_toc } + +Raised when the control loses the keyboard focus. + +Syntax: *object*\_**LostFocus**( ) + +### MouseDown +{: .no_toc } + +Raised when the user presses a mouse button over the control. + +Syntax: *object*\_**MouseDown**( *Button* **As Integer**, *Shift* **As Integer**, *X* **As Single**, *Y* **As Single** ) + +### MouseEnter +{: .no_toc } + +Raised when the cursor first enters the control. + +Syntax: *object*\_**MouseEnter**( ) + +### MouseLeave +{: .no_toc } + +Raised when the cursor leaves the control. + +Syntax: *object*\_**MouseLeave**( ) + +### MouseMove +{: .no_toc } + +Raised when the cursor moves over the control. + +Syntax: *object*\_**MouseMove**( *Button* **As Integer**, *Shift* **As Integer**, *X* **As Single**, *Y* **As Single** ) + +### MouseUp +{: .no_toc } + +Raised when the user releases a mouse button over the control. + +Syntax: *object*\_**MouseUp**( *Button* **As Integer**, *Shift* **As Integer**, *X* **As Single**, *Y* **As Single** ) diff --git a/docs/Reference/CustomControls/WaynesForm/WindowsFormOptions.md b/docs/Reference/CustomControls/WaynesForm/WindowsFormOptions.md new file mode 100644 index 00000000..0a0d4b4a --- /dev/null +++ b/docs/Reference/CustomControls/WaynesForm/WindowsFormOptions.md @@ -0,0 +1,71 @@ +--- +title: WindowsFormOptions +parent: WaynesForm +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesForm/WindowsFormOptions +has_toc: false +--- + +# WindowsFormOptions class +{: .no_toc } + +The Win32-frame settings of a [**WaynesForm**](.) — border style, initial window state, startup position, taskbar visibility, and the title-bar buttons. Surfaces as [**WaynesForm.WindowsOptions**](.#windowsoptions); a single instance per form, created automatically. + +Most of the fields take effect *once*, when the form is first shown — changing [**StartUpPosition**](#startupposition) or [**WindowState**](#windowstate) on a form that is already visible has no effect. The exception is the title-bar buttons; whether they have a visible effect depends on whether [**BorderStyle**](#borderstyle) is one of the styles that include those buttons in the first place. + +The type itself is `Private Class` — you reach the instance only through the form's **WindowsOptions** property and cannot declare a variable typed as **WindowsFormOptions** from outside the package. + +```tb +Private Sub Form_Load() + With Me.WindowsOptions + .StartUpPosition = tbStartUpCenterScreen + .BorderStyle = tbFixedDialog + .MaximizeButton = False + .ShowInTaskbar = False + End With +End Sub +``` + +## Properties + +### BorderStyle +{: .no_toc } + +The Win32 frame style — thin / thick border, resizable / fixed, normal / tool-window title bar. A member of [**BorderStyle**](../Enumerations/BorderStyle). Default: **tbFixedSizable**. + +### ControlBox +{: .no_toc } + +Whether the form's title bar shows the system control box (the icon at the far left of the bar, with the **Move** / **Close** menu). **Boolean**. Default: **True**. + +### MaximizeButton +{: .no_toc } + +Whether the title bar shows a **Maximize** button. **Boolean**. Default: **True**. Effective only when [**BorderStyle**](#borderstyle) is one of the resizable styles. + +### MinimizeButton +{: .no_toc } + +Whether the title bar shows a **Minimize** button. **Boolean**. Default: **True**. Effective only when [**BorderStyle**](#borderstyle) is one of the styles that supports minimizing. + +### ShowInTaskbar +{: .no_toc } + +Whether the form's window appears in the Windows taskbar. **Boolean**. Default: **True**. + +### StartUpPosition +{: .no_toc } + +How the form's window is positioned when first shown. A member of [**StartupPosition**](../Enumerations/StartupPosition). Default: **tbStartUpWindowsDefault**. + +### WindowState +{: .no_toc } + +The window state of the form when first shown — normal, minimized, or maximized. A member of [**WindowState**](../Enumerations/WindowState). Default: **tbNormal**. + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the seven fields is assigned. The parent [**WaynesForm**](.) listens for this event and (where applicable to a not-yet-shown form) re-applies the frame settings. diff --git a/docs/Reference/CustomControls/WaynesForm/index.md b/docs/Reference/CustomControls/WaynesForm/index.md new file mode 100644 index 00000000..996baf53 --- /dev/null +++ b/docs/Reference/CustomControls/WaynesForm/index.md @@ -0,0 +1,123 @@ +--- +title: WaynesForm +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesForm/ +has_toc: false +--- + +# WaynesForm class +{: .no_toc } + +The top-level form class that hosts the package's custom controls. A **WaynesForm** is the equivalent of a `Form` from the [**VB**](../../VB/) package, but instead of being a Win32 native window with controls overlaid on top, it is an owner-drawn surface that paints itself and its child controls through the [**CustomControls**](..) framework. + +Within the current release of the package every form created with the designer is hard-coded to use **WaynesForm** as its root class; other base form classes are planned but not yet supported. + +A form has a [**Caption**](#caption) (shown in the Win32 title bar), a [**BackgroundFill**](#backgroundfill) (painted across its entire client area), and a [**WindowsOptions**](#windowsoptions) sub-object that drives the surrounding Win32 frame — border style, window state, taskbar visibility, minimize / maximize buttons, and so on. Showing the form is done by calling [**Show**](#show); closing it by [**Close**](#close). + +```tb +Private Sub Form_Load() + Me.Caption = "Welcome" + Me.BackgroundFill.ColorPoints.SetSolidColor vbWhite + With Me.WindowsOptions + .StartUpPosition = tbStartUpCenterScreen + .BorderStyle = tbFixedDialog + .MaximizeButton = False + End With +End Sub +``` + +* TOC +{:toc} + +## Modal display + +The current release supports modal display only. Calling [**Show**](#show) with **vbModeless** writes a debug-print message and otherwise does nothing — call **Show vbModal** to display the form. + +## Properties + +### BackgroundFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the form's entire client area. Defaults to a solid light-grey ([**WAYNESCOLOR_LIGHTGREY**](#) — `&HD0D0D0`). + +### Caption +{: .no_toc } + +The text shown in the Win32 title bar of the form. **String**. + +Syntax: *object*.**Caption** [ = *string* ] + +### Controls +{: .no_toc } + +The [**CustomControlsCollection**](../Framework/CustomControlsCollection) of every control hosted on the form. Inherited from the form base. Read-only — iterate or look up by index / name to reach individual controls. + +### FormDesignerId +{: .no_toc } + +A **String** holding the unique GUID that associates this form instance with its designer-saved metadata. Inherited from the form base. Application code does not normally read or write this — the framework populates it. + +### Height +{: .no_toc } + +The form's height in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Left +{: .no_toc } + +The form's left position in pixels — honoured only when [**WindowsOptions.StartUpPosition**](WindowsFormOptions#startupposition) is **tbStartUpManual**. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Name +{: .no_toc } + +The form's name within the project. **String**. Inherited. + +### Top +{: .no_toc } + +The form's top position in pixels — honoured only when [**WindowsOptions.StartUpPosition**](WindowsFormOptions#startupposition) is **tbStartUpManual**. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Width +{: .no_toc } + +The form's width in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### WindowsOptions +{: .no_toc } + +The [**WindowsFormOptions**](WindowsFormOptions) that drives the Win32 frame — border style, window state, taskbar visibility, minimize / maximize buttons, system menu. + +## Methods + +### Close +{: .no_toc } + +Closes the form's underlying window. + +Syntax: *object*.**Close** + +### Show +{: .no_toc } + +Shows the form. The current release supports modal display only — calling with **vbModeless** writes a debug message and otherwise does nothing. + +Syntax: *object*.**Show** [ *Modal* ] + +*Modal* +: *optional* A member of [**FormShowConstants**](../../VBRUN/Constants/FormShowConstants). Pass **vbModal** for the supported modal display; **vbModeless** is currently a no-op. + +### StartupShow +{: .no_toc } + +Shows the form unconditionally — used by the framework to display the project's startup form. Application code can call it but [**Show**](#show) is the normal entry point. + +Syntax: *object*.**StartupShow** + +## Events + +### Click +{: .no_toc } + +Raised when the user clicks on the form's background — i.e. on a region not occupied by a hosted control. + +Syntax: *object*\_**Click**( ) diff --git a/docs/Reference/CustomControls/WaynesFrame.md b/docs/Reference/CustomControls/WaynesFrame.md new file mode 100644 index 00000000..14fd71fd --- /dev/null +++ b/docs/Reference/CustomControls/WaynesFrame.md @@ -0,0 +1,66 @@ +--- +title: WaynesFrame +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesFrame +has_toc: false +--- + +# WaynesFrame class +{: .no_toc } + +A rectangular container control whose entire area is painted with a configurable [**BackgroundFill**](#backgroundfill). Used to group other controls on a [**WaynesForm**](WaynesForm/), with the same layout / sizing surface as any other custom control. + +The default fill is a solid mid-grey ([**WAYNESCOLOR_GREY**](#) — `&H808080`); change it by reaching into the **Fill.ColorPoints** collection. + +```tb +Private Sub Form_Load() + Frame1.BackgroundFill.ColorPoints.SetSolidColor vbWhite +End Sub +``` + +## Properties + +### Anchors +{: .no_toc } + +Which sides of the control are pinned to its container during resize. [**Anchors**](Styles/Anchors). Inherited. + +### BackgroundFill +{: .no_toc } + +The [**Fill**](Styles/Fill) that paints the frame's entire client area. + +### Dock +{: .no_toc } + +How the control is docked inside its container. A member of [**DockMode**](Enumerations/DockMode). Inherited. Default: **tbDockNone**. + +### Height +{: .no_toc } + +The control's height in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Left +{: .no_toc } + +The horizontal offset of the control's left edge from its container, in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Name +{: .no_toc } + +The unique design-time name of the control on its parent form. **String**. Inherited. + +### Top +{: .no_toc } + +The vertical offset of the control's top edge from its container, in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Visible +{: .no_toc } + +Whether the control is currently displayed. **Boolean**. Inherited. Default: **True**. + +### Width +{: .no_toc } + +The control's width in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. diff --git a/docs/Reference/CustomControls/WaynesGrid/CellRenderingOptions.md b/docs/Reference/CustomControls/WaynesGrid/CellRenderingOptions.md new file mode 100644 index 00000000..31ada6b8 --- /dev/null +++ b/docs/Reference/CustomControls/WaynesGrid/CellRenderingOptions.md @@ -0,0 +1,62 @@ +--- +title: CellRenderingOptions +parent: WaynesGrid +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesGrid/CellRenderingOptions +has_toc: false +--- + +# CellRenderingOptions class +{: .no_toc } + +A bundle of the style objects that describe one *category* of cell in a [**WaynesGrid**](.). Each grid carries six parallel instances — one for column headers, one for row headers, one for normal cells, one for the hovered cell, one for the selected cell, and one for cells inside a full-row or full-column multi-selection — and the grid picks the appropriate instance per cell at paint time. + +```tb +With Grid1.SelectedCellOptions + .Fill.ColorPoints.SetSolidColor &HFFEEAA ' pale blue + .Borders.SetSimpleBorder StrokeSize:=2, ColorRGB:=vbBlue +End With +``` + +## Properties + +### Borders +{: .no_toc } + +The [**Borders**](../Styles/Borders) drawn around the cell. + +### Corners +{: .no_toc } + +The [**Corners**](../Styles/Corners) that controls the per-corner shape and radius of the cell. Most cells use the default sharp 90° corners; rounded corners only really make sense on a single highlighted cell rather than on every cell in a column. + +### Cursor +{: .no_toc } + +The mouse cursor shown when the pointer is over this category of cell. A member of [**MousePointerConstants**](../../VBRUN/Constants/MousePointerConstants). Defaults to **vbDefault**; the grid sets **vbHand** on the column-header and row-header instances internally to indicate that those rows / columns are clickable for multi-selection. + +### Fill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the cell background. Newly-constructed **CellRenderingOptions** instances default to a solid mid-grey background ([**WAYNESCOLOR_GREY**](#) — `&H808080`). + +### TextRendering +{: .no_toc } + +The [**TextRendering**](../Styles/TextRendering) that controls how the cell's text (supplied by the [**GetCellText**](.#getcelltext) event) is drawn. + +## Methods + +### New +{: .no_toc } + +Constructs a [**CellRenderingOptions**](#) with the default mid-grey fill. + +Syntax: **New CellRenderingOptions** + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the contained style objects raises its own **OnChanged**, or when [**Cursor**](#cursor) is assigned. The parent [**WaynesGrid**](.) listens for this and requests a repaint. diff --git a/docs/Reference/CustomControls/WaynesGrid/Column.md b/docs/Reference/CustomControls/WaynesGrid/Column.md new file mode 100644 index 00000000..e2028d74 --- /dev/null +++ b/docs/Reference/CustomControls/WaynesGrid/Column.md @@ -0,0 +1,38 @@ +--- +title: Column +parent: WaynesGrid +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesGrid/Column +has_toc: false +--- + +# Column class +{: .no_toc } + +One column of a [**WaynesGrid**](.). Carries a [**Caption**](#caption) that is shown in the column-header row and a [**Width**](#width) that the user can drag at run time. Elements of [**WaynesGrid.Columns**](.#columns). + +```tb +ReDim Grid1.Columns(2) +Set Grid1.Columns(0) = New Column +Grid1.Columns(0).Caption = "ID" +Grid1.Columns(0).Width = 80 +``` + +## Properties + +### Caption +{: .no_toc } + +The text shown in the column-header cell. **String**. Default: `"Column"`. + +### Width +{: .no_toc } + +The column's width in pixels (unscaled by DPI). [**PixelCount**](../Enumerations/PixelCount). Default: 100. Editable by the user at run time by dragging the resizer bar on the column's right edge; assignments at run time update the grid immediately. + +## Events + +### OnChanged +{: .no_toc } + +Raised when [**Caption**](#caption) or [**Width**](#width) is assigned. The parent [**WaynesGrid**](.) listens for this and requests a repaint. diff --git a/docs/Reference/CustomControls/WaynesGrid/index.md b/docs/Reference/CustomControls/WaynesGrid/index.md new file mode 100644 index 00000000..364068ec --- /dev/null +++ b/docs/Reference/CustomControls/WaynesGrid/index.md @@ -0,0 +1,213 @@ +--- +title: WaynesGrid +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesGrid/ +has_toc: false +--- + +# WaynesGrid class +{: .no_toc } + +A tabular data display — a grid of cells with column headers and row headers, resizable columns, optional grid lines, hover and selection highlighting, vertical and horizontal scrolling via the mouse wheel, and full keyboard navigation. The number of rows is set by [**RowCount**](#rowcount); the cells themselves are filled in by handling the [**GetCellText**](#getcelltext) event, which fires once per visible cell as the grid paints. + +The grid carries an array of [**Column**](Column) objects giving each column its [**Caption**](Column#caption) and [**Width**](Column#width). Five distinct [**CellRenderingOptions**](CellRenderingOptions) sub-objects drive the appearance of column headers, row headers, normal cells, the hovered cell, the selected cell, and full-column / full-row multi-selection. + +```tb +Private Sub Form_Load() + ReDim Grid1.Columns(2) + Set Grid1.Columns(0) = New Column + Set Grid1.Columns(1) = New Column + Set Grid1.Columns(2) = New Column + Grid1.Columns(0).Caption = "ID" + Grid1.Columns(1).Caption = "Name" + Grid1.Columns(2).Caption = "Date" + Grid1.RowCount = 100 +End Sub + +Private Sub Grid1_GetCellText( _ + ByVal X As Long, ByVal Y As Long, ByRef Value As String) + + Select Case X + Case 0: Value = CStr(Y + 1) + Case 1: Value = "Row " & (Y + 1) + Case 2: Value = Format$(DateAdd("d", Y, Date), "yyyy-mm-dd") + End Select +End Sub +``` + +* TOC +{:toc} + +## Cell selection + +The grid exposes three separate selection states, each tracked through its own pair of properties: + +- A single hover-highlight cell — the cell currently under the mouse — driven by [**HoverCellOptions**](#hovercelloptions). Internal to the grid; not exposed as a property. +- A single selected cell, with coordinates in [**SelectedCellX**](#selectedcellx) and [**SelectedCellY**](#selectedcelly), drawn using [**SelectedCellOptions**](#selectedcelloptions). +- A full-row or full-column multi-selection, indicated by clicking the row header or column header. [**SelectedFullColumnX**](#selectedfullcolumnx) and [**SelectedFullRowY**](#selectedfullrowy) hold the indices; the affected cells render with [**MultiSelectCellOptions**](#multiselectcelloptions). + +A value of `-1` on any of the selection-coordinate properties means "no selection of that kind". Setting a selection programmatically and then asking the grid to repaint moves the focus to the corresponding cell as well, by way of [**CustomControlContext.ChangeFocusedElement**](../Framework/CustomControlContext#changefocusedelement). + +## Properties + +### Anchors +{: .no_toc } + +Which sides of the control are pinned to its container during resize. [**Anchors**](../Styles/Anchors). Inherited. + +### CellOptions +{: .no_toc } + +The [**CellRenderingOptions**](CellRenderingOptions) used to draw ordinary, unselected, non-hovered cells. + +### ColumnHeaderOptions +{: .no_toc } + +The [**CellRenderingOptions**](CellRenderingOptions) used to draw the column-header row (the top row). + +### Columns +{: .no_toc } + +The array of [**Column**](Column) objects describing each column. Read-write; `ReDim` to grow / shrink, and assign individual [**Column**](Column) instances into the elements. + +### Dock +{: .no_toc } + +How the control is docked inside its container. A member of [**DockMode**](../Enumerations/DockMode). Inherited. + +### HeaderRowHeight +{: .no_toc } + +The height of the column-header row, in pixels (unscaled by DPI). **Long**. Default: 60. + +### Height +{: .no_toc } + +The control's height in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### HorizontalLineOptions +{: .no_toc } + +The [**Line**](../Styles/Line) drawn between successive rows. Set its [**StrokeSize**](../Styles/Line#strokesize) to 0 to suppress the horizontal lines. + +### HoverCellOptions +{: .no_toc } + +The [**CellRenderingOptions**](CellRenderingOptions) used to draw the cell currently under the mouse cursor. + +### Left +{: .no_toc } + +The horizontal offset of the control's left edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### MultiSelectCellOptions +{: .no_toc } + +The [**CellRenderingOptions**](CellRenderingOptions) used to draw cells that belong to a full-column or full-row multi-selection. + +### Name +{: .no_toc } + +The unique design-time name of the control on its parent form. **String**. Inherited. + +### ResizerBar +{: .no_toc } + +The [**Line**](../Styles/Line) drawn over a column-edge while the user is dragging it to resize. Transparent when not hovered; rendered with the line's fill while the resize is active. + +### RowCount +{: .no_toc } + +The total number of rows in the grid. **Long**. Default: -1 (unbounded — the grid paints rows forever as the user scrolls). + +### RowHeaderOptions +{: .no_toc } + +The [**CellRenderingOptions**](CellRenderingOptions) used to draw the row-header column (the leftmost column). + +### RowHeight +{: .no_toc } + +The height of every non-header row, in pixels (unscaled by DPI). **Long**. Default: 40. + +### SelectedCellOptions +{: .no_toc } + +The [**CellRenderingOptions**](CellRenderingOptions) used to draw the single currently-selected cell at ([**SelectedCellX**](#selectedcellx), [**SelectedCellY**](#selectedcelly)). + +### SelectedCellX +{: .no_toc } + +The X (column) index of the currently-selected cell, or -1 if no cell is selected. **Long**. Default: -1. + +### SelectedCellY +{: .no_toc } + +The Y (row) index of the currently-selected cell, or -1 if no cell is selected. **Long**. Default: -1. + +### SelectedFullColumnX +{: .no_toc } + +The X (column) index of a full-column multi-selection, or -1 if no full column is selected. **Long**. Default: -1. + +### SelectedFullRowY +{: .no_toc } + +The Y (row) index of a full-row multi-selection, or -1 if no full row is selected. **Long**. Default: -1. + +### TabIndex +{: .no_toc } + +The position of the control in the form's TAB-key navigation order. **Long**. Inherited. + +### TabStop +{: .no_toc } + +Whether the user can reach the control by pressing **TAB**. **Boolean**. Inherited. Default: **True**. + +### Top +{: .no_toc } + +The vertical offset of the control's top edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### VerticalLineOptions +{: .no_toc } + +The [**Line**](../Styles/Line) drawn between successive columns. Set its [**StrokeSize**](../Styles/Line#strokesize) to 0 to suppress the vertical lines. + +### Visible +{: .no_toc } + +Whether the control is currently displayed. **Boolean**. Inherited. Default: **True**. + +### Width +{: .no_toc } + +The control's width in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +## Methods + +### Repaint +{: .no_toc } + +Asks the framework to redraw the grid. Equivalent to calling [**CustomControlContext.Repaint**](../Framework/CustomControlContext#repaint) on the control's stored context; exposed as a public method on the grid so an external observer (e.g. the form, after updating the data behind the grid) can trigger a redraw without reaching into the framework. + +Syntax: *object*.**Repaint** + +## Events + +### GetCellText +{: .no_toc } + +Raised once per visible cell as the grid paints, asking the host for the text to display. The default text is `` — replace *Value* in the handler to show real data. + +Syntax: *object*\_**GetCellText**( **ByVal** *X* **As Long**, **ByVal** *Y* **As Long**, **ByRef** *Value* **As String** ) + +*X* +: The column index of the cell being painted. + +*Y* +: The row index of the cell being painted. + +*Value* +: A pre-populated default value; assign to it to override what is displayed. diff --git a/docs/Reference/CustomControls/WaynesLabel.md b/docs/Reference/CustomControls/WaynesLabel.md new file mode 100644 index 00000000..d2bdfdec --- /dev/null +++ b/docs/Reference/CustomControls/WaynesLabel.md @@ -0,0 +1,83 @@ +--- +title: WaynesLabel +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesLabel +has_toc: false +--- + +# WaynesLabel class +{: .no_toc } + +A static text-display control. Paints a [**Caption**](#caption) string inside its rectangle using the configured [**TextRendering**](#textrendering), on top of a [**BackgroundFill**](#backgroundfill). The label has no interactive states — appearance is the same whether the mouse is hovering over it or not. + +```tb +Private Sub Form_Load() + Label1.Caption = "Hello, world" + With Label1.TextRendering + .Font.Size = 14 + .Font.Weight = tbBold + .Alignment = tbAlignMiddleCenter + .Fill.ColorPoints.SetSolidColor vbWhite + End With + Label1.BackgroundFill.ColorPoints.SetSolidColor vbBlue +End Sub +``` + +## Properties + +### Anchors +{: .no_toc } + +Which sides of the control are pinned to its container during resize. [**Anchors**](Styles/Anchors). Inherited. + +### BackgroundFill +{: .no_toc } + +The [**Fill**](Styles/Fill) that paints the label's entire client area. + +### Caption +{: .no_toc } + +The text displayed on the label. **String**. Default: `"Label"`. + +Syntax: *object*.**Caption** [ = *string* ] + +### Dock +{: .no_toc } + +How the control is docked inside its container. A member of [**DockMode**](Enumerations/DockMode). Inherited. + +### Height +{: .no_toc } + +The control's height in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Left +{: .no_toc } + +The horizontal offset of the control's left edge from its container, in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Name +{: .no_toc } + +The unique design-time name of the control on its parent form. **String**. Inherited. + +### TextRendering +{: .no_toc } + +The [**TextRendering**](Styles/TextRendering) that controls how the [**Caption**](#caption) is drawn — font, padding, fill, outlines, alignment, and overflow. + +### Top +{: .no_toc } + +The vertical offset of the control's top edge from its container, in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Visible +{: .no_toc } + +Whether the control is currently displayed. **Boolean**. Inherited. Default: **True**. + +### Width +{: .no_toc } + +The control's width in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. diff --git a/docs/Reference/CustomControls/WaynesSlider/WaynesSliderState.md b/docs/Reference/CustomControls/WaynesSlider/WaynesSliderState.md new file mode 100644 index 00000000..a0dea8ef --- /dev/null +++ b/docs/Reference/CustomControls/WaynesSlider/WaynesSliderState.md @@ -0,0 +1,76 @@ +--- +title: WaynesSliderState +parent: WaynesSlider +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesSlider/WaynesSliderState +has_toc: false +--- + +# WaynesSliderState class +{: .no_toc } + +A bundle of the style objects that describe a single visual state of a [**WaynesSlider**](.). Each slider holds three parallel instances ([**NormalState**](.#normalstate), [**HoverState**](.#hoverstate), [**FocusedState**](.#focusedstate)); the slider picks one at each repaint depending on the mouse / focus state. + +The state has two halves — the *background* (the full track behind the block) and the *block* (the draggable rectangle that indicates [**Value**](.#value)). Each half has its own [**Fill**](../Styles/Fill), [**Borders**](../Styles/Borders), and [**Corners**](../Styles/Corners). A [**TextRendering**](../Styles/TextRendering) on the state drives how the optional [**DisplayFormat**](.#displayformat) text is drawn on the block. + +[**InitializeDefaultValues**](#initializedefaultvalues) pre-sets the block to a solid mid-blue ([**WAYNESCOLOR_BLUE**](#) — `&HAC7220`) fill, a 2-pixel black background border, and a transparent block border that acts as inner padding inside the background. + +The type itself is `Public Class` but cannot be instantiated from outside the package — reach instances only through the slider's **NormalState** / **HoverState** / **FocusedState** properties. + +## Properties + +### BackgroundBorders +{: .no_toc } + +The [**Borders**](../Styles/Borders) drawn around the background track. + +### BackgroundCorners +{: .no_toc } + +The [**Corners**](../Styles/Corners) that controls the per-corner shape and radius of the background track. + +### BackgroundFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the background track. + +### BlockBorders +{: .no_toc } + +The [**Borders**](../Styles/Borders) drawn around the block. + +### BlockCorners +{: .no_toc } + +The [**Corners**](../Styles/Corners) that controls the per-corner shape and radius of the block. + +### BlockFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the block. + +### BlockWidth +{: .no_toc } + +The width of the block, in pixels. [**PixelCount**](../Enumerations/PixelCount). Default: 100. When [**Direction**](.#direction) is **Vertical**, this is the *height* of the block rather than its width; the block's other dimension takes the full available extent of the slider. + +### TextRendering +{: .no_toc } + +The [**TextRendering**](../Styles/TextRendering) that controls how the optional [**DisplayFormat**](.#displayformat) text is rendered on the block. + +## Methods + +### InitializeDefaultValues +{: .no_toc } + +Resets the state object to the package's defaults — a solid mid-blue block fill, a 2-pixel black background border, and a transparent block border. Called automatically the first time the parent slider is initialized, if no serialized data was loaded. + +Syntax: *object*.**InitializeDefaultValues** + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the contained style objects raises its own **OnChanged**, or when [**BlockWidth**](#blockwidth) is assigned. The parent [**WaynesSlider**](.) listens for this and requests a repaint. diff --git a/docs/Reference/CustomControls/WaynesSlider/index.md b/docs/Reference/CustomControls/WaynesSlider/index.md new file mode 100644 index 00000000..55f832ec --- /dev/null +++ b/docs/Reference/CustomControls/WaynesSlider/index.md @@ -0,0 +1,161 @@ +--- +title: WaynesSlider +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesSlider/ +has_toc: false +--- + +# WaynesSlider class +{: .no_toc } + +A horizontal or vertical slider control — a draggable block over a track — for editing an integer value within a range. The user can drag the block, click on the track to step the value by one page, or use the arrow keys when the control has focus; an optional auto-increment timer activates while a mouse button is held down on the track. + +The control paints three visual states ([**NormalState**](#normalstate), [**HoverState**](#hoverstate), [**FocusedState**](#focusedstate)) driven by parallel [**WaynesSliderState**](WaynesSliderState) sub-objects, each of which carries independent fill / border / corner styling for the background and for the block. The current [**Value**](#value) is optionally rendered as text on the block — as a raw integer or as a formatted percentage — depending on [**DisplayFormat**](#displayformat). + +If the control's [**Height**](#height) is greater than its [**Width**](#width) on first display, the slider defaults to [**Direction**](#direction) = **Vertical**; otherwise it defaults to **Horizontal**. + +```tb +Private Sub Form_Load() + sldVolume.MinValue = 0 + sldVolume.MaxValue = 100 + sldVolume.StepValue = 5 + sldVolume.PagingStepValue = 10 + sldVolume.DisplayFormat = SliderDisplayValueFormat.DisplayPercentage +End Sub +``` + +* TOC +{:toc} + +## SliderDirection + +The slider orientation enum, declared inside the **WaynesSlider** class. Assigned to [**Direction**](#direction). + +| Constant | Value | Description | +|----------|-------|-------------| +| **Horizontal**{: #horizontal } | 0 | Track runs left-to-right; arrow keys **Left** / **Right** step the value. | +| **Vertical**{: #vertical } | 1 | Track runs top-to-bottom; arrow keys **Up** / **Down** step the value. | + +## SliderDisplayValueFormat + +How the [**Value**](#value) is rendered on the block, declared inside the **WaynesSlider** class. Assigned to [**DisplayFormat**](#displayformat). + +| Constant | Value | Description | +|----------|-------|-------------| +| **DisplayValue**{: #displayvalue } | 0 | Show the raw integer value. | +| **DisplayPercentage**{: #displaypercentage } | 1 | Show the value as a percentage of the range — `FormatPercent((Value - MinValue) / (MaxValue - MinValue), 1)`. | +| **DisplayNone**{: #displaynone } | 2 | No text on the block. | + +## Properties + +### Anchors +{: .no_toc } + +Which sides of the control are pinned to its container during resize. [**Anchors**](../Styles/Anchors). Inherited. + +### Direction +{: .no_toc } + +Whether the slider is laid out horizontally or vertically. A member of [**SliderDirection**](#sliderdirection). Default: chosen on first display from the control's aspect ratio (vertical if **Height** > **Width**, else horizontal). + +### DisplayFormat +{: .no_toc } + +How the [**Value**](#value) is rendered as text on the block. A member of [**SliderDisplayValueFormat**](#sliderdisplayvalueformat). Default: **DisplayValue**. + +### Dock +{: .no_toc } + +How the control is docked inside its container. A member of [**DockMode**](../Enumerations/DockMode). Inherited. + +### FocusedState +{: .no_toc } + +The [**WaynesSliderState**](WaynesSliderState) used when the control has the keyboard focus and the mouse is not hovering. + +### Height +{: .no_toc } + +The control's height in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### HoverState +{: .no_toc } + +The [**WaynesSliderState**](WaynesSliderState) used when the mouse is hovering over the block or over the track. + +### Left +{: .no_toc } + +The horizontal offset of the control's left edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### MaxValue +{: .no_toc } + +The upper bound of the slider's value range. **Long**. Default: 100. + +### MinValue +{: .no_toc } + +The lower bound of the slider's value range. **Long**. Default: 0. + +### MoveInterval +{: .no_toc } + +The interval, in milliseconds, between automatic increments of [**Value**](#value) while a mouse button is held down on the track. **Long**. A value of 0 disables auto-repeat. + +### Name +{: .no_toc } + +The unique design-time name of the control on its parent form. **String**. Inherited. + +### NormalState +{: .no_toc } + +The [**WaynesSliderState**](WaynesSliderState) used when the slider is at rest — not hovered, not focused. + +### PagingStepValue +{: .no_toc } + +How far [**Value**](#value) moves when the user clicks on the track outside the block (or holds a mouse button down on the track). **Long**. Default: 1. + +### StepValue +{: .no_toc } + +The granularity of the slider — [**Value**](#value) is rounded to a multiple of **StepValue** offset from [**MinValue**](#minvalue) before each paint. **Long**. Default: 1. + +### TabIndex +{: .no_toc } + +The position of the control in the form's TAB-key navigation order. **Long**. Inherited. + +### TabStop +{: .no_toc } + +Whether the user can reach the control by pressing **TAB**. **Boolean**. Inherited. Default: **True**. + +### Top +{: .no_toc } + +The vertical offset of the control's top edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Value +{: .no_toc } + +The current position of the block within the range, as an integer. **Long**. Clamped to `[MinValue, MaxValue]` at paint time unless [**WrapAround**](#wraparound) is **True**. + +Syntax: *object*.**Value** [ = *value* ] + +### Visible +{: .no_toc } + +Whether the control is currently displayed. **Boolean**. Inherited. Default: **True**. + +### Width +{: .no_toc } + +The control's width in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### WrapAround +{: .no_toc } + +When **False** (the default), [**Value**](#value) is clamped to the range `[MinValue, MaxValue]`. When **True**, values outside the range are allowed and the block wraps around — the slider paints additional block instances on the opposite edge to give a continuous visual. **Boolean**. diff --git a/docs/Reference/CustomControls/WaynesTextBox/WaynesTextBoxState.md b/docs/Reference/CustomControls/WaynesTextBox/WaynesTextBoxState.md new file mode 100644 index 00000000..122eac7a --- /dev/null +++ b/docs/Reference/CustomControls/WaynesTextBox/WaynesTextBoxState.md @@ -0,0 +1,98 @@ +--- +title: WaynesTextBoxState +parent: WaynesTextBox +grand_parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesTextBox/WaynesTextBoxState +has_toc: false +--- + +# WaynesTextBoxState class +{: .no_toc } + +A bundle of the style objects that describe a single visual state of a [**WaynesTextBox**](.). Each textbox holds three parallel instances ([**NormalState**](.#normalstate), [**HoverState**](.#hoverstate), [**FocusedState**](.#focusedstate)); the textbox picks one at each repaint depending on the focus / hover state. + +In addition to the usual background / borders / corners / text-rendering quartet, a **WaynesTextBoxState** carries selection-highlight colours, a caret colour and width, and three decorator fills used for the *ERROR* / *WARNING* / *INFO* literal-substring decorations the textbox draws automatically. + +[**InitializeDefaultValues**](#initializedefaultvalues) and [**InitializeDefaultValues_Focused**](#initializedefaultvalues_focused) populate the state with sensible defaults — the focused variant uses a different selection background and caret colour. + +The type itself is `Public Class` but is `[COMCreatable(False)]` — reach instances only through the textbox's **NormalState** / **HoverState** / **FocusedState** properties. + +## Properties + +### BackgroundFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the textbox background. Defaults to solid white. + +### Borders +{: .no_toc } + +The [**Borders**](../Styles/Borders) drawn around the textbox. Defaults to a 1-pixel black border. + +### CaretFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the caret. Defaults to solid black in the normal state, orange in the focused state. + +### CaretWidth +{: .no_toc } + +The width of the caret, in pixels. **Long**. Default: 1. + +### Corners +{: .no_toc } + +The [**Corners**](../Styles/Corners) that controls the per-corner shape and radius. Defaults to **tbCurve** with a radius of 5. + +### DecorationERROR +{: .no_toc } + +The [**Fill**](../Styles/Fill) used to draw the inline squiggle decoration when the substring `ERROR` is detected in [**Value**](.#value). Defaults to solid red. + +### DecorationINFO +{: .no_toc } + +The [**Fill**](../Styles/Fill) used to draw the inline background-highlight decoration when the substring `INFO` is detected in [**Value**](.#value). Defaults to a light blue. + +### DecorationWARNING +{: .no_toc } + +The [**Fill**](../Styles/Fill) used to draw the inline 2-pixel straight-underline decoration when the substring `WARNING` is detected in [**Value**](.#value). Defaults to a dark blue. + +### SelectedBackgroundFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints behind selected text. Defaults to mid-grey in the normal state, blue in the focused state. + +### SelectedTextFill +{: .no_toc } + +The [**Fill**](../Styles/Fill) that paints the selected glyphs themselves. Defaults to solid white. + +### TextRendering +{: .no_toc } + +The [**TextRendering**](../Styles/TextRendering) that controls how [**Value**](.#value) is drawn. Defaults to left-aligned with 5-pixel left / right padding and **tbDisallowPartialChars** overflow. + +## Methods + +### InitializeDefaultValues +{: .no_toc } + +Populates every field with the package defaults — used by [**NormalState**](.#normalstate) and [**HoverState**](.#hoverstate). + +Syntax: *object*.**InitializeDefaultValues** + +### InitializeDefaultValues_Focused +{: .no_toc } + +Calls [**InitializeDefaultValues**](#initializedefaultvalues) first, then overrides [**SelectedBackgroundFill**](#selectedbackgroundfill) and [**CaretFill**](#caretfill) with focus-specific colours. + +Syntax: *object*.**InitializeDefaultValues_Focused** + +## Events + +### OnChanged +{: .no_toc } + +Raised whenever any of the contained style objects raises its own **OnChanged**, or when [**CaretWidth**](#caretwidth) is assigned. The parent [**WaynesTextBox**](.) listens for this and requests a repaint. diff --git a/docs/Reference/CustomControls/WaynesTextBox/index.md b/docs/Reference/CustomControls/WaynesTextBox/index.md new file mode 100644 index 00000000..789699c1 --- /dev/null +++ b/docs/Reference/CustomControls/WaynesTextBox/index.md @@ -0,0 +1,110 @@ +--- +title: WaynesTextBox +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesTextBox/ +has_toc: false +--- + +# WaynesTextBox class +{: .no_toc } + +A single-line editable text field. The user can type, select with the mouse or with shift-modified cursor keys, jump word-by-word with **Ctrl+Left** / **Ctrl+Right**, double-click to select a word, and copy / cut / paste / select-all with the standard Windows shortcuts. The control draws its own caret, selection highlight, and inline text decorators (squiggle for *ERROR*, underline for *WARNING*, background highlight for *INFO*) on top of the configurable background. + +The control paints three visual states ([**NormalState**](#normalstate), [**HoverState**](#hoverstate), [**FocusedState**](#focusedstate)) driven by parallel [**WaynesTextBoxState**](WaynesTextBoxState) sub-objects, each of which carries its own background fill, borders, corners, text rendering, selection colours, caret colour, and decorator colours. + +The current text is held in [**Value**](#value). Surrogate-pair characters are handled correctly by the cursor / selection logic — the caret never lands between the high and low halves of a pair. + +```tb +Private Sub Form_Load() + txtName.Value = "" + txtName.NormalState.TextRendering.Padding.Left = 6 + txtName.NormalState.TextRendering.Padding.Right = 6 +End Sub +``` + +* TOC +{:toc} + +## Inline text decorators + +As the user types, the control automatically marks any occurrence of three literal strings inside [**Value**](#value): + +- `ERROR` — a red squiggle underline (colour from [**WaynesTextBoxState.DecorationERROR**](WaynesTextBoxState#decorationerror)). +- `WARNING` — a dark-blue 2-pixel straight underline (from [**DecorationWARNING**](WaynesTextBoxState#decorationwarning)). +- `INFO` — a light-blue background highlight (from [**DecorationINFO**](WaynesTextBoxState#decorationinfo)). + +The colours are configurable per visual state. The substrings themselves are hard-coded into the control's paint logic in the current release. + +## Properties + +### Anchors +{: .no_toc } + +Which sides of the control are pinned to its container during resize. [**Anchors**](../Styles/Anchors). Inherited. + +### Dock +{: .no_toc } + +How the control is docked inside its container. A member of [**DockMode**](../Enumerations/DockMode). Inherited. + +### FocusedState +{: .no_toc } + +The [**WaynesTextBoxState**](WaynesTextBoxState) used when the control has the keyboard focus. Pre-set with focus-specific defaults — orange caret, blue selection background. + +### Height +{: .no_toc } + +The control's height in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### HoverState +{: .no_toc } + +The [**WaynesTextBoxState**](WaynesTextBoxState) used when the mouse is hovering over the textbox without it having focus. + +### Left +{: .no_toc } + +The horizontal offset of the control's left edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Name +{: .no_toc } + +The unique design-time name of the control on its parent form. **String**. Inherited. + +### NormalState +{: .no_toc } + +The [**WaynesTextBoxState**](WaynesTextBoxState) used when the textbox is at rest — not focused and not hovered. + +### TabIndex +{: .no_toc } + +The position of the control in the form's TAB-key navigation order. **Long**. Inherited. + +### TabStop +{: .no_toc } + +Whether the user can reach the control by pressing **TAB**. **Boolean**. Inherited. Default: **True**. + +### Top +{: .no_toc } + +The vertical offset of the control's top edge from its container, in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. + +### Value +{: .no_toc } + +The current text in the field. **String**. Default: `"Textbox"`. + +Syntax: *object*.**Value** [ = *string* ] + +### Visible +{: .no_toc } + +Whether the control is currently displayed. **Boolean**. Inherited. Default: **True**. + +### Width +{: .no_toc } + +The control's width in pixels. [**PixelCount**](../Enumerations/PixelCount). Inherited. diff --git a/docs/Reference/CustomControls/WaynesTimer.md b/docs/Reference/CustomControls/WaynesTimer.md new file mode 100644 index 00000000..23e7039a --- /dev/null +++ b/docs/Reference/CustomControls/WaynesTimer.md @@ -0,0 +1,91 @@ +--- +title: WaynesTimer +parent: CustomControls Package +permalink: /tB/Packages/CustomControls/WaynesTimer +has_toc: false +--- + +# WaynesTimer class +{: .no_toc } + +A non-visual timer control. Wraps an internal [**CustomControlTimer**](Framework/CustomControlTimer) and surfaces its [**Interval**](#interval) / [**Enabled**](#enabled) as designer-visible properties — drop a **WaynesTimer** onto a [**WaynesForm**](WaynesForm/) at design time, set the interval, and handle the [**Timer**](#timer) event to run code on a repeating schedule. + +At design time the control paints a 🕑 clock-face glyph centred in its rectangle, on a pale grey background, scaled to fit the control. At run time the control is invisible — its visible **Width** and **Height** are clamped to 32×32 on initialize but the control itself draws nothing. + +```tb +Private Sub Form_Load() + Timer1.Interval = 1000 + Timer1.Enabled = True +End Sub + +Private Sub Timer1_Timer() + lblClock.Caption = Format$(Now(), "hh:nn:ss") +End Sub +``` + +## Properties + +### Anchors +{: .no_toc } + +Which sides of the control are pinned to its container during resize. [**Anchors**](Styles/Anchors). Inherited. (Has no visual effect at run time since the control draws nothing then.) + +### Dock +{: .no_toc } + +How the control is docked inside its container. A member of [**DockMode**](Enumerations/DockMode). Inherited. + +### Enabled +{: .no_toc } + +Whether the timer is currently running. Setting to **True** starts it; setting to **False** stops it. **Boolean**. + +Syntax: *object*.**Enabled** [ = *value* ] + +### Height +{: .no_toc } + +The control's height in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. Forced to 32 on initialize. + +### Interval +{: .no_toc } + +The number of milliseconds between successive [**Timer**](#timer) events. **Long**. A value of 0 means the timer never fires. + +Syntax: *object*.**Interval** [ = *value* ] + +Changing **Interval** while the timer is enabled takes effect on the next tick. + +### Left +{: .no_toc } + +The horizontal offset of the control's left edge from its container, in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Name +{: .no_toc } + +The unique design-time name of the control on its parent form. **String**. Inherited. + +### Top +{: .no_toc } + +The vertical offset of the control's top edge from its container, in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. + +### Visible +{: .no_toc } + +Whether the control is currently displayed. **Boolean**. Inherited. (Has no visual effect at run time.) + +### Width +{: .no_toc } + +The control's width in pixels. [**PixelCount**](Enumerations/PixelCount). Inherited. Forced to 32 on initialize. + +## Events + +### Timer +{: .no_toc } + +Raised every [**Interval**](#interval) milliseconds while [**Enabled**](#enabled) is **True**. + +Syntax: *object*\_**Timer**( ) diff --git a/docs/Reference/CustomControls/index.md b/docs/Reference/CustomControls/index.md new file mode 100644 index 00000000..97ccbae6 --- /dev/null +++ b/docs/Reference/CustomControls/index.md @@ -0,0 +1,91 @@ +--- +title: CustomControls Package +parent: Packages +grand_parent: Reference Section +nav_order: 5 +permalink: /tB/Packages/CustomControls/ +has_toc: false +--- + +# CustomControls Package + +The **CustomControls** built-in package supplies a set of fully owner-drawn controls — buttons, a form, a frame, a grid, a label, a slider, a textbox, and a timer — together with the framework on which they are built. Every visible pixel is rendered by the package itself rather than by Windows, so the look and feel is identical across systems and is configured entirely through a small vocabulary of style objects ([**Fill**](Styles/Fill), [**Borders**](Styles/Borders), [**Corners**](Styles/Corners), [**TextRendering**](Styles/TextRendering), …) rather than by toggling theme flags. + +The package ships as two paired components: a **CustomControls DESIGNER** library — the framework half, source-side project `CustomControls` — that defines the rendering surface and the interface every custom control implements; and the **Custom Controls** package — source-side project `CustomControlsPackage` — that supplies the eight concrete `Waynes…` controls. The two are co-versioned with twinBASIC and always ship together; both are MIT-licensed. + +Beyond providing ready-to-use controls, the package doubles as a worked example for authoring your own custom controls. The `Waynes…` classes implement the same [**ICustomControl**](Framework/ICustomControl) interface that a hand-written control would, against the same [**CustomControlContext**](Framework/CustomControlContext) callback object and [**Canvas**](Framework/Canvas) drawing surface — see the [Framework](Framework/) page for the host-side contract. + +```tb +Private Sub Form_Load() + btnGo.Caption = "Continue" + btnGo.NormalState.BackgroundFill.ColorPoints.SetSolidColor vbBlue + btnGo.NormalState.Corners.SetAll tbCurve, 12 + txtName.Value = "" +End Sub + +Private Sub btnGo_Click() + MsgBox "Hello, " & txtName.Value +End Sub +``` + +## Controls + +- [WaynesButton](WaynesButton/) -- owner-drawn push-button with separate visual states for normal, hover, focused, and pressed +- [WaynesForm](WaynesForm/) -- top-level form for hosting custom controls; carries the **WindowsOptions** sub-object that drives the Win32 frame +- [WaynesFrame](WaynesFrame) -- rectangular container that fills its area with a configurable background +- [WaynesGrid](WaynesGrid/) -- tabular data display with column headers, row headers, hover / selection states, and resizable columns +- [WaynesLabel](WaynesLabel) -- static text display with fill, text rendering, and caption +- [WaynesSlider](WaynesSlider/) -- horizontal or vertical value slider with hover / focused states and a draggable block +- [WaynesTextBox](WaynesTextBox/) -- single-line editable text field with selection, caret, surrogate-pair awareness, and inline text decorators +- [WaynesTimer](WaynesTimer) -- non-visual timer that raises a **Timer** event at a programmable interval + +Every concrete control implements [**ICustomControl**](Framework/ICustomControl) and inherits a small set of layout-and-name members from an internal base class: + +- All controls expose **Name**, **Left**, **Top**, **Width**, **Height**, **Anchors**, **Dock**, and **Visible**. +- Controls that can take keyboard focus ([**WaynesButton**](WaynesButton/), [**WaynesGrid**](WaynesGrid/), [**WaynesSlider**](WaynesSlider/), [**WaynesTextBox**](WaynesTextBox/)) additionally expose **TabIndex** and **TabStop**. +- [**WaynesForm**](WaynesForm/) instead exposes form-level members: **FormDesignerId**, **Name**, position / size, and the **Controls** collection. + +These members are listed on each control's own page; their definitions are identical and are not repeated separately. + +## Style objects + +The visual style of every control is driven by a handful of small helper classes, instantiated automatically through `Public WithEvents …` properties. They are nested arbitrarily — a [**TextRendering**](Styles/TextRendering) contains a [**Fill**](Styles/Fill) for the text colour, which contains a `Granularity` and an array of `FillColorPoint` gradient stops; an array of [**Border**](Styles/Borders#border-class) objects describes how the outline of a control is stroked; and so on. + +- [Anchors](Styles/Anchors) -- which sides of a control are pinned to its container when the container is resized +- [Borders](Styles/Borders) -- one or more border strokes drawn around a control (including the single-stroke `Border` sub-object) +- [Corners](Styles/Corners) -- the four corner shapes and radii of a control (including the per-corner `Corner` sub-object) +- [Fill](Styles/Fill) -- the colour or gradient that paints a region (including the `FillColorPoint` / `FillColorPoints` gradient-stop sub-objects) +- [Line](Styles/Line) -- a single grid-line or resizer-bar stroke; thinner shape than a full border +- [Padding](Styles/Padding) -- per-side padding around text inside a [**TextRendering**](Styles/TextRendering) +- [TextRendering](Styles/TextRendering) -- font, padding, fill, outlines, alignment, and overflow for the text drawn inside a control (including the `FontStyle` sub-object) + +Every style object raises an **OnChanged** event whenever one of its fields is set, and the control that hosts it requests a repaint on each change — assigning style values at runtime triggers an immediate redraw. + +## Framework + +For authoring your own custom controls or forms, the **CustomControls DESIGNER** half of the package supplies: + +- [ICustomControl](Framework/ICustomControl) -- the interface every custom control implements: **Initialize**, **Destroy**, **Paint** +- [ICustomForm](Framework/ICustomForm) -- the analogous interface for custom form classes +- [CustomControlContext](Framework/CustomControlContext) -- callback object passed to **Initialize**; offers serializer access, repaint requests, timer creation, and focus changes +- [CustomFormContext](Framework/CustomFormContext) -- a **CustomControlContext** extended with **Show** and **Close** for form-class controls +- [CustomControlTimer](Framework/CustomControlTimer) -- the timer returned by **CustomControlContext.CreateTimer**; carries **Interval**, **Enabled**, and an **OnTimer** event +- [CustomControlsCollection](Framework/CustomControlsCollection) -- the **Controls** collection on a form +- [Canvas](Framework/Canvas) -- the drawing surface passed to **Paint**; the only way to put pixels into a custom control +- [SerializeInfo](Framework/SerializeInfo) -- the per-instance serializer reached via **CustomControlContext.GetSerializer**; used to deserialize designer-set property values and to query the runtime mode + +## Enumerations + +- [BorderStyle](Enumerations/BorderStyle) -- window-frame style passed to [**WindowsFormOptions.BorderStyle**](WaynesForm/WindowsFormOptions#borderstyle) +- [ColorRGBA](Enumerations/ColorRGBA) -- `Long`-compatible type alias for 32-bit ABGR colour values +- [CornerShape](Enumerations/CornerShape) -- how a single corner of a control is shaped: curve, notch, or cut-out +- [Customtate](Enumerations/Customtate) -- duplicate of [**WindowState**](Enumerations/WindowState); reserved +- [DockMode](Enumerations/DockMode) -- how a control is docked inside its container +- [FillPattern](Enumerations/FillPattern) -- the gradient or fill pattern used by a [**Fill**](Styles/Fill) +- [FontWeight](Enumerations/FontWeight) -- font weights from **tbThin** through **tbHeavy**, mirroring the OpenType `wght` scale +- [PixelCount](Enumerations/PixelCount) -- `Long`-compatible type alias for measurements expressed in pixels +- [PointSize](Enumerations/PointSize) -- `Long`-compatible type alias for font sizes expressed in points +- [StartupPosition](Enumerations/StartupPosition) -- initial position of a form when it is first shown +- [TextAlignment](Enumerations/TextAlignment) -- horizontal and vertical alignment of text within a [**TextRendering**](Styles/TextRendering) +- [TextOverflowMode](Enumerations/TextOverflowMode) -- how text longer than the available area is truncated +- [WindowState](Enumerations/WindowState) -- the minimized / normal / maximized window state of a form diff --git a/docs/Reference/WebView2/index.md b/docs/Reference/WebView2/index.md index d18f54b0..a5d47707 100644 --- a/docs/Reference/WebView2/index.md +++ b/docs/Reference/WebView2/index.md @@ -2,7 +2,7 @@ title: WebView2 Package parent: Packages grand_parent: Reference Section -nav_order: 5 +nav_order: 6 permalink: /tB/Packages/WebView2/ has_toc: false --- From 742be5c3b0a72d3b0aa191f4093de06cec90c97f Mon Sep 17 00:00:00 2001 From: Kuba Sunderland-Ober Date: Wed, 13 May 2026 17:04:41 +0200 Subject: [PATCH 4/4] Link to the CustomControls documentation where appropriate. --- docs/Features/GUI-Components/Windowless.md | 6 +++--- .../CustomControls/Defining a CustomControl.md | 14 +++++++++++--- .../Notes about the form designer.md | 6 +++++- .../Painting-drawing to your control.md | 17 ++++++++++++++--- .../Property sheet and object serialization.md | 8 +++++++- docs/Tutorials/CustomControls/index.md | 6 +++++- 6 files changed, 45 insertions(+), 12 deletions(-) diff --git a/docs/Features/GUI-Components/Windowless.md b/docs/Features/GUI-Components/Windowless.md index 46b4378d..8a72788c 100644 --- a/docs/Features/GUI-Components/Windowless.md +++ b/docs/Features/GUI-Components/Windowless.md @@ -101,12 +101,12 @@ redirect_from: 1. **Render the Entire Form to a Bitmap** * In VB6: Use `BitBlt` or `PaintPicture` to copy the form’s visible area. - * In TwinBASIC: Use the form’s `Canvas` or `ICustomControl.Paint` logic to manually render windowless elements to a bitmap. + * In TwinBASIC: Use the form’s [`Canvas`](../../tB/Packages/CustomControls/Framework/Canvas) or [`ICustomControl.Paint`](../../tB/Packages/CustomControls/Framework/ICustomControl#paint) logic to manually render windowless elements to a bitmap. See the [CustomControls package reference](../../tB/Packages/CustomControls/) for the full framework surface. 2. **Ensure Windowless Controls Are Painted** - * For custom controls using `ICustomControl.Paint`, call their paint routines manually into the same bitmap or `DC`. - * If using `Canvas.AddElement`, simulate a paint pass with the same layout logic used during runtime. + * For [custom controls](../../tB/Packages/CustomControls/) using [`ICustomControl.Paint`](../../tB/Packages/CustomControls/Framework/ICustomControl#paint), call their paint routines manually into the same bitmap or `DC`. + * If using [`Canvas.RuntimeUICCCanvasAddElement`](../../tB/Packages/CustomControls/Framework/Canvas#runtimeuicccanvasaddelement), simulate a paint pass with the same layout logic used during runtime. 3. **Send the Bitmap to the Printer** diff --git a/docs/Tutorials/CustomControls/Defining a CustomControl.md b/docs/Tutorials/CustomControls/Defining a CustomControl.md index a3a65260..e53a573d 100644 --- a/docs/Tutorials/CustomControls/Defining a CustomControl.md +++ b/docs/Tutorials/CustomControls/Defining a CustomControl.md @@ -43,7 +43,7 @@ This is an optional attribute, but it is usually advisable to set this attribute ## Must implement ICustomControl ![CustomControl ICustomControl interface](Images/ccICustomControl.png) -All CustomControls *must* implement CustomControls.ICustomControl. This interface currently has 3 methods that you must implement: +All CustomControls *must* implement [`CustomControls.ICustomControl`](../../tB/Packages/CustomControls/Framework/ICustomControl). This interface currently has 3 methods that you must implement: ```tb Sub Initialize(ByVal Context As CustomControlContext) @@ -78,7 +78,7 @@ Public Dock As CustomControls.DockMode Public Visible As Boolean ``` -The form designer and the form engine work with these properties, so it is important to include them in your CustomControl class. +The form designer and the form engine work with these properties, so it is important to include them in your CustomControl class. The types used here are all defined in the framework: [`PixelCount`](../../tB/Packages/CustomControls/Enumerations/PixelCount), [`DockMode`](../../tB/Packages/CustomControls/Enumerations/DockMode), and the [`Anchors`](../../tB/Packages/CustomControls/Styles/Anchors) style object. Note that the form designer works with pixel values which are not DPI-scaled. So the Left/Top/Width/Height properties of your control do not reflect DPI scaling. For example, if your control has a width of 50 pixels, then at DPI 150%, then the actual drawing width is 75 pixels ( see [Painting / drawing to your control](Painting)). @@ -90,4 +90,12 @@ CustomControls *must* offer a serialization constructor: Public Sub New(Serializer As SerializationInfo) ``` -The passed in Serializer object offers a `Deserialize()` method that you call in order to load the properties that have been set for your control via the form designer. See [Property Sheet and Object Serialization](Properties) for further information. \ No newline at end of file +The passed in Serializer object offers a `Deserialize()` method that you call in order to load the properties that have been set for your control via the form designer. See [Property Sheet and Object Serialization](Properties) for further information. + +> [!NOTE] +> The current framework names the serializer type [`SerializeInfo`](../../tB/Packages/CustomControls/Framework/SerializeInfo) (not `SerializationInfo`), and `Deserialize()` is exposed as `RuntimeUISrzDeserialize()`. See the reference page for the current member names and the design-mode / runtime-mode flags also carried on this object. + +*** +## See also + +- [CustomControls package reference](../../tB/Packages/CustomControls/) — the full reference for the framework half (interfaces, callback objects, the [`Canvas`](../../tB/Packages/CustomControls/Framework/Canvas) drawing surface, the [`SerializeInfo`](../../tB/Packages/CustomControls/Framework/SerializeInfo) serializer) and the built-in `Waynes…` controls built on it. \ No newline at end of file diff --git a/docs/Tutorials/CustomControls/Notes about the form designer.md b/docs/Tutorials/CustomControls/Notes about the form designer.md index 2450f9d3..bca399df 100644 --- a/docs/Tutorials/CustomControls/Notes about the form designer.md +++ b/docs/Tutorials/CustomControls/Notes about the form designer.md @@ -9,4 +9,8 @@ redirect_from: # Notes About the Form Designer -For the painting of controls in the form designer, CustomControl instances are instantiated and then release immediately after painting has finished. \ No newline at end of file +For the painting of controls in the form designer, CustomControl instances are instantiated and then release immediately after painting has finished. The design-mode flag is exposed on the framework's [`SerializeInfo.RuntimeUISrzIsDesignMode`](../../tB/Packages/CustomControls/Framework/SerializeInfo#runtimeuisrzisdesignmode) — controls that want to render a placeholder only inside the designer (the way [`WaynesTimer`](../../tB/Packages/CustomControls/WaynesTimer) draws its 🕑 glyph) check this flag during [`Initialize`](../../tB/Packages/CustomControls/Framework/ICustomControl#initialize). + +## See also + +- [CustomControls package reference](../../tB/Packages/CustomControls/) — overview of the framework and the built-in `Waynes…` controls \ No newline at end of file diff --git a/docs/Tutorials/CustomControls/Painting-drawing to your control.md b/docs/Tutorials/CustomControls/Painting-drawing to your control.md index 9c83c98a..2efd7f5c 100644 --- a/docs/Tutorials/CustomControls/Painting-drawing to your control.md +++ b/docs/Tutorials/CustomControls/Painting-drawing to your control.md @@ -10,7 +10,7 @@ redirect_from: # Painting / Drawing to Your Control ### The ICustomControl.Paint method -This is by far the most important method of a CustomControl. It tells the form engine exactly how you want it to render your control. +This is by far the most important method of a CustomControl. It tells the form engine exactly how you want it to render your control. See the [`ICustomControl.Paint`](../../tB/Packages/CustomControls/Framework/ICustomControl#paint) reference for the host-side contract. > [!TIP] > It is highly advisable to look at and experiment with the sample project provided with twinBASIC before trying to implement your own CustomControl. @@ -20,7 +20,7 @@ Private Sub OnPaint(ByVal Canvas As CustomControls.Canvas) _ Implements ICustomControl.Paint ``` -You are passed a Canvas object that offers the following methods: +You are passed a [`Canvas`](../../tB/Packages/CustomControls/Framework/Canvas) object that offers the following methods: ```tb Canvas.Width As Long [Property-Get] @@ -30,6 +30,9 @@ Canvas.DpiScaleFactor As Double [Property-Get] Canvas.AddElement(Descriptor As ElementDescriptor) ``` +> [!NOTE] +> The current framework spells these members [`RuntimeUICCGetWidth`](../../tB/Packages/CustomControls/Framework/Canvas#runtimeuiccgetwidth), [`RuntimeUICCGetHeight`](../../tB/Packages/CustomControls/Framework/Canvas#runtimeuiccgetheight), [`RuntimeUICCGetDpi`](../../tB/Packages/CustomControls/Framework/Canvas#runtimeuiccgetdpi), [`RuntimeUICCGetDpiScaleFactor`](../../tB/Packages/CustomControls/Framework/Canvas#runtimeuiccgetdpiscalefactor), and [`RuntimeUICCCanvasAddElement`](../../tB/Packages/CustomControls/Framework/Canvas#runtimeuicccanvasaddelement). The shorter names shown above are how the API was originally drafted; the underlying behaviour is the same. + `Canvas.Width` and `Canvas.Height` are the absolute pixel sizes that your control is drawing to. Unlike your controls Width/Height properties that are not DPI-scaled, the `Canvas.Width` and `Canvas.Height` values **are** DPI-scaled. The `Canvas.Dpi` property represents the DPI setting in Windows. If no DPI scaling is in effect, this value is 96. For example, if you have scaling set at 150% on your monitor, then the `Canvas.Dpi` property will be 144. @@ -98,4 +101,12 @@ Class MyCustomControl EventInfo (MouseEvent) provides mouse information such as the relative X/Y position of the mouse, plus the TrackingX/Y values discussed earlier. -- When you call Canvas.AddElement, your element goes into a render pipeline. It is **not** immediately painted to the screen. The render pipeline is compared to the previous render pipeline that was provided by you in the last OnPaint call, and the tB form engine will only redraw areas of the control that have changed. This allows for efficient painting of controls whilst not needing to be concerned about the finer details of how to do partial repainting. \ No newline at end of file +- When you call Canvas.AddElement, your element goes into a render pipeline. It is **not** immediately painted to the screen. The render pipeline is compared to the previous render pipeline that was provided by you in the last OnPaint call, and the tB form engine will only redraw areas of the control that have changed. This allows for efficient painting of controls whilst not needing to be concerned about the finer details of how to do partial repainting. + +*** +## See also + +- [`ICustomControl`](../../tB/Packages/CustomControls/Framework/ICustomControl) — the interface every custom control implements +- [`Canvas`](../../tB/Packages/CustomControls/Framework/Canvas) — the drawing surface passed to **Paint** +- Style helpers used by the `BackgroundFill` / `Borders` / `Corners` / `TextRenderingOptions` fields of an `ElementDescriptor`: [`Fill`](../../tB/Packages/CustomControls/Styles/Fill), [`Borders`](../../tB/Packages/CustomControls/Styles/Borders), [`Corners`](../../tB/Packages/CustomControls/Styles/Corners), [`TextRendering`](../../tB/Packages/CustomControls/Styles/TextRendering) +- [CustomControls package reference](../../tB/Packages/CustomControls/) — overview of the framework and the built-in `Waynes…` controls (a number of which — `WaynesGrid`, `WaynesButton`, … — are exactly the worked examples mentioned above) \ No newline at end of file diff --git a/docs/Tutorials/CustomControls/Property sheet and object serialization.md b/docs/Tutorials/CustomControls/Property sheet and object serialization.md index aa708f10..60eb7c16 100644 --- a/docs/Tutorials/CustomControls/Property sheet and object serialization.md +++ b/docs/Tutorials/CustomControls/Property sheet and object serialization.md @@ -83,4 +83,10 @@ At the moment, the form-designer doesn't yet support code-behind-forms, so this > The serialization happens via JSON when running in the IDE, but via a binary format when running in a compiled DLL/EXE. The `SerializationInfo` object that is passed to your serialization constructor is a different implementation when running in the IDE, but this should be transparent to you as a CustomControl implementer. > [!TIP] -> When making changes or updates to a CustomControl always consider backwards compatibility. For example, if you rename an exposed property, the old property values stored via the property sheet won't be deserialized to your new property. \ No newline at end of file +> When making changes or updates to a CustomControl always consider backwards compatibility. For example, if you rename an exposed property, the old property values stored via the property sheet won't be deserialized to your new property. + +*** +## See also + +- [`SerializeInfo`](../../tB/Packages/CustomControls/Framework/SerializeInfo) — the reference for the current serializer type (the `SerializationInfo` name in the snippets above is the older draft name; the current type is `SerializeInfo` and `Deserialize()` is exposed as `RuntimeUISrzDeserialize()`) +- [CustomControls package reference](../../tB/Packages/CustomControls/) — overview of the framework and the built-in `Waynes…` controls \ No newline at end of file diff --git a/docs/Tutorials/CustomControls/index.md b/docs/Tutorials/CustomControls/index.md index 6b2e0f59..5b111101 100644 --- a/docs/Tutorials/CustomControls/index.md +++ b/docs/Tutorials/CustomControls/index.md @@ -20,4 +20,8 @@ A few highlights; - designed for efficiency so that supporting complex controls with hundreds of elements (e.g. a DataGrid with 100's of cells) is easily possible - designed for flexibility, allowing for curved corners, multiple borders, background gradients and much more - the form engine supports anchoring and docking without any considerations needed for CustomControl implementers -- simple property sheet synchronization via the built-in form designer \ No newline at end of file +- simple property sheet synchronization via the built-in form designer + +## See also + +- [CustomControls package reference](../tB/Packages/CustomControls/) — the full reference for the built-in `Waynes…` controls and the framework they are built on, including [`ICustomControl`](../tB/Packages/CustomControls/Framework/ICustomControl), [`Canvas`](../tB/Packages/CustomControls/Framework/Canvas), and the style helpers ([`Fill`](../tB/Packages/CustomControls/Styles/Fill), [`Corners`](../tB/Packages/CustomControls/Styles/Corners), [`Borders`](../tB/Packages/CustomControls/Styles/Borders), [`TextRendering`](../tB/Packages/CustomControls/Styles/TextRendering), …) \ No newline at end of file