tune
This commit is contained in:
+835
@@ -0,0 +1,835 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Building Your Own Rendering Canvas | HiAPI-C# 2025 </title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="title" content="Building Your Own Rendering Canvas | HiAPI-C# 2025 ">
|
||||
|
||||
|
||||
<link rel="icon" href="../../../../../img/HiAPI.favicon.ico">
|
||||
<link rel="stylesheet" href="../../../../../public/docfx.min.css">
|
||||
<link rel="stylesheet" href="../../../../../public/main.css">
|
||||
<meta name="docfx:navrel" content="../../../../../toc.html">
|
||||
<meta name="docfx:tocrel" content="../../../toc.html">
|
||||
|
||||
<meta name="docfx:rel" content="../../../../../">
|
||||
|
||||
|
||||
|
||||
<meta name="loc:inThisArticle" content="In this article">
|
||||
<meta name="loc:searchResultsCount" content="{count} results for "{query}"">
|
||||
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
||||
<meta name="loc:tocFilter" content="Filter by title">
|
||||
<meta name="loc:nextArticle" content="Next">
|
||||
<meta name="loc:prevArticle" content="Previous">
|
||||
<meta name="loc:themeLight" content="Light">
|
||||
<meta name="loc:themeDark" content="Dark">
|
||||
<meta name="loc:themeAuto" content="Auto">
|
||||
<meta name="loc:changeTheme" content="Change theme">
|
||||
<meta name="loc:copy" content="Copy">
|
||||
<meta name="loc:downloadPdf" content="Download PDF">
|
||||
|
||||
<script type="module" src="./../../../../../public/docfx.min.js"></script>
|
||||
|
||||
<script>
|
||||
const theme = localStorage.getItem('theme') || 'auto'
|
||||
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
|
||||
<header class="bg-body border-bottom">
|
||||
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
|
||||
<div class="container-xxl flex-nowrap">
|
||||
<a class="navbar-brand" href="../../../../../index.html">
|
||||
<img id="logo" class="svg" src="../../../../../img/HiAPI.logo.png" alt="">
|
||||
|
||||
</a>
|
||||
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<i class="bi bi-three-dots"></i>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navpanel">
|
||||
<div id="navbar">
|
||||
<form class="search" role="search" id="search">
|
||||
<i class="bi bi-search"></i>
|
||||
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="container-xxl">
|
||||
<div class="toc-offcanvas">
|
||||
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<nav class="toc" id="toc"></nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="actionbar">
|
||||
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
|
||||
<i class="bi bi-list"></i>
|
||||
</button>
|
||||
|
||||
<nav id="breadcrumb"></nav>
|
||||
</div>
|
||||
|
||||
<article data-uid="">
|
||||
<h1 id="building-your-own-rendering-canvas">Building Your Own Rendering Canvas</h1>
|
||||
|
||||
<p>This guide provides detailed implementation information for creating your own <code>RenderingCanvas</code> using the <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a>. By understanding these implementation details, you can customize the rendering component for specific application needs or create implementations for other UI frameworks.</p>
|
||||
<div class="NOTE">
|
||||
<h5>Note</h5>
|
||||
<p><strong>For Windows Applications</strong>: If you are developing for Windows systems, it is recommended to directly use the existing <code>RenderingCanvas</code> implementations in the <code>Hi.WinForm</code> or <code>Hi.Wpf</code> packages, rather than creating your own. These implementations are fully tested, optimized, and maintained.
|
||||
<strong>For Webapi Applications</strong>: Using <code>Hi.Webapi</code>.</p>
|
||||
<p>The implementation details provided in this document are primarily for educational purposes or for developers who need to port RenderingCanvas to other platforms/frameworks.</p>
|
||||
</div>
|
||||
<h2 id="basic-dispengine-usage">Basic DispEngine Usage</h2>
|
||||
<p>The <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> is designed to display objects that implement the <a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a> interface. This is the fundamental purpose of DispEngine - to render displayable objects. Assign <a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a> to <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a>.<a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_Displayee">Displayee</a>.</p>
|
||||
<h2 id="core-implementation-pattern">Core Implementation Pattern</h2>
|
||||
<p>When implementing a custom <code>RenderingCanvas</code> for a UI platform, follow these key steps:</p>
|
||||
<ol>
|
||||
<li><strong>Initialize UI Component</strong> - Set up the UI control properties and event handling</li>
|
||||
<li><strong>Configure DispEngine</strong> - Create and properly initialize the <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> instance</li>
|
||||
<li><strong>Set Up Rendering Pipeline</strong> - Implement buffer swapping mechanism for visualization</li>
|
||||
<li><strong>Handle User Input</strong> - Map platform-specific input events to DispEngine methods</li>
|
||||
<li><strong>Manage Component Lifecycle</strong> - Ensure proper resource management and cleanup</li>
|
||||
</ol>
|
||||
<p>Let's examine the actual implementations in WinForm and WPF frameworks to understand these patterns in practice.</p>
|
||||
<h2 id="winform-implementation-details">WinForm Implementation Details</h2>
|
||||
<p>The WinForm implementation in <code>Hi.WinForm</code> combines Windows Forms controls with the <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> rendering system.</p>
|
||||
<h3 id="core-properties-and-fields">Core Properties and Fields</h3>
|
||||
<p>Here are the essential properties and fields defined in the WinForm implementation:</p>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// <see cref="DispEngine"/>.
|
||||
/// </summary>
|
||||
public DispEngine DispEngine { get; }
|
||||
|
||||
// Constants and structures for WM_TOUCH
|
||||
private const int WM_TOUCH = 0x0240;
|
||||
private const int TOUCHEVENTF_MOVE = 0x0001;
|
||||
private const int TOUCHEVENTF_DOWN = 0x0002;
|
||||
private const int TOUCHEVENTF_UP = 0x0004;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct TOUCHINPUT
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
public IntPtr hSource;
|
||||
public int dwID;
|
||||
public int dwFlags;
|
||||
public int dwMask;
|
||||
public int dwTime;
|
||||
public IntPtr dwExtraInfo;
|
||||
public int cxContact;
|
||||
public int cyContact;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool RegisterTouchWindow(IntPtr hWnd, uint ulFlags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetTouchInputInfo(IntPtr hTouchInput, int cInputs, [In, Out] TOUCHINPUT[] pInputs, int cbSize);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern void CloseTouchInputHandle(IntPtr lParam);
|
||||
</code></pre><h3 id="initialization">Initialization</h3>
|
||||
<p>The initialization code sets up event handlers and creates the DispEngine:</p>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// Ctor.
|
||||
/// </summary>
|
||||
/// <param name="displayees">displayees</param>
|
||||
public unsafe RenderingCanvas(params IDisplayee[] displayees)
|
||||
{
|
||||
// Configure the control's visual styles
|
||||
SetStyle(ControlStyles.Selectable, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
|
||||
SetStyle(ControlStyles.ContainerControl, false);
|
||||
SetStyle(ControlStyles.ResizeRedraw, false);
|
||||
DoubleBuffered = true;
|
||||
|
||||
InitializeComponent();
|
||||
Dock = DockStyle.Fill;
|
||||
|
||||
// Connect event handlers for user input and window events
|
||||
this.Resize += RenderingCanvas_Resize;
|
||||
this.VisibleChanged += RenderingCanvas_VisibleChanged;
|
||||
this.MouseMove += RenderingCanvas_MouseMove;
|
||||
this.MouseDown += RenderingCanvas_MouseDown;
|
||||
this.MouseUp += RenderingCanvas_MouseUp;
|
||||
this.MouseWheel += RenderingCanvas_MouseWheel;
|
||||
this.KeyDown += RenderingCanvas_KeyDown;
|
||||
this.KeyUp += RenderingCanvas_KeyUp;
|
||||
|
||||
// Add focus event handler
|
||||
this.GotFocus += RenderingCanvas_GotFocus;
|
||||
this.HandleCreated += OnHandleCreated;
|
||||
|
||||
// Enable touch input and click events for the control
|
||||
this.SetStyle(ControlStyles.StandardClick, true);
|
||||
this.SetStyle(ControlStyles.StandardDoubleClick, true);
|
||||
this.TabStop = true;
|
||||
|
||||
// Initialize the DispEngine with provided displayees
|
||||
DispEngine = new DispEngine(displayees);
|
||||
DispEngine.BackgroundColor = new Vec3d(0.1, 0.1, 0.5);
|
||||
DispEngine.BackgroundOpacity = 0.1;
|
||||
DispEngine.SetViewToHomeView();
|
||||
DispEngine.ImageRequestAfterBufferSwapped += DispEngine_ImageRequestAfterBufferSwapped;
|
||||
|
||||
// Set initial size and start the rendering engine
|
||||
this.Size = new System.Drawing.Size(500, 300);
|
||||
DispEngine.Start(this.ClientSize.Width, this.ClientSize.Height);
|
||||
}
|
||||
</code></pre><h3 id="rendering-pipeline">Rendering Pipeline</h3>
|
||||
<p>The rendering pipeline processes images from DispEngine and displays them:</p>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">private unsafe void DispEngine_ImageRequestAfterBufferSwapped(byte* bgra_unsignedbyte_pixels, int w, int h)
|
||||
{
|
||||
// Create a bitmap from the raw pixel data provided by DispEngine
|
||||
Bitmap bitmap;
|
||||
bitmap = new Bitmap(new Bitmap(w, h, w * 4,
|
||||
PixelFormat.Format32bppArgb, new IntPtr(bgra_unsignedbyte_pixels)));
|
||||
|
||||
// Update the background image and dispose the previous one
|
||||
Image pre = this.BackgroundImage;
|
||||
this.BackgroundImage = bitmap;
|
||||
pre?.Dispose();
|
||||
}
|
||||
</code></pre><h3 id="input-handling">Input Handling</h3>
|
||||
<h4 id="windows-message-handling-for-touch">Windows Message Handling for Touch</h4>
|
||||
<p>WinForm implementation intercepts Windows touch messages and forwards them to DispEngine:</p>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">protected override void WndProc(ref Message m)
|
||||
{
|
||||
if (m.Msg == WM_TOUCH)
|
||||
{
|
||||
HandleTouchInput(m.WParam, m.LParam);
|
||||
return;
|
||||
}
|
||||
|
||||
base.WndProc(ref m);
|
||||
}
|
||||
|
||||
private void OnHandleCreated(object sender, EventArgs e)
|
||||
{
|
||||
// Register window to receive touch messages
|
||||
RegisterTouchWindow(this.Handle, 0);
|
||||
}
|
||||
|
||||
private void HandleTouchInput(IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
int inputCount = wParam.ToInt32();
|
||||
TOUCHINPUT[] inputs = new TOUCHINPUT[inputCount];
|
||||
|
||||
if (!GetTouchInputInfo(lParam, inputCount, inputs, Marshal.SizeOf(typeof(TOUCHINPUT))))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < inputCount; i++)
|
||||
{
|
||||
TOUCHINPUT ti = inputs[i];
|
||||
int touchId = ti.dwID;
|
||||
|
||||
// Convert touch coordinates to client coordinates
|
||||
Point touchPoint = PointToClient(new Point(ti.x / 100, ti.y / 100));
|
||||
|
||||
if ((ti.dwFlags & TOUCHEVENTF_DOWN) != 0)
|
||||
{
|
||||
// Touch down event
|
||||
DispEngine.TouchDown(touchId, touchPoint.X, touchPoint.Y);
|
||||
this.Focus();
|
||||
}
|
||||
else if ((ti.dwFlags & TOUCHEVENTF_MOVE) != 0)
|
||||
{
|
||||
// Touch move event
|
||||
DispEngine.TouchMove(touchId, touchPoint.X, touchPoint.Y);
|
||||
}
|
||||
else if ((ti.dwFlags & TOUCHEVENTF_UP) != 0)
|
||||
{
|
||||
// Touch up event
|
||||
DispEngine.TouchUp(touchId);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseTouchInputHandle(lParam);
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>The key aspect is mapping Windows touch events to DispEngine's touch API:</p>
|
||||
<pre><code class="lang-csharp">// Inside HandleTouchInput method
|
||||
if ((ti.dwFlags & TOUCHEVENTF_DOWN) != 0)
|
||||
{
|
||||
// Touch down event - delegate to DispEngine
|
||||
DispEngine.TouchDown(touchId, touchPoint.X, touchPoint.Y);
|
||||
this.Focus();
|
||||
}
|
||||
else if ((ti.dwFlags & TOUCHEVENTF_MOVE) != 0)
|
||||
{
|
||||
// Touch move event - delegate to DispEngine
|
||||
DispEngine.TouchMove(touchId, touchPoint.X, touchPoint.Y);
|
||||
}
|
||||
else if ((ti.dwFlags & TOUCHEVENTF_UP) != 0)
|
||||
{
|
||||
// Touch up event - delegate to DispEngine
|
||||
DispEngine.TouchUp(touchId);
|
||||
}
|
||||
</code></pre>
|
||||
<h4 id="mouse-events">Mouse Events</h4>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">private void RenderingCanvas_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
// Update mouse position and handle drag transforms
|
||||
DispEngine.MouseMove(e.Location.X, e.Location.Y);
|
||||
DispEngine.MouseDragTransform(e.Location.X, e.Location.Y,
|
||||
new mouse_button_table__transform_view_by_mouse_drag_t()
|
||||
{
|
||||
LEFT_BUTTON = (long)MouseButtons.Left,
|
||||
RIGHT_BUTTON = (long)MouseButtons.Right
|
||||
});
|
||||
}
|
||||
|
||||
private void RenderingCanvas_MouseDown(object sender, MouseEventArgs e)
|
||||
{
|
||||
// Handle mouse button press
|
||||
DispEngine.MouseButtonDown((long)e.Button);
|
||||
this.Focus();
|
||||
}
|
||||
|
||||
private void RenderingCanvas_MouseUp(object sender, MouseEventArgs e)
|
||||
{
|
||||
// Handle mouse button release
|
||||
DispEngine.MouseButtonUp((long)e.Button);
|
||||
}
|
||||
|
||||
private void RenderingCanvas_MouseWheel(object sender, MouseEventArgs e)
|
||||
{
|
||||
// Handle mouse wheel for zoom operations
|
||||
DispEngine.MouseWheel(0, e.Delta / 120);
|
||||
DispEngine.MouseWheelTransform(0, e.Delta / 120);
|
||||
}
|
||||
</code></pre><h4 id="keyboard-events">Keyboard Events</h4>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <inheritdoc/>
|
||||
protected override bool IsInputKey(Keys keyData)
|
||||
{
|
||||
//since in default, arrow does not trigger key event(keyDown and keyUp).
|
||||
return true;
|
||||
}
|
||||
|
||||
private void RenderingCanvas_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
Focus();
|
||||
DispEngine.KeyDown((long)e.KeyData);
|
||||
|
||||
// Map specific keys for view transformation
|
||||
long key = (long)e.KeyData;
|
||||
if (key == (long)Keys.LShiftKey || key == (long)Keys.RShiftKey || key == (long)Keys.ShiftKey)
|
||||
key = (long)Keys.Shift;
|
||||
|
||||
DispEngine.KeyDownTransform(key, new key_table__transform_view_by_key_pressing_t()
|
||||
{
|
||||
HOME = (long)Keys.Home,
|
||||
PAGE_UP = (long)Keys.PageUp,
|
||||
PAGE_DOWN = (long)Keys.PageDown,
|
||||
F1 = (long)Keys.F1,
|
||||
F2 = (long)Keys.F2,
|
||||
F3 = (long)Keys.F3,
|
||||
F4 = (long)Keys.F4,
|
||||
SHIFT = (long)Keys.Shift,
|
||||
ARROW_LEFT = (long)Keys.Left,
|
||||
ARROW_RIGHT = (long)Keys.Right,
|
||||
ARROW_DOWN = (long)Keys.Down,
|
||||
ARROW_UP = (long)Keys.Up
|
||||
});
|
||||
}
|
||||
|
||||
private void RenderingCanvas_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
DispEngine.KeyUp((long)e.KeyData);
|
||||
}
|
||||
</code></pre><h3 id="lifecycle-management">Lifecycle Management</h3>
|
||||
<p>Window event handling ensures proper state management:</p>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">private void RenderingCanvas_Resize(object sender, EventArgs e)
|
||||
{
|
||||
// Notify DispEngine of size changes
|
||||
DispEngine.Resize(this.ClientSize.Width, this.ClientSize.Height);
|
||||
}
|
||||
|
||||
private void RenderingCanvas_VisibleChanged(object sender, EventArgs e)
|
||||
{
|
||||
// Update visibility state in DispEngine
|
||||
DispEngine.IsVisible = this.Visible;
|
||||
}
|
||||
</code></pre><h3 id="resource-cleanup">Resource Cleanup</h3>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
// Dispose the DispEngine to free resources
|
||||
DispEngine.Dispose();
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
</code></pre><h2 id="wpf-implementation-details">WPF Implementation Details</h2>
|
||||
<p>The WPF implementation uses WPF-specific controls and mechanisms but follows the same core pattern.</p>
|
||||
<h3 id="core-properties">Core Properties</h3>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// The DispEngine instance that handles rendering and user interactions
|
||||
/// </summary>
|
||||
public DispEngine DispEngine { get; } = new DispEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Internal container for rendering content
|
||||
/// </summary>
|
||||
private UserControl DisplayerPane { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary to store touch point information
|
||||
/// </summary>
|
||||
private Dictionary<int, Point> TouchingPointsMap { get; } = new Dictionary<int, Point>();
|
||||
|
||||
/// <summary>
|
||||
/// Dictionary to store previous positions of touch points
|
||||
/// </summary>
|
||||
private Dictionary<int, Point> PreviousTouchingPointsMap { get; } = new Dictionary<int, Point>();
|
||||
</code></pre><h3 id="initialization-1">Initialization</h3>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// Initializes a new instance of the RenderingCanvas
|
||||
/// </summary>
|
||||
public RenderingCanvas()
|
||||
{
|
||||
DispEngine.BackgroundColor = new Vec3d(0.1, 0.1, 0.5);
|
||||
DispEngine.BackgroundOpacity = 0.1;
|
||||
|
||||
// Configure the main control properties
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
VerticalAlignment = VerticalAlignment.Stretch;
|
||||
Focusable = true;
|
||||
KeyboardNavigation.SetDirectionalNavigation(this, KeyboardNavigationMode.Cycle);
|
||||
DataContextChanged += CanvasDataContextChanged;
|
||||
|
||||
// Create and configure the display pane
|
||||
DisplayerPane = new UserControl();
|
||||
DisplayerPane.HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
DisplayerPane.VerticalAlignment = VerticalAlignment.Stretch;
|
||||
DisplayerPane.Focusable = true;
|
||||
DisplayerPane.IsTabStop = true;
|
||||
|
||||
// Connect event handlers for user input and window events
|
||||
DisplayerPane.SizeChanged += RenderingCanvas_SizeChanged;
|
||||
DisplayerPane.MouseMove += RenderingCanvas_MouseMove;
|
||||
DisplayerPane.MouseDown += RenderingCanvas_MouseDown;
|
||||
DisplayerPane.MouseUp += RenderingCanvas_MouseUp;
|
||||
DisplayerPane.MouseWheel += RenderingCanvas_MouseWheel;
|
||||
DisplayerPane.KeyDown += RenderingCanvas_KeyDown;
|
||||
DisplayerPane.KeyUp += RenderingCanvas_KeyUp;
|
||||
DisplayerPane.Loaded += RenderingCanvas_Loaded;
|
||||
DisplayerPane.Unloaded += RenderingCanvas_Unloaded;
|
||||
DisplayerPane.IsVisibleChanged += DisplayerPane_IsVisibleChanged;
|
||||
|
||||
// Add touch event handlers
|
||||
DisplayerPane.TouchDown += RenderingCanvas_TouchDown;
|
||||
DisplayerPane.TouchMove += RenderingCanvas_TouchMove;
|
||||
DisplayerPane.TouchUp += RenderingCanvas_TouchUp;
|
||||
|
||||
// Enable touch support
|
||||
this.IsManipulationEnabled = true;
|
||||
|
||||
// Initialize power management
|
||||
InitializePowerManagement();
|
||||
|
||||
// Add the display pane to this control's content
|
||||
Content = DisplayerPane;
|
||||
}
|
||||
</code></pre><h3 id="rendering-pipeline-1">Rendering Pipeline</h3>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">private byte[] PreImageBgra { get; set; }
|
||||
/// <summary>
|
||||
/// Handles the buffer swapped event from DispEngine
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_BufferSwapped(byte* data, int w, int h)
|
||||
{
|
||||
if (data == null)
|
||||
return;
|
||||
|
||||
//since the treatment is different from Razor version,
|
||||
//the image checking mechanism cannot be set in DispEngine.
|
||||
Span<byte> bgra = new Span<byte>(data, w * h * 4);
|
||||
if (PreImageBgra != null && bgra.SequenceEqual(PreImageBgra))
|
||||
return;
|
||||
PreImageBgra = bgra.ToArray();
|
||||
|
||||
// Copy pixel data from DispEngine
|
||||
int n = w * h * 4;
|
||||
byte[] arr = new byte[n];
|
||||
for (int i = 0; i < n; i++)
|
||||
arr[i] = data[i];
|
||||
|
||||
// Update UI on the UI thread
|
||||
DisplayerPane.Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
BitmapSource bitmap = BitmapSource.Create(w, h, 1, 1, PixelFormats.Bgra32, null, arr, w * 4);
|
||||
DisplayerPane.Background = new ImageBrush(bitmap);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the size changed event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
// Notify DispEngine of size changes
|
||||
DispEngine.Resize((int)DisplayerPane.RenderSize.Width, (int)DisplayerPane.RenderSize.Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles visibility changes
|
||||
/// </summary>
|
||||
private unsafe void DisplayerPane_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// Update visibility state in DispEngine
|
||||
DispEngine.IsVisible = IsVisible;
|
||||
}
|
||||
</code></pre><h3 id="mouse-and-keyboard-handling">Mouse and Keyboard Handling</h3>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// Helper method to get mouse button mask
|
||||
/// </summary>
|
||||
internal static HiMouseButtonMask GetMouseButtonMask(MouseDevice device)
|
||||
{
|
||||
HiMouseButtonMask mouseButtonMask = 0;
|
||||
mouseButtonMask.SetLeftPressed(device.LeftButton == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetMiddlePressed(device.MiddleButton == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetRightPressed(device.RightButton == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetXButton1Pressed(device.XButton1 == MouseButtonState.Pressed);
|
||||
mouseButtonMask.SetXButton2Pressed(device.XButton2 == MouseButtonState.Pressed);
|
||||
return mouseButtonMask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse wheel event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
// Handle mouse wheel for zoom operations
|
||||
DispEngine.MouseWheel(0, e.Delta / 120);
|
||||
DispEngine.MouseWheelTransform(0, e.Delta / 120);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse up event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// Handle mouse button release
|
||||
DispEngine.MouseButtonUp((long)e.ChangedButton);
|
||||
(sender as UIElement)?.ReleaseMouseCapture();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse down event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
// Handle mouse button press
|
||||
DispEngine.MouseButtonDown((long)e.ChangedButton);
|
||||
DisplayerPane.Focus();
|
||||
(sender as UIElement)?.CaptureMouse();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the mouse move event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
// Update mouse position and handle drag transforms
|
||||
Point p = e.GetPosition(DisplayerPane);
|
||||
DispEngine.MouseMove((int)p.X, (int)p.Y);
|
||||
DispEngine.MouseDragTransform((int)p.X, (int)p.Y,
|
||||
new mouse_button_table__transform_view_by_mouse_drag_t()
|
||||
{
|
||||
LEFT_BUTTON = (long)MouseButton.Left,
|
||||
RIGHT_BUTTON = (long)MouseButton.Right
|
||||
});
|
||||
}
|
||||
</code></pre><pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// Handles the key up event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
DispEngine.KeyUp((long)e.Key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the key down event
|
||||
/// </summary>
|
||||
private void RenderingCanvas_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
DispEngine.KeyDown((long)e.Key);
|
||||
|
||||
// Map specific keys for view transformation
|
||||
long key = (long)e.Key;
|
||||
if (key == (long)Key.RightShift)
|
||||
key = (long)Key.LeftShift;
|
||||
|
||||
DispEngine.KeyDownTransform(key, new key_table__transform_view_by_key_pressing_t()
|
||||
{
|
||||
HOME = (long)Key.Home,
|
||||
PAGE_UP = (long)Key.PageUp,
|
||||
PAGE_DOWN = (long)Key.PageDown,
|
||||
F1 = (long)Key.F1,
|
||||
F2 = (long)Key.F2,
|
||||
F3 = (long)Key.F3,
|
||||
F4 = (long)Key.F4,
|
||||
SHIFT = (long)Key.LeftShift,
|
||||
ARROW_LEFT = (long)Key.Left,
|
||||
ARROW_RIGHT = (long)Key.Right,
|
||||
ARROW_DOWN = (long)Key.Down,
|
||||
ARROW_UP = (long)Key.Up
|
||||
});
|
||||
}
|
||||
</code></pre><h3 id="lifecycle-management-1">Lifecycle Management</h3>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// Handles window state changes (maximize, minimize, etc.)
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_StateChanged(object sender, EventArgs e)
|
||||
{
|
||||
switch ((sender as Window).WindowState)
|
||||
{
|
||||
case WindowState.Maximized:
|
||||
DispEngine.IsVisible = true;
|
||||
break;
|
||||
case WindowState.Minimized:
|
||||
DispEngine.IsVisible = false;
|
||||
break;
|
||||
case WindowState.Normal:
|
||||
DispEngine.IsVisible = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles data context changes
|
||||
/// </summary>
|
||||
private unsafe void CanvasDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
DispEngine pre = e.OldValue as DispEngine;
|
||||
DispEngine cur = e.NewValue as DispEngine;
|
||||
|
||||
//child's binding event is triggered after IsVisible event and Load event.
|
||||
if (pre != null) //this section will never occur if the datacontext not set twice.
|
||||
{
|
||||
pre.Terminate();
|
||||
pre.ImageRequestAfterBufferSwapped -= RenderingCanvas_BufferSwapped;
|
||||
}
|
||||
if (cur != null)
|
||||
{
|
||||
cur.ImageRequestAfterBufferSwapped += RenderingCanvas_BufferSwapped;
|
||||
cur.Start((int)DisplayerPane.RenderSize.Width, (int)DisplayerPane.RenderSize.Height);
|
||||
|
||||
cur.IsVisible = IsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the current window containing this control
|
||||
/// </summary>
|
||||
private Window currentWindow;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current window, connecting or disconnecting state change events
|
||||
/// </summary>
|
||||
Window CurrentWindow
|
||||
{
|
||||
get => currentWindow; set
|
||||
{
|
||||
if (currentWindow != null)
|
||||
currentWindow.StateChanged -= RenderingCanvas_StateChanged;
|
||||
currentWindow = value;
|
||||
if (currentWindow != null)
|
||||
currentWindow.StateChanged += RenderingCanvas_StateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the loaded event
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Get the window containing this control
|
||||
CurrentWindow = Window.GetWindow(this);
|
||||
|
||||
// Set up DispEngine rendering
|
||||
DispEngine.ImageRequestAfterBufferSwapped -= RenderingCanvas_BufferSwapped;
|
||||
DispEngine.ImageRequestAfterBufferSwapped += RenderingCanvas_BufferSwapped;
|
||||
DispEngine.Start((int)DisplayerPane.RenderSize.Width, (int)DisplayerPane.RenderSize.Height);
|
||||
DispEngine.IsVisible = IsVisible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the unloaded event
|
||||
/// </summary>
|
||||
private unsafe void RenderingCanvas_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DispEngine.IsVisible = IsVisible;
|
||||
DispEngine.ImageRequestAfterBufferSwapped -= RenderingCanvas_BufferSwapped;
|
||||
CurrentWindow = null;
|
||||
}
|
||||
</code></pre><h3 id="resource-cleanup-1">Resource Cleanup</h3>
|
||||
<pre><code class="lang-csharp" name="RenderingCanvas">/// <summary>
|
||||
/// Flag to track disposed state
|
||||
/// </summary>
|
||||
private bool disposedValue;
|
||||
|
||||
/// <summary>
|
||||
/// Disposes managed resources
|
||||
/// </summary>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposedValue)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Unsubscribe from power events
|
||||
SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
|
||||
|
||||
// Dispose the DispEngine to free resources
|
||||
DispEngine.Dispose();
|
||||
}
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public dispose method to free resources
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
</code></pre><h2 id="core-dispengine-integration-patterns">Core DispEngine Integration Patterns</h2>
|
||||
<h3 id="1-initialization-sequence">1. Initialization Sequence</h3>
|
||||
<pre><code class="lang-csharp">// Create DispEngine (optionally with displayees)
|
||||
var engine = new DispEngine(displayees);
|
||||
|
||||
// Set up image buffer callback
|
||||
engine.ImageRequestAfterBufferSwapped += OnBufferSwapped;
|
||||
|
||||
// Initialize with canvas size
|
||||
engine.Start(width, height);
|
||||
|
||||
// Set initial view (optional)
|
||||
engine.SetViewToHomeView();
|
||||
</code></pre>
|
||||
<h3 id="2-render-loop">2. Render Loop</h3>
|
||||
<p>The rendering process follows this pattern:</p>
|
||||
<ol>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> processes <a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a> objects</li>
|
||||
<li>Buffer is swapped and callback is triggered</li>
|
||||
<li>UI framework renders the buffer to screen</li>
|
||||
<li>User input triggers view updates</li>
|
||||
<li>Process repeats</li>
|
||||
</ol>
|
||||
<h3 id="3-complete-user-input-mapping">3. Complete User Input Mapping</h3>
|
||||
<p>All user interactions must be mapped to <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> methods:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>User Action</th>
|
||||
<th>DispEngine Method</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Mouse move</td>
|
||||
<td><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_MouseMove_System_Int32_System_Int32_">MouseMove(int, int)</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mouse drag</td>
|
||||
<td><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_MouseDragTransform_System_Int32_System_Int32_Hi_Native_mouse_button_table__transform_view_by_mouse_drag_t_">MouseDragTransform(int, int, mouse_button_table__transform_view_by_mouse_drag_t)</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mouse button</td>
|
||||
<td><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_MouseButtonDown_System_Int64_">MouseButtonDown(long)</a> / <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_MouseButtonUp_System_Int64_">MouseButtonUp(long)</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mouse wheel</td>
|
||||
<td><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_MouseWheel_System_Int32_System_Int32_">MouseWheel(int, int)</a> and <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_MouseWheelTransform_System_Int32_System_Int32_System_Double_">MouseWheelTransform(int, int, double)</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Key press</td>
|
||||
<td><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_KeyDown_System_Int64_">KeyDown(long)</a> / <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_KeyUp_System_Int64_">KeyUp(long)</a> and <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_KeyDownTransform_System_Int64_Hi_Native_key_table__transform_view_by_key_pressing_t_">KeyDownTransform(long, key_table__transform_view_by_key_pressing_t)</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Touch events</td>
|
||||
<td><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_TouchDown_System_Int32_System_Int32_System_Int32_">TouchDown(int, int, int)</a> / <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_TouchMove_System_Int32_System_Int32_System_Int32_">TouchMove(int, int, int)</a> / <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_TouchUp_System_Int32_">TouchUp(int)</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="4-proper-resource-cleanup">4. Proper Resource Cleanup</h3>
|
||||
<p>Resource management is critical for proper operation:</p>
|
||||
<pre><code class="lang-csharp">// In dispose method
|
||||
DispEngine.ImageRequestAfterBufferSwapped -= OnBufferSwapped;
|
||||
DispEngine.Terminate();
|
||||
DispEngine.Dispose();
|
||||
</code></pre>
|
||||
<h2 id="advanced-implementation-considerations">Advanced Implementation Considerations</h2>
|
||||
<p>When creating custom implementations, consider these aspects:</p>
|
||||
<h3 id="view-manipulation">View Manipulation</h3>
|
||||
<p>Use <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html#Hi_Disp_DispEngine_SketchView">SketchView</a> to directly access or modify the view matrix:</p>
|
||||
<pre><code class="lang-csharp">// Get current view matrix
|
||||
Mat4d currentView = engine.SketchView;
|
||||
|
||||
// Apply custom rotation
|
||||
Mat4d rotation = Mat4d.RotateX(Math.PI/4);
|
||||
engine.SketchView = currentView * rotation;
|
||||
</code></pre>
|
||||
<h2 id="see-also">See Also</h2>
|
||||
<ul>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a></li>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a></li>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Geom.Vec2d.html">Vec2d</a></li>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Geom.Mat4d.html">Mat4d</a></li>
|
||||
</ul>
|
||||
|
||||
</article>
|
||||
|
||||
<div class="contribution d-print-none">
|
||||
</div>
|
||||
|
||||
<div class="next-article d-print-none border-top" id="nextArticle"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="affix">
|
||||
<nav id="affix"></nav>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="container-xxl search-results" id="search-results"></div>
|
||||
|
||||
<footer class="border-top text-secondary">
|
||||
<div class="container-xxl">
|
||||
<div class="flex-fill">
|
||||
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,268 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Using RenderingCanvas with DispEngine | HiAPI-C# 2025 </title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="title" content="Using RenderingCanvas with DispEngine | HiAPI-C# 2025 ">
|
||||
|
||||
|
||||
<link rel="icon" href="../../../../../img/HiAPI.favicon.ico">
|
||||
<link rel="stylesheet" href="../../../../../public/docfx.min.css">
|
||||
<link rel="stylesheet" href="../../../../../public/main.css">
|
||||
<meta name="docfx:navrel" content="../../../../../toc.html">
|
||||
<meta name="docfx:tocrel" content="../../../toc.html">
|
||||
|
||||
<meta name="docfx:rel" content="../../../../../">
|
||||
|
||||
|
||||
|
||||
<meta name="loc:inThisArticle" content="In this article">
|
||||
<meta name="loc:searchResultsCount" content="{count} results for "{query}"">
|
||||
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
||||
<meta name="loc:tocFilter" content="Filter by title">
|
||||
<meta name="loc:nextArticle" content="Next">
|
||||
<meta name="loc:prevArticle" content="Previous">
|
||||
<meta name="loc:themeLight" content="Light">
|
||||
<meta name="loc:themeDark" content="Dark">
|
||||
<meta name="loc:themeAuto" content="Auto">
|
||||
<meta name="loc:changeTheme" content="Change theme">
|
||||
<meta name="loc:copy" content="Copy">
|
||||
<meta name="loc:downloadPdf" content="Download PDF">
|
||||
|
||||
<script type="module" src="./../../../../../public/docfx.min.js"></script>
|
||||
|
||||
<script>
|
||||
const theme = localStorage.getItem('theme') || 'auto'
|
||||
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
|
||||
<header class="bg-body border-bottom">
|
||||
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
|
||||
<div class="container-xxl flex-nowrap">
|
||||
<a class="navbar-brand" href="../../../../../index.html">
|
||||
<img id="logo" class="svg" src="../../../../../img/HiAPI.logo.png" alt="">
|
||||
|
||||
</a>
|
||||
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<i class="bi bi-three-dots"></i>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navpanel">
|
||||
<div id="navbar">
|
||||
<form class="search" role="search" id="search">
|
||||
<i class="bi bi-search"></i>
|
||||
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="container-xxl">
|
||||
<div class="toc-offcanvas">
|
||||
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<nav class="toc" id="toc"></nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="actionbar">
|
||||
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
|
||||
<i class="bi bi-list"></i>
|
||||
</button>
|
||||
|
||||
<nav id="breadcrumb"></nav>
|
||||
</div>
|
||||
|
||||
<article data-uid="">
|
||||
<h1 id="using-renderingcanvas-with-dispengine">Using RenderingCanvas with DispEngine</h1>
|
||||
|
||||
<p>The <code>RenderingCanvas</code> is the primary UI component for displaying and interacting with 3D content across different platforms. This section explains how to use it with the <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> to create cross-platform applications.</p>
|
||||
<h2 id="overview">Overview</h2>
|
||||
<p>The <code>RenderingCanvas</code> class is available in frameworks:</p>
|
||||
<ul>
|
||||
<li><code>Hi.WinForm</code> for Windows Forms applications</li>
|
||||
<li><code>Hi.Wpf</code> for WPF applications</li>
|
||||
<li><code>Hi.Webapi</code> for Webapi applications</li>
|
||||
</ul>
|
||||
<p>All implementations share a common architecture centered around the <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> class, enabling consistent rendering and interaction across platforms.</p>
|
||||
<h2 id="core-concept-dispengine-and-idisplayee">Core Concept: DispEngine and IDisplayee</h2>
|
||||
<p>At the heart of the rendering system is the relationship between <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> and <a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a>:</p>
|
||||
<ul>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a>: The rendering engine that manages the OpenGL context and handles user interaction</li>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a>: The interface that defines objects that can be rendered by the DispEngine</li>
|
||||
</ul>
|
||||
<p>This relationship is fundamental - <strong>the purpose of <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> is to render <a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a> objects</strong>.</p>
|
||||
<pre><code class="lang-mermaid">graph TD
|
||||
A[IDisplayee Objects] -->|Rendered by| B
|
||||
B[DispEngine] <--> C[RenderingCanvas UI Component]
|
||||
</code></pre>
|
||||
<h3 id="working-with-idisplayee">Working with IDisplayee</h3>
|
||||
<p>Objects implementing <a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a> define what gets rendered. Typically, you'll use <a class="xref" href="../../../../../api/Hi.Disp.Drawing.html">Drawing</a> objects or compose multiple IDisplayee objects together:</p>
|
||||
<pre><code class="lang-csharp">// Create a composite displayee
|
||||
public class MyCompositeDisplayee : IDisplayee
|
||||
{
|
||||
private List<IDisplayee> _displayees = new List<IDisplayee>();
|
||||
|
||||
public MyCompositeDisplayee()
|
||||
{
|
||||
// Add various displayees
|
||||
_displayees.Add(new AxesDisplayee());
|
||||
_displayees.Add(new ModelDisplayee());
|
||||
}
|
||||
|
||||
public void Display(Bind bind)
|
||||
{
|
||||
// Render all contained displayees
|
||||
foreach (var displayee in _displayees)
|
||||
{
|
||||
displayee.Display(bind);
|
||||
}
|
||||
}
|
||||
|
||||
public void ExpandToBox3d(Box3d box)
|
||||
{
|
||||
// Update bounding box based on all displayees
|
||||
foreach (var displayee in _displayees)
|
||||
{
|
||||
displayee.ExpandToBox3d(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<p>For more detailed information on creating displayees with <a class="xref" href="../../../../../api/Hi.Disp.Drawing.html">Drawing</a>, see the <a href="../drawing/index.html">Drawing</a> section.</p>
|
||||
<h2 id="basic-usage">Basic Usage</h2>
|
||||
<h3 id="apply-hiwinform">Apply Hi.WinForm</h3>
|
||||
<pre><code class="lang-csharp">// Create a new instance with displayee objects
|
||||
using Hi.WinForm.Disp;
|
||||
|
||||
// Create displayee object
|
||||
var displayee = new MyCompositeDisplayee();
|
||||
|
||||
// Initialize canvas with the displayee
|
||||
var canvas = new RenderingCanvas(displayee);
|
||||
|
||||
// Access the DispEngine for direct manipulation
|
||||
DispEngine engine = canvas.DispEngine;
|
||||
|
||||
// Add to a form
|
||||
myForm.Controls.Add(canvas);
|
||||
</code></pre>
|
||||
<h3 id="apply-hiwpf">Apply Hi.WPF</h3>
|
||||
<pre><code class="lang-csharp">// Create a new instance
|
||||
using Hi.Wpf.Disp;
|
||||
|
||||
// Create displayee object
|
||||
var displayee = new MyCompositeDisplayee();
|
||||
|
||||
// Initialize the canvas
|
||||
var canvas = new RenderingCanvas();
|
||||
|
||||
// Set displayee objects through the DispEngine
|
||||
canvas.DispEngine.Displayee = displayee;
|
||||
|
||||
// Add to a container
|
||||
myGrid.Children.Add(canvas);
|
||||
</code></pre>
|
||||
<h2 id="apply-hiwebapi">Apply Hi.Webapi</h2>
|
||||
<p>See <a href="webapi-rendering-canvas.html">Using Rendering Canvas By Hi.Webapi</a>.</p>
|
||||
<h2 id="switching-displayees-at-runtime">Switching Displayees at Runtime</h2>
|
||||
<p>You can dynamically change what's being displayed:</p>
|
||||
<pre><code class="lang-csharp">// Switch to a different displayee
|
||||
renderingCanvas.DispEngine.Displayee = alternativeDisplayee;
|
||||
|
||||
// Or update a DispList
|
||||
var displayList = new DispList();
|
||||
if (showModel) displayList.Add(modelDisplayee);
|
||||
if (showGrid) displayList.Add(gridDisplayee);
|
||||
renderingCanvas.DispEngine.Displayee = displayList;
|
||||
</code></pre>
|
||||
<h2 id="key-features-of-dispengine">Key Features of DispEngine</h2>
|
||||
<p>The <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> provides cross-platform support for:</p>
|
||||
<ul>
|
||||
<li>Handles buffer swapping and image generation</li>
|
||||
<li>Mouse/pointer events</li>
|
||||
<li>Keyboard navigation</li>
|
||||
<li>Touch gestures</li>
|
||||
<li>Zoom, pan, and rotate operations</li>
|
||||
<li>Resize and Visibility changed.</li>
|
||||
<li>Camera positioning and orientation</li>
|
||||
<li>Standard views (front, top, isometric, etc.)</li>
|
||||
<li>Renders <a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a> implementations</li>
|
||||
</ul>
|
||||
<h2 id="touch-and-gesture-support">Touch and Gesture Support</h2>
|
||||
<p>The <a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a> centralizes touch handling across all platforms with a unified API that supports:</p>
|
||||
<ul>
|
||||
<li>Single-finger pan</li>
|
||||
<li>Two-finger rotate and scale</li>
|
||||
<li>Multi-finger specialized operations</li>
|
||||
</ul>
|
||||
<p>The touch API is designed to be simple for UI implementations to use. Platform-specific UI components only need to capture touch events and forward them to the DispEngine.</p>
|
||||
<h2 id="common-operations">Common Operations</h2>
|
||||
<pre><code class="lang-csharp">// Accessing DispEngine (works on all platforms)
|
||||
var engine = renderingCanvas.DispEngine;
|
||||
|
||||
// Set to standard views
|
||||
engine.SetViewToHomeView();
|
||||
engine.SetViewToFrontView();
|
||||
|
||||
// Manual camera manipulation
|
||||
engine.Translate(dx, dy);
|
||||
engine.Rotate(deltaX, deltaY);
|
||||
|
||||
// Resize handling
|
||||
engine.Resize(width, height);
|
||||
</code></pre>
|
||||
<h2 id="implementation-details">Implementation Details</h2>
|
||||
<p>For detailed implementation information, including:</p>
|
||||
<ul>
|
||||
<li>Full source code examples</li>
|
||||
<li>Implementation details for each platform</li>
|
||||
<li>Advanced touch handling</li>
|
||||
<li>Custom implementation guidance</li>
|
||||
</ul>
|
||||
<p>See the <a href="custom-implementation.html">Building Your Own RenderingCanvas</a> guide.</p>
|
||||
<h2 id="see-also">See Also</h2>
|
||||
<ul>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.DispEngine.html">DispEngine</a></li>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a></li>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.DispList.html">DispList</a></li>
|
||||
<li><a class="xref" href="../../../../../api/Hi.Disp.Drawing.html">Drawing</a></li>
|
||||
<li><a href="custom-implementation.html">Building Your Own RenderingCanvas</a></li>
|
||||
</ul>
|
||||
|
||||
</article>
|
||||
|
||||
<div class="contribution d-print-none">
|
||||
</div>
|
||||
|
||||
<div class="next-article d-print-none border-top" id="nextArticle"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="affix">
|
||||
<nav id="affix"></nav>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="container-xxl search-results" id="search-results"></div>
|
||||
|
||||
<footer class="border-top text-secondary">
|
||||
<div class="container-xxl">
|
||||
<div class="flex-fill">
|
||||
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Using Rendering Canvas By Hi.Webapi | HiAPI-C# 2025 </title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="title" content="Using Rendering Canvas By Hi.Webapi | HiAPI-C# 2025 ">
|
||||
|
||||
|
||||
<link rel="icon" href="../../../../../img/HiAPI.favicon.ico">
|
||||
<link rel="stylesheet" href="../../../../../public/docfx.min.css">
|
||||
<link rel="stylesheet" href="../../../../../public/main.css">
|
||||
<meta name="docfx:navrel" content="../../../../../toc.html">
|
||||
<meta name="docfx:tocrel" content="../../../toc.html">
|
||||
|
||||
<meta name="docfx:rel" content="../../../../../">
|
||||
|
||||
|
||||
|
||||
<meta name="loc:inThisArticle" content="In this article">
|
||||
<meta name="loc:searchResultsCount" content="{count} results for "{query}"">
|
||||
<meta name="loc:searchNoResults" content="No results for "{query}"">
|
||||
<meta name="loc:tocFilter" content="Filter by title">
|
||||
<meta name="loc:nextArticle" content="Next">
|
||||
<meta name="loc:prevArticle" content="Previous">
|
||||
<meta name="loc:themeLight" content="Light">
|
||||
<meta name="loc:themeDark" content="Dark">
|
||||
<meta name="loc:themeAuto" content="Auto">
|
||||
<meta name="loc:changeTheme" content="Change theme">
|
||||
<meta name="loc:copy" content="Copy">
|
||||
<meta name="loc:downloadPdf" content="Download PDF">
|
||||
|
||||
<script type="module" src="./../../../../../public/docfx.min.js"></script>
|
||||
|
||||
<script>
|
||||
const theme = localStorage.getItem('theme') || 'auto'
|
||||
document.documentElement.setAttribute('data-bs-theme', theme === 'auto' ? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : theme)
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="tex2jax_ignore" data-layout="" data-yaml-mime="">
|
||||
<header class="bg-body border-bottom">
|
||||
<nav id="autocollapse" class="navbar navbar-expand-md" role="navigation">
|
||||
<div class="container-xxl flex-nowrap">
|
||||
<a class="navbar-brand" href="../../../../../index.html">
|
||||
<img id="logo" class="svg" src="../../../../../img/HiAPI.logo.png" alt="">
|
||||
|
||||
</a>
|
||||
<button class="btn btn-lg d-md-none border-0" type="button" data-bs-toggle="collapse" data-bs-target="#navpanel" aria-controls="navpanel" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<i class="bi bi-three-dots"></i>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navpanel">
|
||||
<div id="navbar">
|
||||
<form class="search" role="search" id="search">
|
||||
<i class="bi bi-search"></i>
|
||||
<input class="form-control" id="search-query" type="search" disabled placeholder="Search" autocomplete="off" aria-label="Search">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="container-xxl">
|
||||
<div class="toc-offcanvas">
|
||||
<div class="offcanvas-md offcanvas-start" tabindex="-1" id="tocOffcanvas" aria-labelledby="tocOffcanvasLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="tocOffcanvasLabel">Table of Contents</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" data-bs-target="#tocOffcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<nav class="toc" id="toc"></nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="actionbar">
|
||||
<button class="btn btn-lg border-0 d-md-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#tocOffcanvas" aria-controls="tocOffcanvas" aria-expanded="false" aria-label="Show table of contents">
|
||||
<i class="bi bi-list"></i>
|
||||
</button>
|
||||
|
||||
<nav id="breadcrumb"></nav>
|
||||
</div>
|
||||
|
||||
<article data-uid="">
|
||||
<h1 id="using-rendering-canvas-by-hiwebapi">Using Rendering Canvas By Hi.Webapi</h1>
|
||||
|
||||
<p>Hi.Webapi git repo:</p>
|
||||
<p>The Rendering Canvas implementation is located on the Hi.Webapi project (See<a href="../../../index.html">HiAPI Overview</a> to get git repository):</p>
|
||||
<ul>
|
||||
<li>wwwroot/disp/rendering-canvas.js
|
||||
<ul>
|
||||
<li>Pure js implementation.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>wwwroot/disp/rendering-canvas-vue.js
|
||||
<ul>
|
||||
<li>vue implementation.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>wwwroot/disp/rendering-canvas.css</li>
|
||||
</ul>
|
||||
<h2 id="usage-demonstration-by-hisamplewebapi-project">Usage Demonstration by Hi.Sample.Webapi Project</h2>
|
||||
<p>The usage is illustrated by the sample code in Hi.Sample.Webapi project (See<a href="../../../index.html">HiAPI Overview</a> to get git repository).</p>
|
||||
<p>The project applies Hi.Webapi nuget package (See<a href="../../../index.html">HiAPI Overview</a> to get git repository).</p>
|
||||
<p>Following pathes are based on the Hi.Sample.Webapi project.</p>
|
||||
<ul>
|
||||
<li>A sample GUI to controll the rendering view
|
||||
<ul>
|
||||
<li>wwwroot/disp/rendering-canvas-view-dropdown.js</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Set Rendering Content (<a class="xref" href="../../../../../api/Hi.Disp.IDisplayee.html">IDisplayee</a>) to the Rendering Canvas
|
||||
<ul>
|
||||
<li>Controllers/RenderingController.cs</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<h2 id="component-usage">Component Usage</h2>
|
||||
<ul>
|
||||
<li>wwwroot/demo.html
|
||||
<ul>
|
||||
<li>apply rendering-canvas.js from Hi.Webapi package.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>wwwroot/demo-vue.html
|
||||
<ul>
|
||||
<li>apply rendering-canvas-vue.js from Hi.Webapi package.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>wwwroot/demo-plain-inline.html
|
||||
<ul>
|
||||
<li>Hard code implementation without re-using js file.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</article>
|
||||
|
||||
<div class="contribution d-print-none">
|
||||
</div>
|
||||
|
||||
<div class="next-article d-print-none border-top" id="nextArticle"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="affix">
|
||||
<nav id="affix"></nav>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<div class="container-xxl search-results" id="search-results"></div>
|
||||
|
||||
<footer class="border-top text-secondary">
|
||||
<div class="container-xxl">
|
||||
<div class="flex-fill">
|
||||
<span> Copyright © 2025 <a href='https://superhightech.com.tw'>Tech Coordinate</a>. All rights reserved. <a href='https://superhightech.com.tw'>超級高科技股份有限公司</a> © 2025 版權所有 </span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user