前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自己动手把 VTK 封装成 Windows Forms 控件

自己动手把 VTK 封装成 Windows Forms 控件

原创
作者头像
秦建辉
修改2024-08-16 16:01:54
2870
修改2024-08-16 16:01:54
举报
文章被收录于专栏:VTK

虽然 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
    }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档