Repository navigation
🐛 fix(activex): compose frames offscreen to remove pan flicker - #61
Merged
pmeems merged 6 commits intoNov 6, 2026
Merged
Conversation
- Compose OnDraw frames in a resizable DIB-section frame buffer and present them with a single BitBlt, so the visible surface never shows the background erase or a partially drawn frame - Suppress WM_ERASEBKGND because OnDraw paints an opaque frame over the whole bounds - Reword the OpenGL fallback diagnostic to name the preview limitation and the GDI fallback - Add FrameBuffer unit tests and update the diagnostic assertions
pmeems
reviewed
Nov 6, 2026
pmeems
left a comment
Contributor
There was a problem hiding this comment.
Automated review. Final decision is with the human reviewer.
- Compose the frame through a renderFrame lambda used for both the buffered and direct paths - On failure of BitBlt from the offscreen memory DC (cross-device targets such as printers or metafiles), redraw the frame directly to drawInfo.hdcDraw instead of returning E_FAIL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of the flicker/diagnostic plan: double-buffered
OnDraw,WM_ERASEBKGNDsuppression, and a reworded OpenGL fallback diagnostic. Phase 2 (pan-by-blit layer cache) and Phase 3 (Core tessellation for OpenGL) are deliberately not part of this PR.Motivation
Panning a vector map in the C# test host (
samples/CSharp/ActiveXTestHost) flickered heavily on every mouse move, unlike MapWinGIS 5. Two causes:OnDrawpainted directly to the container's DC, so every redraw showed the background erase and the partially drawn frame.WM_ERASEBKGND, so the windowed control erased its background to the host color before each redraw, flashing through the geometry.Separately, the OpenGL preview backend's rejection message ("The scene uses geometry that the OpenGL backend does not support.") read like a geometry corruption error even though the GDI fallback renders the frame correctly. The status bar now reports the actual situation.
Changes
FrameBuffer(new,mwg::activex) — a resizable offscreen DC backed by a 32-bit top-down DIB section (CreateDIBSection,BI_RGB).Resizeallocates the replacement before releasing the current buffer, so a failed resize keeps a presentable buffer; non-positive sizes and allocation failures returnfalse.CMapWinGISControl::OnDraw(rewritten) — composes the frame in theFrameBufferwhen the target size is drawable and presents it with a singleBitBlt(SRCCOPY). Drawing straight todrawInfo.hdcDrawremains the fallback for sizes the buffer cannot hold. Backend contract unchanged: both backends take any HDC, so no backend code was touched for buffering.WM_ERASEBKGNDsuppressed (OnEraseBkgndreturns 1, handled) —OnDrawpaints an opaque frame over the whole bounds, so the erase pass only ever produced a visible flash.OpenGlVectorLayerRenderer::ValidateTarget) — "The OpenGL preview backend supports only convex, hole-free polygons; this frame was rendered with GDI." The OpenGL convex-onlyGL_POLYGONlimitation itself is unchanged; tessellating concave/holed polygons in Core is Phase 3.FrameBufferTests.cpp(8 tests: allocation, resize, same-size reuse, failed-resize keeps buffer, pixel round-trip, release/reuse, non-positive sizes);VectorLayerRendererTests.cppassertions updated to the new diagnostic string.FrameBufferis compiled intoMapWinGIS.ActiveX.Impl.libso the native tests exercise it without COM activation; registered in all three.vcxprojfiles..ai/memory/architecture/activex.mddocumenting the offscreen composition contract.Design decisions
VectorRenderBackendtaking any HDC) is preserved, and the Core stays pure.Resizenever leaves the control without a buffer: the previous DIB is released only after the replacement is fully selected.RenderingStatusdiagnostic string.Build and test status
AGENTS.md) and the authoring environment is Linux-only. Validation is delegated to thebuild.ymlworkflow (windows-2025, Debug x64), which runs on PRs.[[nodiscard]], repo commit conventions); no new warnings are expected, but the compiler pass on CI is the authoritative check.Out of scope (future phases)
_bufferBitmap/_layerBitmap,RedrawSkipDataLayers) for panning without re-rendering layers.