# Copyright (c) 2025-2026 Gigasoft, Inc. All rights reserved. === ProEssentials Cursor (knowledge rev 4.1), ToolTip & CacheBmp Patterns === CORE: PeConfigure.CacheBmp = true; -- ALWAYS SET for all charts. Caches rendered image in memory for flicker-free repainting. Without it, any window overlap causes flicker. No exceptions. Direct2D/Direct3D RenderEngines force it true automatically. CORE: HourGlassThreshold -- set to very large value to disable hourglass cursor during mousemove. Legacy feature from when computers were slow. Modern apps: set to effectively infinite: Cursor.HourGlassThreshold = 1000000000; // disable hourglass === TWO INDEPENDENT SYSTEMS share PeUserInterface.Cursor parent === SYSTEM 1: CursorMode -- visible crosshair/line/square OVERLAY on chart. Gives a specific data point the "focus" (subset index + point index). User navigates with arrow keys (Left/Right = points, Up/Down = subsets) or mouse click (requires MouseCursorControl = true + HotSpot.Data = true). CursorMode values: NoCursor(0) -- no visible cursor overlay (default) Point(1) -- vertical line at focused POINT INDEX (0..Points-1) DataCross(2) -- crosshair lines through focused data point DataSquare(3) -- small square on focused data point FloatingXY(5) -- crosshair follows mouse freely (no point snap) FloatingXOnly(6)-- vertical line follows mouse X position FloatingYOnly(7)-- horizontal line follows mouse Y position FloatingY(4) -- horizontal line follows mouse Y position WARNING: "Point" means point-index focus, NOT a dot/symbol. Floating modes (FloatingXY/XOnly/YOnly) follow mouse freely without snapping to data points -- useful as visual guides while custom MouseMove code reads interpolated values via ConvPixelToGraph (e.g. updating table annotations, example 028). Lazy cursor activation pattern (example 030): start with no CursorMode, then on PeDataHotSpot click set CursorMode.Point and Cursor.Point = e.PointIndex. Cursor only appears after first user interaction -- focused, intentional UX. Reading cursor focus: Cursor.Subset, Cursor.Point (zero-based indices). PeCursorMoved event fires when cursor moves to new data point. SYSTEM 2: PromptTracking -- shows data coordinates as user moves mouse. Works INDEPENDENTLY of CursorMode. You can have tooltips without a visible cursor overlay, or a cursor overlay without tooltips. Setup: Cursor.PromptTracking = true; Cursor.PromptStyle = CursorPromptStyle.XYValues; (etc.) Cursor.PromptLocation = CursorPromptLocation.ToolTip; (etc.) === PromptLocation Options === Left(0) -- text in upper-left corner of chart Right(1) -- text in upper-right corner of chart ToolTip(2) -- standard Windows API tooltip popup (most common) Text(3) -- larger text overlay following mouse on chart For Pe3do (3D), ONLY Text location is supported. Font size controls differ by location: PeFont.SizeCursorPromptCntl -- adjusts Left/Right corner text (0.25-2.0) Cursor.FontSizeTrackingCntl -- adjusts Text location only (0.5-2.0) ToolTip location: font size controlled by Windows, not adjustable. === PromptStyle (what values to show) === None(0), XValue(1), YValue(2), XYValues(3), XYZValues(4), ZValue(5) For Pe3do (3D): only YValue and XYZValues produce output. Others are silently ignored (no error). XZ permutations make no sense in 3D. === CacheBmp2 and Colored Cursors === Default cursor uses legacy SetROP2 XOR drawing -- it inverts pixels on screen, producing no actual "color" (just inverted overlay). For colored cursor lines, enable the newer Direct2D drawing pipeline: PeConfigure.CacheBmp2 = true; // secondary screen buffer Cursor.DrawCursorToCache = true; // draw cursor to cache Cursor.CursorColor = Color.Red; // actual cursor color Cursor.VertLineType = LineAnnotationType.Dash; // line style Cursor.HorzLineType = LineAnnotationType.Dash; DrawCursorToCache auto-sets ImprovedCursor = true (not reverse). Use DrawCursorToCache -- it is the modern uniform property for both WinForms and WPF. ImprovedCursor is older, was WPF-only originally. CacheBmp2 is also required for Quick Annotations (see example 110). === Custom Tracking Tooltips (Event-Driven Content) === Setup requires ALL of: Cursor.PromptTracking = true; Cursor.PromptLocation = CursorPromptLocation.ToolTip; // or Text Cursor.TrackingCustomDataText = true; // fires PeCustomTrackingDataText Cursor.TrackingCustomOtherText = true; // fires PeCustomTrackingOtherText PeCustomTrackingDataText -- fires when mouse is over DATA area. PeCustomTrackingOtherText -- fires when mouse is over NON-DATA areas (titles, axes, legends, grid numbers). Requires matching HotSpot enables: HotSpot.Title, HotSpot.Subset, HotSpot.AxisLabel, etc. In handler: set e.TrackingText = "your string"; Use \n for multiline. Reading interpolated values (work even between data points): Cursor.CursorValueX, Cursor.CursorValueY, Cursor.CursorValueZ TrackingPromptTrigger dual-path pattern: if (Cursor.TrackingPromptTrigger == TrackingTrigger.MouseMove) // Mouse hover -- use ConvPixelToGraph for interpolated coords // or CursorValueX/Y for auto-interpolated values else // TrackingTrigger.CursorMove // Keyboard arrow moved cursor -- snapped to exact data point // Use Cursor.Subset / Cursor.Point to read actual Y data === Tooltip Styling (set inside event handler) === Cursor.TrackingTooltipTitle = "Bold Title"; // first line, bold Cursor.TrackingTooltipBkColor = Color.FromArgb(0, R, G, B); Cursor.TrackingTooltipTextColor = Color.FromArgb(0, R, G, B); Cursor.TrackingTooltipMaxWidth = 250; // pixel max width IMPORTANT: Alpha channel is IGNORED. Standard Windows tooltip UX does not support transparency. RGB(0,0,0) = black, not transparent. These properties PERSIST until changed again. Set them each time inside the handler if they need to vary (e.g. different colors for positive vs negative values as shown in example 105). === MouseCursorControl options === Cursor.MouseCursorControl = true; // click data point to move cursor Requires: HotSpot.Data = true; Cursor.MouseCursorControlClosestPoint = true; // click NEAR data point No need to hit exact hot spot -- snaps to closest point. === PeCursorMoved Event === Fires after cursor moves to a new data point (arrow keys or mouse click). Read: Cursor.Subset, Cursor.Point for current focus. Common pattern: update table annotations with data at focused point: int nX = chart.PeUserInterface.Cursor.Point; float val = chart.PeData.Y[subsetIndex, nX]; chart.PeAnnotation.Table.Text[row, col] = val.ToString(); chart.PeFunction.DrawTable(0); // efficient partial redraw === Pe3do (3D) Cursor Specifics === Pe3do has NO CursorMode overlay. No crosshair/line/square on 3D. Always use RenderEngine Direct3D for 3D charts. HighlightColor -- colors polygon under mouse (3D only): Cursor.HighlightColor = Color.FromArgb(255, 255, 0, 0); PromptLocation: only Text(3) is supported (not ToolTip). PromptStyle: only YValue(2) or XYZValues(4). In PeCustomTrackingDataText for 3D: Use GetHotSpot() to check ds.Type == HotSpotType.DataPoint Read PeData.Y[ds.Data1, ds.Data2] for actual data value Or Cursor.CursorValueY for interpolated surface value. === Cursor.Hand Property === Cursor.Hand = (int)MouseCursorStyles.Arrow; // override hotspot cursor Default is a pointing hand over hot spots. Set to Arrow or other style for different UX feel. Purely cosmetic, case-by-case. === Other Cursor Properties === Cursor.ProcessingMouseMove -- read-only bool, true when PE internal logic is processing mousemove. Check to avoid conflicts with custom MouseMove handlers (see example 032). Cursor.LastMouseMove -- read-only Point, last mouse position. Standard idiom for ConvPixelToGraph and GetRectGraph().Contains(). Cursor.PromptShorten -- when true, numeric values >9 digits switch to exponential notation in prompt string. Cursor.Zoom, Cursor.NoDrop, Cursor.SizeNS -- override mouse cursor styles during zoom, no-drop, and axis sizing operations.