# Copyright (c) 2025-2026 Gigasoft, Inc. All rights reserved. === ProEssentials Quick (knowledge rev 4.1) (Negative) Annotations === Quick Annotations are temporary graph annotations rendered via an optimized path that avoids full image rebuilds. They are ideal for measurement overlays, drag rectangles, crosshairs, and transient tooling UI that updates on every MouseMove. See Example 110 (log-log axes with drag measurement tool). CONCEPT: Normal annotations are part of the chart's cached bitmap (CacheBmp). Changing them requires a full ResetImage rebuild -- too slow for MouseMove. Quick annotations use a separate render list drawn ON TOP of the cached bitmap (CacheBmp2), so only the quick annotation drawing commands are rebuilt each frame. This is the same concept as a display-list overlay. REQUIRED SETUP (in chart configuration): chart.PeConfigure.CacheBmp2 = true; // REQUIRED -- enables the second cache layer HOW TO MARK AN ANNOTATION AS "QUICK" (NEGATIVE TYPE): Instead of setting a positive GraphAnnotationType, negate it with this formula: Graph.Type[i] = ((int)GraphAnnotationType.SomeType + 1) * -1; Examples: // Normal annotation (permanent, part of full image): Graph.Type[0] = (int)GraphAnnotationType.TopLeft; // Quick annotation (temporary, overlay-only): Graph.Type[0] = ((int)GraphAnnotationType.TopLeft + 1) * -1; This works with ANY GraphAnnotationType value. The negative sign is the signal that this annotation belongs to the quick-draw overlay list. SHOWING AND HIDING (trigger the overlay render path): // After setting quick annotation properties, trigger display: chart.PeAnnotation.ShowingQuickAnnotations = true; chart.Invalidate(); chart.Refresh(); // To clear/hide all quick annotations (e.g., on MouseUp): chart.PeAnnotation.ShowingQuickAnnotations = false; chart.PeAnnotation.HidingQuickAnnotations = true; chart.Invalidate(); chart.Refresh(); RENDERING PIPELINE (what happens internally): 1. Normal WM_PAINT with CacheBmp2: bitblits the cached chart image. 2. When ShowingQuickAnnotations = true: after bitblit, the engine rebuilds ONLY the drawing commands for negative-type annotations and composites them on top of the cached image. The cached image itself is NOT rebuilt. 3. When HidingQuickAnnotations = true: the overlay is cleared, reverting to the clean cached image. CacheBmp2 remains valid throughout. Result: smooth real-time annotation updates with minimal CPU usage. COMPLETE EXAMPLE PATTERN (from Example 110 -- drag measurement tool): Setup (chart configuration): Pesgo1.PeConfigure.CacheBmp2 = true; Pesgo1.PeUserInterface.Allow.Zooming = AllowZooming.None; // mouse used for drag Pesgo1.PeUserInterface.Cursor.PromptStyle = CursorPromptStyle.XYValues; Class-level variables: bool bDragging = false; double dDragStartX, dDragStartY; MouseDown handler -- capture start point: bDragging = true; // ConvPixelToGraph to get dDragStartX, dDragStartY in data coordinates // Clamp to ManualMinX/MaxX/MinY/MaxY chart.PeUserInterface.Cursor.PromptStyle = CursorPromptStyle.None; // hide default tooltip MouseMove handler (while dragging) -- build measurement overlay: if (!bDragging) return; // ConvPixelToGraph to get current fX, fY // Clamp to ManualMinX/MaxX/MinY/MaxY // Determine dLeft, dRight, dTop, dBottom from start and current points // Annotation [0]: TopLeft corner of bounding rect Graph.X[0] = dLeft; Graph.Y[0] = dTop; Graph.Type[0] = ((int)GraphAnnotationType.TopLeft + 1) * -1; // Annotation [1]: BottomRight corner of bounding rect Graph.X[1] = dRight; Graph.Y[1] = dBottom; Graph.Type[1] = ((int)GraphAnnotationType.BottomRight + 1) * -1; // Annotation [2]: Filled rectangle overlay (semi-transparent) Graph.X[2] = dRight; Graph.Y[2] = dBottom; Graph.Type[2] = ((int)GraphAnnotationType.RoundRectFill + 1) * -1; Graph.Color[2] = Color.FromArgb(70, 198, 198, 198); // semi-transparent Graph.Text[2] = ""; Graph.GradientStyle[2] = (int)PlotGradientStyle.RadialBottomRight; Graph.GradientColor[2] = Color.FromArgb(170, 255, 255, 255); // Annotation [3]: Rectangle border Graph.X[3] = dRight; Graph.Y[3] = dBottom; Graph.Type[3] = ((int)GraphAnnotationType.RoundRectMedium + 1) * -1; Graph.Color[3] = Color.FromArgb(255, 255, 255, 255); Graph.Text[3] = ""; // Annotation [4]: X-delta label (centered horizontally) Graph.X[4] = centeredX; // midpoint of selection in data coordinates Graph.Y[4] = dTop; Graph.Type[4] = ((int)GraphAnnotationType.NoSymbol + 1) * -1; Graph.Color[4] = Color.FromArgb(255, 0, 255, 0); Graph.Text[4] = "|c<~ " + deltaX + " ~>"; // |c = center justified // Annotation [5]: Y-delta label (centered vertically) Graph.X[5] = dRight; Graph.Y[5] = centeredY; Graph.Type[5] = ((int)GraphAnnotationType.NoSymbol + 1) * -1; Graph.Color[5] = Color.FromArgb(255, 0, 255, 0); Graph.Text[5] = "|D<~ " + deltaY + " ~>"; // |D = perpendicular/angled text Graph.TextSize = 120; chart.PeAnnotation.Graph.Show = true; chart.PeAnnotation.Show = true; chart.PeAnnotation.ShowingQuickAnnotations = true; chart.Invalidate(); chart.Refresh(); MouseUp handler -- clear overlay: bDragging = false; chart.PeAnnotation.ShowingQuickAnnotations = false; chart.PeAnnotation.HidingQuickAnnotations = true; chart.PeUserInterface.Cursor.PromptStyle = CursorPromptStyle.XYValues; // restore tooltip chart.Invalidate(); chart.Refresh(); LOG SCALE CENTERING: When axes use log scale, the visual midpoint of a selection is the geometric mean, not arithmetic mean. Example 110 computes this: double centeredXInLog = (Math.Log10(fX) + Math.Log10(dDragStartX)) / 2.0; double centeredX = Math.Pow(10.0, centeredXInLog); NOTES: - All normal annotation properties work on quick annotations (Color, Text, GradientStyle, GradientColor, BevelStyle, TextSize, text prefixes). - Quick annotations are indexed in the same Graph.X/Y/Type/Color/Text arrays as normal annotations. The negative Type value is the ONLY difference. - You can mix normal (positive) and quick (negative) annotations in the same array. Normal ones render with the cached image; quick ones overlay. - CacheBmp2 = true is also used by DrawCursorToCache for cursor overlays. Both features use the same two-layer caching mechanism. - Quick annotations apply to 2D charts (Pego, Pesgo, Pepso, Pepco). For Pe3do, annotation updates use Force3dxAnnotVerticeRebuild instead.