虽然 Kitware 提供了 ActiViz 作为 vtk 的 .Net 库,但这是一个收费软件,并且在调试模式下一直存在程序退出时资源无法释放的问题,于是自己动手做了 vtk 的 .Net 封装库。
代码语言:csharp复制/*
* 功能:把 VTK 封装成 Windows Forms 控件
* 作者:秦建辉
* 微信:splashcn
* VTK版本:9.3.1
*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace FirstSolver
{
/// <summary>
/// VTK WinForm 控件
/// </summary>
public class RenderWindowControl : UserControl
{
/// <summary>
/// 构造函数
/// </summary>
public RenderWindowControl()
{ // 设置控件样式
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
InitializeComponent();
}
/// <summary>
/// 释放资源
/// </summary>
/// <param name="disposing">true/false:是否释放托管资源</param>
protected override void Dispose(bool disposing)
{
try
{
if (disposing)
{
components?.Dispose();
}
}
finally
{
base.Dispose(disposing);
}
}
/// <summary>
/// 同步窗口大小
/// </summary>
internal void SyncRenderWindowSize() => RenderWindow?.SetSize(Size.Width, Size.Height);
/// <summary>
/// 引发 HandleCreated 事件
/// </summary>
/// <param name="e">包含事件数据的 EventArgs</param>
protected override void OnHandleCreated(EventArgs e)
{
if (!DesignMode)
{ // 不是处于设计模式
RenderWindow = vtkRendererWindow.New(); // 渲染窗口
Renderer = vtkRenderer.New(); // 渲染器
RenderWindow.AddRenderer(Renderer);
RenderWindowInteractor = vtkRenderWindowInteractor.New(); // 交互器
RenderWindowInteractor.SetInteractorStyle(vtkInteractorStyleTrackballCamera.New());
RenderWindow.SetInteractor(RenderWindowInteractor);
RenderWindow.SetParentId(Handle); // 控件句柄
}
base.OnHandleCreated(e);
}
/// <summary>
/// 引发 HandleDestroyed 事件
/// </summary>
/// <param name="e">包含事件数据的 EventArgs</param>
protected override void OnHandleDestroyed(EventArgs e)
{
if (Renderer != null && Renderer.Handle != IntPtr.Zero)
{
Renderer.SetRenderWindow(new vtkRendererWindow(IntPtr.Zero));
Renderer = null;
}
if ((RenderWindowInteractor != null) && (RenderWindowInteractor.Handle != IntPtr.Zero))
{
RenderWindowInteractor.SetRenderWindow(new vtkRendererWindow(IntPtr.Zero));
RenderWindowInteractor = null;
}
RenderWindow = null;
base.OnHandleDestroyed(e);
}
#region MouseEvent
/// <summary>
/// 引发 MouseDown 事件
/// </summary>
/// <param name="e">包含事件数据的 MouseEventArgs</param>
protected override void OnMouseDown(MouseEventArgs e)
{
if (RenderWindowInteractor == null || RenderWindowInteractor.Handle == IntPtr.Zero) return;
RenderWindowInteractor.SetEventInformationFlipY(e.X, e.Y, 0, 0, 0, e.Clicks, null);
switch (e.Button)
{
case MouseButtons.Left:
RenderWindowInteractor.LeftButtonPressEvent();
break;
case MouseButtons.Right:
RenderWindowInteractor.RightButtonPressEvent();
break;
case MouseButtons.Middle:
RenderWindowInteractor.MiddleButtonPressEvent();
break;
}
}
/// <summary>
/// 引发 MouseMove 事件
/// </summary>
/// <param name="e">包含事件数据的 MouseEventArgs</param>
protected override void OnMouseMove(MouseEventArgs e)
{
if (RenderWindowInteractor == null || RenderWindowInteractor.Handle == IntPtr.Zero) return;
RenderWindowInteractor.SetEventInformationFlipY(e.X, e.Y, 0, 0, 0, e.Clicks, null);
RenderWindowInteractor.MouseMoveEvent();
}
/// <summary>
/// 引发 MouseUp 事件
/// </summary>
/// <param name="e">包含事件数据的 MouseEventArgs</param>
protected override void OnMouseUp(MouseEventArgs e)
{
if (RenderWindowInteractor == null || RenderWindowInteractor.Handle == IntPtr.Zero) return;
RenderWindowInteractor.SetEventInformationFlipY(e.X, e.Y, 0, 0, 0, e.Clicks, null);
switch (e.Button)
{
case MouseButtons.Left:
RenderWindowInteractor.LeftButtonReleaseEvent();
break;
case MouseButtons.Right:
RenderWindowInteractor.RightButtonReleaseEvent();
break;
case MouseButtons.Middle:
RenderWindowInteractor.MiddleButtonReleaseEvent();
break;
}
}
/// <summary>
/// 引发 MouseWheel 事件
/// </summary>
/// <param name="e">包含事件数据的 MouseEventArgs</param>
protected override void OnMouseWheel(MouseEventArgs e)
{
if (RenderWindowInteractor == null || RenderWindowInteractor.Handle == IntPtr.Zero) return;
RenderWindowInteractor.SetEventInformationFlipY(e.X, e.Y, 0, 0, 0, e.Clicks, null);
if (e.Delta > 0)
{ // 前滚
RenderWindowInteractor.MouseWheelForwardEvent();
}
else
{ // 后滚
RenderWindowInteractor.MouseWheelBackwardEvent();
}
}
#endregion
#region KeyEvent
/// <summary>
/// 引发 KeyDown 事件
/// </summary>
/// <param name="e">包含事件数据的 KeyEventArgs</param>
protected override void OnKeyDown(KeyEventArgs e)
{
if (RenderWindowInteractor == null || RenderWindowInteractor.Handle == IntPtr.Zero) return;
RenderWindowInteractor.SetKeyEventInformation(e.Control ? 1 : 0, e.Shift ? 1 : 0, (sbyte)e.KeyCode, 1, null);
RenderWindowInteractor.KeyPressEvent();
}
/// <summary>
/// 引发 KeyPress 事件
/// </summary>
/// <param name="e">包含事件数据的 KeyPressEventArgs</param>
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (RenderWindowInteractor == null || RenderWindowInteractor.Handle == IntPtr.Zero) return;
RenderWindowInteractor.SetKeyEventInformation(0, 0, (sbyte)e.KeyChar, 1, e.KeyChar.ToString());
RenderWindowInteractor.CharEvent();
}
/// <summary>
/// 引发 KeyUp 事件
/// </summary>
/// <param name="e">包含事件数据的 KeyEventArgs</param>
protected override void OnKeyUp(KeyEventArgs e)
{
if (RenderWindowInteractor == null || RenderWindowInteractor.Handle == IntPtr.Zero) return;
RenderWindowInteractor.SetKeyEventInformation(e.Control ? 1 : 0, e.Shift ? 1 : 0, (sbyte)e.KeyCode, 1, null);
RenderWindowInteractor.KeyReleaseEvent();
}
#endregion
/// <summary>
/// 引发 SizeChanged 事件
/// </summary>
/// <param name="e">包含事件数据的 EventArgs</param>
protected override void OnSizeChanged(EventArgs e)
{
SyncRenderWindowSize();
RenderWindowInteractor?.ConfigureEvent();
base.OnSizeChanged(e);
Invalidate();
}
#region Focus
[DllImport("user32.dll")]
internal static extern IntPtr SetFocus(IntPtr hWnd);
/// <summary>
/// 引发 GotFocus 事件
/// </summary>
/// <param name="e">包含事件数据的 EventArgs</param>
protected override void OnGotFocus(EventArgs e)
{
if (RenderWindow != null && RenderWindow.Handle != IntPtr.Zero)
{
IntPtr genericWindowId = RenderWindow.GetGenericWindowId();
if (genericWindowId != IntPtr.Zero)
{
try
{
SetFocus(genericWindowId);
}
catch
{
// 屏蔽异常
}
}
}
base.OnGotFocus(e);
}
#endregion
/// <summary>
/// 引发 Paint 事件
/// </summary>
/// <param name="e">包含事件数据的 PaintEventArgs</param>
protected override void OnPaint(PaintEventArgs e)
{
if (RenderWindow != null && RenderWindow.Handle != IntPtr.Zero)
{
if (Visible)
{
SyncRenderWindowSize();
if (RenderWindow.GetInteractor().Handle != RenderWindowInteractor.Handle)
{ // 设置新的交互器
RenderWindow.SetInteractor(RenderWindowInteractor);
}
RenderWindow.Render();
}
}
base.OnPaint(e);
}
/// <summary>
/// 引发 VisibleChanged 事件
/// </summary>
/// <param name="e">包含事件数据的 EventArgs</param>
protected override void OnVisibleChanged(EventArgs e) => base.OnVisibleChanged(e);
/// <summary>
/// 初始化组件
/// </summary>
private void InitializeComponent()
{
SuspendLayout();
AutoScaleDimensions = new SizeF(6f, 13f);
AutoScaleMode = AutoScaleMode.Font;
Name = "RenderWindowControl";
Size = new Size(400, 300);
ResumeLayout(false);
}
#region Property
/// <summary>
/// 渲染窗口
/// </summary>
public vtkRendererWindow RenderWindow { get; protected set; }
/// <summary>
/// 渲染器
/// </summary>
public vtkRenderer Renderer
{
get => _renderer;
set
{
if (_renderer == null)
{
_renderer = value;
}
else
{
if (value == null || _renderer.Handle != value.Handle)
{
_renderer.Delete();
_renderer = value;
}
}
}
}
private vtkRenderer _renderer;
/// <summary>
/// 渲染窗口交互器
/// </summary>
public vtkRenderWindowInteractor RenderWindowInteractor
{
get => _renderWindowInteractor;
set
{
if (_renderWindowInteractor == null)
{
_renderWindowInteractor = value;
}
else
{
if (value == null || _renderWindowInteractor.Handle != value.Handle)
{
_renderWindowInteractor.Delete();
_renderWindowInteractor = value;
}
}
}
}
private vtkRenderWindowInteractor _renderWindowInteractor;
/// <summary>
/// 设计模式下的容器
/// </summary>
private IContainer components = null;
#endregion
}
}