# Copyright (c) 2025-2026 Gigasoft, Inc. All rights reserved. === ProEssentials Core Knowledge (knowledge rev 4.2) === ProEssentials is a .NET/C++ charting SDK with five chart objects. Each wraps a native Win32 DLL for high performance, exposed through a hierarchical .NET property interface. ALWAYS use pe_query.py to look up exact property paths, types, enum values, and method signatures before writing code. CHART OBJECTS (choose first, drives entire implementation): Pego -- Graph Object. Categorical/sequential X-axis. Bar, line, area, OHLC. X-axis labels via PointLabels array. Best for: dashboards, bar charts, financial OHLC, categorical data. Pesgo -- Scientific Graph Object. Continuous numeric X-axis. Scatter, line, area. Requires explicit X data array. Best for: scientific data, real-time streaming, XY scatter, time-series with irregular intervals. Pe3do -- 3D Scientific Graph. Surface plots, 3D scatter, wireframe, contour. Requires X, Y, Z data arrays. Pepso -- Polar/Smith Object. Polar coordinates, Smith charts, radar/spider plots. Pepco -- Pie Chart Object. Pie, doughnut, multi-ring charts. KEY ARCHITECTURAL CONCEPTS: 1) HIERARCHICAL PROPERTY INTERFACE All configuration is through nested property objects accessed from the chart: Pesgo1.PeData.___ (data arrays, counts, modes) Pesgo1.PePlot.___ (plotting method, visual options) Pesgo1.PeGrid.___ (axis scales, grid lines, zoom) Pesgo1.PeColor.___ (colors for all elements) Pesgo1.PeString.___ (labels, titles) Pesgo1.PeFont.___ (font sizing) Pesgo1.PeAnnotation.___ (line, graph, axis annotations) Pesgo1.PeUserInterface.___(interaction, cursors, hotspots, scrollbars) Pesgo1.PeConfigure.___ (rendering, prepare images, misc) Pesgo1.PeSpecial.___ (OHLC data, HObject handle, advanced) Pesgo1.PeFunction.___ (actions: reinitialize, print, zoom, export) Pesgo1.PeTable.___ (data table below chart) Pesgo1.PeLegend.___ (legend configuration) CRITICAL: Property NAMES within these groups are often abbreviated or shortened (e.g., the color for the desk area is PeColor.Desk, NOT PeColor.DeskColor). NEVER guess -- always query pe_query.py. 2) SUBSETS AND POINTS Data is organized as Subsets (series/lines) x Points (data values). Set PeData.Subsets and PeData.Points first, then populate PeData.Y[s,p]. Pego: X-axis is implicit (0,1,2...). Use PeString.PointLabels for labels. Pesgo: X-axis needs explicit PeData.X[s,p] values. 3) PROPERTY ARRAYS Large data arrays (Y, X, Z, SubsetColors, PointLabels, etc.) are special PropertyArray objects with methods like FastCopyFrom(), AppendData(), UseDataAtLocation(), BindData(). Use: pe_query.py methods "PeData.Y" ARRAY SIZE AND CONTROL: Property arrays are dynamic -- they grow as you set elements. Their size directly controls image construction behavior. Two categories exist: Empty by default (size=0): MultiAxesSubsets, OverlapMultiAxes, MultiAxesProportions, SubsetsToShow, SubsetsToLegend, Methods[]. These have NO effect when empty. They only activate when populated. Defaults defined (size>0): SubsetColors, SubsetLineTypes, SubsetPointTypes. These have pre-set values and work without explicit configuration. This distinction matters when reconfiguring a chart dynamically. An array that was populated must be explicitly cleared, otherwise old values persist. CLEARING ARRAYS: Use .Clear() to empty all elements in one call. Use .Clear(newSize) to trim. Essential when switching between chart modes or axis configurations: Pesgo1.PeGrid.MultiAxesSubsets.Clear(); // remove all axis assignments Pesgo1.PeGrid.OverlapMultiAxes.Clear(); Pesgo1.PeGrid.MultiAxesProportions.Clear(); Do NOT zero elements individually in a loop -- .Clear() is correct. INITIALIZING WITH A FILL VALUE: Initialize(value) fills the entire array with a scalar in one call. Useful to pre-fill data arrays with a null data sentinel before spoon-feeding: Pesgo1.PeData.Y.Initialize(-999f); // fill all with null value Set PeData.NullDataValue = -999 to match. See pe-nulldata. VIRTUAL LABELS: If PeString.PointLabels array is empty or has fewer items than PeData.Points, reading PointLabels[N] beyond the array range returns a string of "N+1" (e.g., PointLabels[0] returns "1", PointLabels[4] returns "5"). This auto-generation is called "VirtualLabels." It means the chart always has point labels even if none were explicitly set. GOTCHA: When building graph annotations (especially 3D polygon sequences), set the trailing annotation's Text = "" explicitly, otherwise VirtualLabels will produce unwanted numeric text at those annotation positions. 4) PER-DATAPOINT PROPERTIES vs GRAPH ANNOTATIONS PointColors and DataPointLabels are per-data-point properties tied to PeData.Y values -- they color or label individual Y data points within the chart's data model. PointColors is commonly used to color bars, points, or line segments based on data value, threshold, or category. DataPointLabels places custom text next to each data point. For scattered overlay items INDEPENDENT of chart data (markers, callouts, reference dots, icons), use PeAnnotation.Graph instead. Graph annotations are positioned at arbitrary X,Y coordinates and are not tied to subsets. Rule of thumb: coloring/labeling data --> PointColors/DataPointLabels. Overlay decorations independent of data --> GraphAnnotations. 5) RENDERING PIPELINE PeConfigure.CacheBmp = true; -- ALWAYS SET on every chart. Caches rendered image in memory for flicker-free repainting. Without it, window overlap causes flicker. Direct2D/Direct3D RenderEngines force it true automatically. PeFunction.ReinitializeResetImage() -- full rebuild (data + image) PeFunction.ResetImage(0,0) -- image only rebuild (after visual changes) PeFunction.ReinitializeResetImage() is the standard refresh after data changes. PeFunction.Reinitialize() -- lighter rebuild (axis/layout only, no image reset). Use when changing ManualScaleControl or axis limits without data changes. Follow with Invalidate(). See pe-pe3do-patterns for details. PeData.ComputeShader = true -- enables GPU-side Direct3D construction on Pego, Pesgo, and Pe3do (RenderEngine.Direct3D required). Best for real-time and large datasets. See pe-pesgo-patterns and pe-pe3do-patterns for supported plotting methods, line type implications, and tuning. 6) BACKGROUND BITMAPS (all chart objects) Place a bitmap image behind the chart with three steps: a) PeColor.BitmapGradientMode = true; // MUST be set first b) PeColor.DeskBmpFilename = "path/to/image.jpg"; // desk area bitmap c) PeColor.DeskBmpStyle = BitmapStyle.StretchBlt; // large images PeColor.DeskBmpStyle = BitmapStyle.TiledBitBlt; // small/tileable images To see bitmap through graph area, make graph backgrounds transparent: PeColor.GraphBackground = Color.FromArgb(0,1,0,0); // PE "empty" color PeColor.GraphGradientStyle = GradientStyle.NoGradient; With multi-axis: set transparent background per axis via WorkingAxis loop. PE "empty" color convention: Color.FromArgb(0,1,0,0) means transparent/empty. Also available: GraphBmpFilename (graph area only), TableBmpFilename (table). DeskBmpOpacity (0-100) controls bitmap translucency. Query: pe_query.py search "BmpFilename" 7) ENUM-DRIVEN CONFIGURATION Most behavioral settings use enums. Never hardcode integer values. Query: pe_query.py enum "GraphPlottingMethod" Key enums: GraphPlottingMethod, SGraphPlottingMethod, ManualScaleControl, ViewingStyle, QuickStyle, RenderEngine, AllowZooming, MultiAxisStyle, DataShadows, CursorMode, CursorPromptStyle, MouseWheelFunction. CRITICAL -- PePlot.Method ENUM DIFFERS BY CHART OBJECT: The query tool reports PePlot.Method as type "GraphPlottingMethod" generically, but EACH chart object uses a DIFFERENT enum with DIFFERENT integer values. Using the wrong enum compiles but produces WRONG plotting at runtime. Pego --> GraphPlottingMethod (27 values, Point=2) Pesgo --> SGraphPlottingMethod (26 values, Point=1) Pepso --> PSGraphPlottingMethod (4 values: Line=0, Point=1, PointsPlusLine=2, Area=3) Pe3do --> ThreeDGraphPlottingMethod (5 values: Zero..Four, controls rendering quality) Pepco --> No PePlot.Method (pie charts have no plotting method enum) ALWAYS select the enum matching the chart object. Verify via base examples: Base 000: Pego1.PePlot.Method = GraphPlottingMethod.Area; Base 100: Pesgo1.PePlot.Method = SGraphPlottingMethod.PointsPlusSpline; Base 200: Pepso1.PePlot.Method = PSGraphPlottingMethod.PointsPlusLine; Base 400: Pe3do1.PePlot.Method = ThreeDGraphPlottingMethod.Zero; 8) APPLIES-TO FILTERING Properties apply to specific chart objects. pe_query.py shows this as Pg|Sg|3D|Po|Pi codes. A property that shows "Pg|Sg" works on Pego and Pesgo but not Pe3do, Pepso, or Pepco. 9) THREE API LAYERS (interchangeable) .NET: Pesgo1.PeData.Subsets = 5; DLL: PEnset(hObject, PEP_nSUBSETS, 5); VBA: Pego1.Subsets = 5 All three access the same engine. .NET is standard for C#/VB. DLL is used for MFC, special cases, or C++ native. .NET PeSpecial.HObject provides the DLL handle. VBA OCX Pego1.hObject provides DLL handle. C++ DLL REFERENCE: For MFC/Win32 C++ code, see pe-cpp-api-reference (~17K tokens, add only when writing pure DLL C++ code) for all PEP_ property constants, PEGAT_ annotation types, enum constants (PEMSC_*, PEQS_*, etc.), DLL function signatures, type prefix conventions, and the PERGB color macro. KEY RULE: 'a' in PEP_ prefix = array = use PEvsetcell. No 'a' = scalar = use PEnset. The .NET enum names do NOT match C++ constant names -- e.g., GraphAnnotationType.TopLeft is PEGAT_TOPLEFT. ALWAYS look up exact constants before writing DLL code. HELP FILE NAMING: HTM help files are named by the C++ property constant. Example: PEP_nSUBSETS -> PEP_nSUBSETS.htm in the help system. 10) LICENSING / EVAL NAG STRING Customers receive a serial number and matching key array (16 integers). The key must be applied via PEvsetW BEFORE any image render or WM_PAINT: int[] keys = { /* 16 integers from license */ }; Gigasoft.ProEssentials.Api.PEvsetW( Pesgo1.PeSpecial.HObject, 1798, keys, 16); // 64 bytes COMMON ISSUE: "Why does the eval string still show after installing with my serial number?" a) Key code must execute early -- before the chart renders its first image. If the chart receives WM_PAINT before the key is set, the eval nag persists for that session. b) If PeFunction.Reset / PEreset is called, the key must be re-applied immediately after the reset. In demo projects, add the PEvsetW key code just after PeFunction.Reset in the CreateAllChart functions (Form2, Form3, Form4, Form5, Form6). C++ DLL equivalent: int keys[] = { /* 16 integers */ }; PEvset(hObject, 1798, keys, 16); 10) OCX/VBA API LAYER (third interface, distinct from .NET and DLL) ActiveX/VCL users call methods directly on the control object. These have their own signatures, separate from .NET PeFunction.* equivalents: VBA method call: iPego1.GetRectGraph nLeft, nTop, nRight, nBottom .NET equivalent: Pego1.PeFunction.GetRectGraph(ref nL, ref nT, ref nR, ref nB) DLL equivalent: PExxx or no direct DLL equivalent in some cases uses PEvget & PEP_rectGRAPH VBA PROPERTY SYNTAX uses OCX constants, not .NET enum names: .NET: Pego1.PePlot.Method = GraphPlottingMethod.Point VBA: iPego1.PlottingMethod = GPM_POINT .NET: Pego1.PeUserInterface.Cursor.Mode = CursorMode.DataCross VBA: iPego1.CursorMode = PECM_DATACROSS The OCX constant names (PEQS_*, PECM_*, PEGAT_*, PELT_*, etc.) match the DLL PEP_ values but use shorter prefixes. NEVER use .NET enum names in VBA. SCOPE CONSTRAINT: OCX methods are not universal across all 5 chart objects. Unlike .NET properties that show appliesTo, OCX method scope is fixed: All 5 objects: GetLastMouseMove, GetHotSpotData, PEreinitialize, PEresetimage, PEcopy*, PElaunch*, PEprint*, PEdrawtable, GetRectTA Pego/Pesgo/Pepso: GetRectGraph, PEconvpixeltograph, PEpartialresetimage, GetRectAxis, GetGraphLoc Pego/Pesgo only: GetExtraAxisX, GetFallDayLight, SetFallDayLight Pe3do only: DxSetLight, DxGetLight 116 VBA examples are available (one per C#/C++ example, same example IDs). Access via: pe_query.py example --lang vba VBA examples show OCX method calls, event handlers, and constant usage reflecting real working code from the ProEssentials demo application. WORKFLOW FOR WRITING CODE: 1. Choose chart object based on use case 2. Read relevant knowledge files for conceptual understanding 3. Query pe_query.py for EVERY property path, enum, and method 4. Use pe_query.py validate to verify all paths before final code 5. Query pe_query.py examples to find similar working examples