Skip to content

Image is modelled but not in the toolbox: it cannot be drawn, add_control refuses it, and an empty one is invisible in the designer #860

Open

Description

@imojenisys

VB.Image is modelled, but the toolbox does not offer it, so it cannot be drawn and add_control refuses it. And because an Image with no Picture draws nothing in the designer, one drawn by hand would vanish once deselected.

Evidence

All of this comes from reading the code at main 45e3a6b, where every citation was checked. None of it was checked in a running IDE.

  • IDE/HexIDE/IDE/ComponentRegistry.cs:24 and IDE/HexIDE.Runtime/Serialization/FormDeserializer.cs:26 both list ImageComponentClass. So a Begin VB.Image block loads and saves (VB.Image, and its mouse-pointer names — 18/22 to 20/22 #111), and draws its picture.
  • The toolbox is hard-coded. IDE/HexIDE/VisualDesigner/ViewModels/ToolBoxToolViewModel.cs:33-47 adds the pointer and 13 controls, PictureBox through Shape, and Image is not among them. The toolbox reads the registry only through ComponentRegistered (:51, :59-62), which only Register() fires. The add-in host (IDE/HexIDE/Addins/HexIdeHost.cs:35) is the only caller of Register(), so the built-in Image never reaches the toolbox.
  • add_control looks up type only among the toolbox's entries (IDE/HexIDE.Desktop/Server/HexIdeTools.cs:1099-1114). So type: "Image" returns Unknown control type 'Image'. Known types: ..., and Image is not in that list. get_toolbox_items (:1704) reads the same collection.
  • IDE/HexIDE/Themes/IconGeometry.axaml:94-107 runs from Geo.Cursor to Geo.Shape and has no Geo.Image.
  • An empty Image is invisible on the design canvas. The designer creates the runtime control and renders it to a bitmap (IDE/HexIDE/Controls/ControlRenderer.cs:66-97, created at :73). The item template is a bare ContentPresenter and draws no outline (IDE/HexIDE/VisualDesigner/Views/FormEditView.axaml:200-205). When there is no picture, VBImage.Render returns before drawing anything (IDE/HexIDE.Runtime/BuiltinControls/VBImage.cs:103-106). You can see this today: load a .frm holding an Image with no Picture, and once it is deselected only the grid shows where it is.

docs/MISSING_FEATURES.md:348 marks Image Done. Before #165 the row read | Image | Missing | Not in toolbox |, which was right about the toolbox. #165 changed only docs. It changed the row to Done, reasoning from the component class and the deserializer ("Image was never missing"). #163 makes the same assumption ("Shape and Image are both implemented"). Step 3 of CLAUDE.md's "Adding a new VB6 control" recipe was only half done: the deserializer part, not the toolbox part.

What VB6 does

None of this was measured on the oracle VM.

  • Toolbox order: VB6's General tab has Image after Shape and Line.
  • What VB6's designer draws for an Image with no Picture and BorderStyle 0 is unknown, and step 2 of the fix depends on it.

Suggested fix

  1. Add ImageComponentClass to the toolbox directly after Shape, with a new Geo.Image geometry. When The Line control — the first intrinsic that is not a rectangle #163 lands, Line goes between them.
  2. Measure on the oracle what VB6 draws at design time for an empty Image, record it in docs/vb6-fidelity-oracle.md, and draw the same thing, at design time only. PowerShell Direct alone cannot see the guest desktop. Instead, use the IDE route in that file's "Reaching the VB6 IDE, not just the compiler" section (:25): a logon agent drives the IDE, and a framebuffer screenshot shows what it drew. The Settle whether a new module gets a file at all: two Add Form commands answer differently, and #273 is about to build naming on top of it #489 entry (:4217) was measured this way. The human-in-the-loop method in "Note on method" (:1490) also works; the empty-box entry at :1539 used it.
    The seam is ControlRenderer.UpdateContent, which creates every control the designer shows (:73). It can set a design-time property on the VBImage it renders. The property defaults to off, so a running form is unchanged. Timer is not the model to copy: its runtime template doubles as its design-time icon, and the runtime loader hides it (IDE/HexIDE.Runtime/VBLoader.cs:336). If VB6 also draws nothing, this step comes down to the oracle entry alone.
  3. Pin it with a test that every ComponentRegistry entry except FormComponentClass has a toolbox entry. That test guards the registry against the toolbox. It does not cover FormDeserializer.AllSupportedComponents, a third list, which also holds Menu.
    Three test classes skip the toolbox's constructor with GetUninitializedObject, each inside a shared builder: DockFactoryTests.CreateFactory (IDE/HexIDE.Tests/ViewModels/DockFactoryTests.cs:31-32), MainViewViewModelTests.Build, called from the class constructor (MainViewViewModelTests.cs:54-56), and FindReplaceViewModelTests.CreateMainViewViewModel (FindReplaceViewModelTests.cs:595). The first two say the constructor "loads Avalonia bitmaps". That looks out of date. IconFactory.Themed builds a vector DrawingImage, and with no Application, or on the wrong thread, it falls back to an icon with no geometry (IDE/HexIDE/Utils/IconFactory.cs:47-52, :84-85). So plain construction may work, but nobody has tried it. If it does not work, build the toolbox under the headless Avalonia setup, or move the built-in list out of the constructor.
  4. Update the note on row 348. Once this lands, the toolbox half of that row is true. The row as a whole is not, because Image raises no events (see below).

Not in this issue

  • Image raises no events. IDE/HexIDE.Runtime/Components/ImageComponentClass.cs:20-32 passes no event list, where Label passes [ClickEvent] (LabelComponentClass.cs:17). VBImage never calls AttachedEvents.AttachClick. So the code window lists no event procedures for an Image (IDE/HexIDE/Forms/ViewModels/CodeEditorViewModel.cs:483-486), and Image1_Click never fires. A hand-drawn Image hits this as soon as this issue lands. No issue covers it yet.
  • ImageComponentClass declares BorderStyle (:23), but InstantiateInternal never passes it on (:39-49), and VBImage has no such property. So BorderStyle = 1 draws no border, at design time or at run time. Whoever does step 2 will run into this. No issue covers it yet.

Related: #111 (added the class), #157 (an unmodelled control is invisible in the designer for a different reason: it has no ComponentInstance at all), #163 (Line), #164, #165.

Activity

  1. added
    enhancementNew feature or request
    needs-oracleThe answer comes from real vb6.exe. Measure it, then record it in docs/vb6-fidelity-oracle.md.
    form-designerThe visual designer and the controls it draws: toolbox, selection, geometry, properties.
    smallT-shirt size, never time. One seam, mechanism already settled. Anchor: PR #240.
    on Oct 12, 2026
  2. added a commit that references this issue on Nov 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestform-designerThe visual designer and the controls it draws: toolbox, selection, geometry, properties.needs-oracleThe answer comes from real vb6.exe. Measure it, then record it in docs/vb6-fidelity-oracle.md.smallT-shirt size, never time. One seam, mechanism already settled. Anchor: PR #240.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions