Thanks for the clear report and the follow-up. You've found a genuine runtime bug here, and your diagnosis is exactly right.
To answer your question about the order: there's no "window destructs its controls before or after its properties" step at all. When a window closes, teardown runs in this order:
- The
Closing/Close events fire.
- Once the native window is gone, the window releases its children - it removes them and severs each control's
Parent link at that point.
- Destructors run separately under reference counting: an object is destructed when its last reference goes away. Since your Window subclass holds the titlebar in a property, the titlebar actually outlives the window's teardown.
So what you observed is the Parent link being severed during window release, before that last Paint had a chance to fire.
As for why the paint happens at all: a Canvas requests an automatic repaint whenever it's resized or re-rendered, and during the close sequence the renderer can still sneak in one final resize/render pass. That queues one last Paint event, but it gets delivered after the window has already severed the Parent link - so Me.Parent is Nothing inside the handler. It's intermittent because it depends on whether that final render pass beats the teardown, which is pure timing.
Your fix is the right one —-If Me.Parent <> Nothing Then around the paint body is exactly what I'd recommend, and it's good defensive practice for any Paint handler that reads its parent regardless of this bug.
I've logged it here: https://feedback.objo.dev/bug/1621 - the fix will stop the runtime from firing automatic Paint events once a window's teardown has begun.