【2025 ODA teigha .NET系列开发教程 第一章】实现WPF ViewDirectX DWGDXF 模式图纸的预览查看,缩放

ops/2025/1/23 5:13:01/

在这里插入图片描述

2025 ODA teigha .NET系列开发教程

  • 🎨 CAD图纸查看器
    • 📖 项目介绍
      • 🎯 项目目标
    • 🛠️ 技术架构
      • 核心技术
    • ✨ 功能特性
      • 📂 文件操作
      • 🔍 视图控制
    • 🎯 使用指南
      • 快速开始
    • 🔧 开发者指南
      • 环境配置
      • 📁 代码结构
        • Control.xaml 显示控件
        • Control.xaml.cs
        • Device.cs类
        • MainWindow.xaml主界面代码
        • MainWindow.xaml.cs后端代码

🎨 CAD图纸查看器

  • 下载Teigha SDK 21.6 FOR C#

📖 项目介绍

嗨!欢迎来到CAD图纸查看器项目!这是一个基于WPF和Teigha SDK开发的专业CAD文件查看工具。无论你是工程师、设计师,还是其他需要查看CAD图纸的专业人士,这个工具都能帮你轻松处理DWG/DXF格式的工程图纸。

🎯 项目目标

  • 提供简单直观的CAD文件查看体验
  • 确保高性能的图纸渲染和操作响应
  • 支持业界标准的文件格式和操作方式

🛠️ 技术架构

核心技术

  • 界面框架:WPF (Windows Presentation Foundation)

    • 现代化的UI设计
    • 流畅的用户交互体验
  • 开发语言:C#

    • 强类型安全
    • 优秀的内存管理
  • CAD引擎:Teigha SDK (Open Design Alliance)

    • 下载Teigha SDK 21.6 FOR C#
    • 专业的CAD文件解析能力
    • 稳定可靠的图纸处理
  • 渲染引擎:DirectX

    • 高性能图形渲染
    • 流畅的缩放和平移体验

✨ 功能特性

📂 文件操作

  • 文件打开

    • 支持.dwg格式(AutoCAD原生格式)
    • 支持.dxf格式(通用交换格式)
    • 智能错误提示和处理
  • 文件保存

    • 快速保存当前文件
    • 支持另存为不同版本
      • AutoCAD R24
      • AutoCAD R21
      • AutoCAD R18
      • AutoCAD R15
      • AutoCAD R14
      • AutoCAD R13
      • AutoCAD R12

🔍 视图控制

  • 智能缩放

    • 鼠标滚轮控制缩放
    • 以鼠标位置为中心点
    • 平滑的缩放效果
  • 视图导航

    • 直观的平移操作
    • 模型空间/图纸空间切换
    • 多视图支持

🎯 使用指南

快速开始

  1. 启动程序

    • 双击程序图标启动
    • 等待初始化完成
  2. 打开文件

    • 点击菜单中的"_Open"
    • 选择需要查看的CAD文件
    • 等待文件加载完成
  3. 查看操作

    • 使用鼠标滚轮进行缩放
    • 拖动视图进行平移
    • 使用菜单功能进行其他操作

🔧 开发者指南

环境配置

  1. 必需组件

    • Visual Studio 2019或更高版本
    • .NET Framework 4.7.2+
    • Teigha SDK(需要许可证,请联系我,我这有最新的许可证)
    • DirectX运行时
  2. 项目设置

    <!-- 项目引用配置 -->
    <Reference Include="Teigha.DatabaseServices">
    <Reference Include="Teigha.GraphicsSystem">
    <Reference Include="Teigha.Runtime">
    <Reference Include="Teigha.GraphicsInterface">
    <Reference Include="Teigha.Geometry">
    

📁 代码结构

```
WpfViewDirectX/
├── MainWindow.xaml.cs     # 主窗口逻辑实现
│   ├── 文件操作相关方法
│   ├── 视图控制相关方法
│   └── 事件处理方法
├── MainWindow.xaml        # 界面布局定义
├── App.xaml              # 应用程序配置
└── Properties/           # 项目属性配置


### 🔑 核心类说明#### D3DImage.cs 显示控件
主窗口类,包含以下关键组件:
```csharpusing System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;
using Teigha.GraphicsSystem;
using Teigha.Runtime;namespace WpfViewDirectX
{/// <summary>/// DirectX图像控件/// 负责处理DirectX渲染表面和WPF图像的交互/// </summary>public class WpfViewDirectXD3DImage : D3DImage{// 图形系统设备引用private Device m_gsDevice;// DirectX渲染表面的本机指针private IntPtr d3dSurfacePtr = IntPtr.Zero;// 用于VC10兼容性的反射方法private static System.Reflection.MethodInfo fSetBackBuffer = null;/// <summary>/// 构造函数/// </summary>public WpfViewDirectXD3DImage(){}/// <summary>/// 初始化DirectX图像/// </summary>/// <param name="device">图形系统设备</param>public void Initialize(Device device){m_gsDevice = device;}/// <summary>/// 更新渲染表面/// 将DirectX渲染的内容更新到WPF图像/// </summary>public void UpdateSurface(){if (m_gsDevice == null)return;// 软件渲染模式下需要特殊处理if (IsSoftwareOnlyRenderMode() && !this.IsFrontBufferAvailable)return;UpdateBackBuffer();}/// <summary>/// 更新后台缓冲区/// </summary>void UpdateBackBuffer(){d3dSurfacePtr = GetD3DSurfaceFromDevice();SetD3DSurfacePtrToBackBuffer(d3dSurfacePtr);}/// <summary>/// 从设备获取DirectX渲染表面/// 在获取前需要更新设备,确保属性是最新的/// 获取新表面前需要释放旧表面/// </summary>private IntPtr GetD3DSurfaceFromDevice(){RXObject d3dSurfaceProp = null;using (Dictionary props = m_gsDevice.Properties){if (props.Contains("D3DSurface"))d3dSurfaceProp = props["D3DSurface"];}if (d3dSurfaceProp == null)return IntPtr.Zero;RxVariant v = new RxVariant(d3dSurfaceProp);return v.IntPtr;}/// <summary>/// 设置DirectX表面指针到后台缓冲区/// </summary>/// <param name="realSurfacePointer">DirectX表面指针</param>private void SetD3DSurfacePtrToBackBuffer(IntPtr realSurfacePointer){if (realSurfacePointer == IntPtr.Zero)return;CallSetBackBufferWithLocks(realSurfacePointer);UpdateDirtyRect();}/// <summary>/// 使用锁定机制调用SetBackBuffer/// 确保线程安全的缓冲区更新/// </summary>/// <param name="surface">DirectX表面指针</param>private void CallSetBackBufferWithLocks(IntPtr surface){// 通过反射获取SetBackBuffer方法if (fSetBackBuffer == null)fSetBackBuffer = typeof(WpfViewDirectXD3DImage).GetMethod("SetBackBuffer", new Type[] { typeof(D3DResourceType), typeof(IntPtr), typeof(bool) });this.Lock();// 调用SetBackBuffer方法设置后台缓冲区fSetBackBuffer.Invoke(this, new object[] {D3DResourceType.IDirect3DSurface9,surface,RenderOptions.ProcessRenderMode == System.Windows.Interop.RenderMode.SoftwareOnly});this.Unlock();}/// <summary>/// 更新脏矩形区域/// 标记需要重新渲染的区域/// </summary>private void UpdateDirtyRect(){Int32Rect updateRect = new Int32Rect();updateRect.X = updateRect.Y = 0;updateRect.Width = this.PixelWidth;updateRect.Height = this.PixelHeight;this.Lock();this.AddDirtyRect(updateRect);this.Unlock();}/// <summary>/// 清理后台缓冲区和渲染表面/// </summary>public void ClearBackBufferAndSurface(){CallSetBackBufferWithLocks(IntPtr.Zero);// 释放DirectX表面资源if (d3dSurfacePtr != IntPtr.Zero){Marshal.Release(d3dSurfacePtr);d3dSurfacePtr = IntPtr.Zero;}}/// <summary>/// 释放资源/// 在控件销毁前调用,确保资源正确释放/// </summary>public void Deinitialize(){if (IsSoftwareOnlyRenderMode() && !this.IsFrontBufferAvailable)return;if (m_gsDevice == null)return;ClearBackBufferAndSurface();m_gsDevice.Dispose();m_gsDevice = null;}/// <summary>/// 检查是否为软件渲染模式/// </summary>/// <returns>是否为软件渲染模式</returns>private bool IsSoftwareOnlyRenderMode(){return RenderOptions.ProcessRenderMode == System.Windows.Interop.RenderMode.SoftwareOnly;}}
}
Control.xaml 显示控件

主窗口类,包含以下关键组件:

<UserControl x:Class="WpfViewDirectX.Control"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:WpfViewDirectX="clr-namespace:WpfViewDirectX"Height="Auto" Width="Auto" SizeChanged="UserControl_SizeChanged"><Grid Name="Grid"><Image x:Name ="drawImage"VerticalAlignment="Stretch"HorizontalAlignment="Stretch" Source="Images/oda_logo.png"/></Grid>
</UserControl>
Control.xaml.cs

主窗口类,包含以下关键组件:


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using Brushes = System.Windows.Media.Brushes;
using System.Windows;
using System.Windows.Interop;
using Size = System.Windows.Size;
using System.Windows.Media.Imaging;
using Teigha;
using Teigha.DatabaseServices;
using Teigha.GraphicsInterface;
using Teigha.GraphicsSystem;
using Teigha.Runtime;namespace WpfViewDirectX
{/// <summary>/// CAD图纸渲染控件/// 负责处理图纸的显示和交互/// </summary>public partial class Control : UserControl{// 用于DirectX渲染的隐藏窗口,作为渲染表面Window HiddenWindowForRendering;// DirectX图像控件,用于显示渲染结果public WpfViewDirectXD3DImage d3dImage;// CAD数据库引用,存储图纸数据public Database database;// 视图设备,处理实际的渲染工作WpfViewDevice device;/// <summary>/// 构造函数/// 初始化控件和渲染相关组件/// </summary>public Control(){InitializeComponent();// 设置默认背景为ODA logodrawImage.Source = GetOdaLogo();// 初始化渲染设备device = new WpfViewDevice();d3dImage = new WpfViewDirectXD3DImage();}/// <summary>/// 初始化控件/// </summary>/// <param name="database">CAD数据库实例</param>public void Initialize(Database database){this.database = database;// 初始化渲染设备device.Initialize(this);// 初始化DirectX图像d3dImage.Initialize(device.graphichsDevice);// 调整大小Resize();// 设置图像源drawImage.Source = d3dImage;}/// <summary>/// 获取或创建用于渲染的隐藏窗口的句柄/// </summary>/// <returns>窗口句柄源</returns>public HwndSource GetHwndSourceOfHiddenWindowForRendering(){if (HiddenWindowForRendering == null){// 创建一个隐藏的窗口用于DirectX渲染HiddenWindowForRendering = new Window();HiddenWindowForRendering.Owner = Application.Current.MainWindow;HiddenWindowForRendering.Visibility = System.Windows.Visibility.Hidden;HiddenWindowForRendering.WindowStyle = System.Windows.WindowStyle.None;HiddenWindowForRendering.ShowInTaskbar = false;HiddenWindowForRendering.Background = Brushes.Transparent;HiddenWindowForRendering.AllowsTransparency = true;HiddenWindowForRendering.Show();HiddenWindowForRendering.Hide();}return HwndSource.FromVisual(HiddenWindowForRendering) as HwndSource;}/// <summary>/// 重新初始化控件/// 在打开新文件前调用,清理旧的资源/// </summary>public void Reinitialize(){// 清理渲染设备if (device != null){device.Deinitialize();device = new WpfViewDevice();}// 清理DirectX图像if (d3dImage != null){d3dImage.Deinitialize();d3dImage = new WpfViewDirectXD3DImage();}}/// <summary>/// 更新渲染内容/// </summary>public void Update(){device.graphichsDevice.Update();}/// <summary>/// 释放控件资源/// 在窗口关闭前调用,确保资源正确释放/// </summary>public void Deinitialize(){// 释放渲染设备资源if (device != null){device.Deinitialize();device = null;}// 释放DirectX图像资源if (d3dImage != null){d3dImage.Deinitialize();d3dImage = null;}}/// <summary>/// 调整控件大小/// 在窗口大小改变时更新渲染区域/// </summary>public void Resize(){if (device == null || d3dImage == null || device.graphichsDevice == null)return;// 清理缓冲区和渲染表面d3dImage.ClearBackBufferAndSurface();// 更新设备尺寸device.graphichsDevice.OnSize(GetControlSize());device.graphichsDevice.Update();// 更新渲染表面d3dImage.UpdateSurface();}/// <summary>/// 获取控件当前尺寸/// </summary>/// <returns>控件尺寸</returns>private System.Drawing.Size GetControlSize(){Size rect = RenderSize;System.Drawing.Size rectInt = new System.Drawing.Size((int)rect.Width, (int)rect.Height);return rectInt;}/// <summary>/// 获取ODA logo作为默认背景/// 在未加载图纸时显示/// </summary>/// <returns>logo图像源</returns>private static BitmapSource GetOdaLogo(){BitmapSource bitmapSource;try{// 加载ODA logo资源System.Drawing.Bitmap bitmap = WpfViewDirectX.Properties.Resources.oda_logo;// 转换为WPF可用的图像源bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(),IntPtr.Zero,System.Windows.Int32Rect.Empty,BitmapSizeOptions.FromWidthAndHeight(bitmap.Width, bitmap.Height));}catch (System.Exception ex){// 如果加载失败,返回空bitmapSource = null;}return bitmapSource;}/// <summary>/// 控件大小改变事件处理/// </summary>private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e){// 重新调整渲染区域大小Resize();}}
}
Device.cs类
using System;
using System.Windows;
using System.Windows.Interop;
using Teigha.DatabaseServices;
using Teigha.GraphicsInterface;
using Teigha.GraphicsSystem;
using Teigha.Runtime;namespace WpfViewDirectX
{/// <summary>/// WPF视图设备类/// 负责管理CAD图形的渲染设备和布局/// </summary>public class WpfViewDevice{// 图形渲染设备,处理实际的绘图操作public Device graphichsDevice;// 布局辅助设备,处理模型空间和图纸空间的视图LayoutHelperDevice layoutHelperDevice;// 绘图控件引用Control drawControl;/// <summary>/// 构造函数/// </summary>public WpfViewDevice(){}/// <summary>/// 初始化视图设备/// </summary>/// <param name="drawControl">绘图控件实例</param>public void Initialize(Control drawControl){this.drawControl = drawControl;try{// 加载预定义的渲染模块(可以是"WinDirectX"或"WinOpenGL")GsModule gsModule = (GsModule)SystemObjects.DynamicLinker.LoadModule("WinDirectX.txv", false, true);// 创建图形设备graphichsDevice = gsModule.CreateDevice();// 创建或获取隐藏窗口,用于OdGsDevice在窗口上渲染模型IntPtr renderWindow = drawControl.GetHwndSourceOfHiddenWindowForRendering().Handle;// 设置设备属性using (Dictionary props = graphichsDevice.Properties){// 设置窗口句柄(DirectX设备必需)if (props.Contains("WindowHWND"))props.AtPut("WindowHWND", new RxVariant(renderWindow));// 启用双缓冲if (props.Contains("DoubleBufferEnabled"))props.AtPut("DoubleBufferEnabled", new RxVariant(true));// 启用背面剔除if (props.Contains("DiscardBackFaces"))props.AtPut("DiscardBackFaces", new RxVariant(true));// 在渲染器端启用场景图if (props.Contains("UseSceneGraph"))props.AtPut("UseSceneGraph", new RxVariant(true));// 启用视觉样式if (props.Contains("UseVisualStyles"))props.AtPut("UseVisualStyles", new RxVariant(true));}// 设置图纸空间视口或平铺using (ContextForDbDatabase ctx = new ContextForDbDatabase(drawControl.database)){// 启用图形系统模型ctx.UseGsModel = true;// 设置活动布局视图layoutHelperDevice = LayoutHelperDevice.SetupActiveLayoutViews(graphichsDevice, ctx);}// 设置调色板(使用深色主题)layoutHelperDevice.SetLogicalPalette(Device.DarkPalette);// 执行初始大小调整drawControl.Resize();}catch (System.Exception ex){MessageBox.Show(ex.ToString());}}/// <summary>/// 释放设备资源/// 确保按正确的顺序释放资源/// </summary>public void Deinitialize(){// 首先释放布局辅助设备if (layoutHelperDevice != null){layoutHelperDevice.Dispose();layoutHelperDevice = null;}// 然后释放图形设备if (graphichsDevice != null){graphichsDevice.Dispose();graphichsDevice = null;}}}
}
MainWindow.xaml主界面代码

<Window x:Class="WpfViewDirectX.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:WpfViewDirectX="clr-namespace:WpfViewDirectX"Title="MainWindow" Height="360" Width="564" MouseWheel="Window_MouseWheel"><Grid x:Name="mainGrid"><Grid.RowDefinitions><RowDefinition Height="25" /><RowDefinition Height="100*" /></Grid.RowDefinitions><Menu x:Name = "MainMenu" Grid.Row="0"><MenuItem Header="_File"><MenuItem Header="_Open"/><MenuItem Header="_Save" IsEnabled="false" x:Name="MenuItemSave"/><MenuItem Header="_SaveAs" IsEnabled="false" x:Name="MenuItemSaveAs"/><MenuItem Header="_Exit"/></MenuItem></Menu><WpfViewDirectX:Controlx:Name="drawControl"Grid.Row="1"VerticalAlignment="Stretch"HorizontalAlignment="Stretch"/></Grid>
</Window>
MainWindow.xaml.cs后端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using MenuItem = System.Windows.Controls.MenuItem;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Interop;
using System.Drawing;
using Teigha;
using Teigha.DatabaseServices;
using Teigha.GraphicsSystem;
using Teigha.Runtime;
using Teigha.GraphicsInterface;
using Teigha.Geometry;

namespace WpfViewDirectX
{
///
/// 主窗口类
/// 负责处理用户界面交互和CAD文件操作
///
public partial class MainWindow : Window
{
// Teigha服务实例,提供CAD核心功能
Teigha.Runtime.Services services;

    // CAD数据库,用于存储和管理图纸数据Database database = null;// 布局管理器,处理图纸布局LayoutManager lm;/// <summary>/// 构造函数/// 初始化窗口和CAD环境/// </summary>public MainWindow(){InitializeComponent();// 为所有菜单项添加点击事件处理foreach (MenuItem topLevelMenu in MainMenu.Items){foreach (MenuItem itemMenu in topLevelMenu.Items){itemMenu.Click += new RoutedEventHandler(MenuItem_Click);}}// 配置环境变量String strPath = Environment.GetEnvironmentVariable("PATH");String strPathModules = ""; // System.Environment.CurrentDirectory;Environment.SetEnvironmentVariable("PATH", strPathModules + ";" + strPath);// 初始化Teigha服务Teigha.Runtime.Services.odActivate(odActivate.UserInfo, odActivate.UserSignature);services = new Teigha.Runtime.Services();}/// <summary>/// 激活信息类/// 包含Teigha SDK的许可证信息/// </summary>internal class odActivate{// 用户信息(Base64编码)public const string UserInfo = "找我购买 微信:me1070202228";// 用户签名public const string UserSignature = "******找我购买 微信:me1070202228**************";}/// <summary>/// 窗口关闭时的清理工作/// </summary>protected override void OnClosing(System.ComponentModel.CancelEventArgs e){// 释放绘图控件资源drawControl.Deinitialize();// 释放数据库资源if (database != null)database.Dispose();// 释放Teigha服务services.Dispose();}/// <summary>/// 打开CAD文件/// </summary>/// <param name="sFilePath">文件路径</param>private void fileOpen(String sFilePath){// 重新初始化绘图控件drawControl.Reinitialize();// 释放旧的数据库资源if (database != null)database.Dispose();// 清理布局管理器if (lm != null){lm.LayoutSwitched -= new Teigha.DatabaseServices.LayoutEventHandler(reinitGraphDevice);HostApplicationServices.WorkingDatabase = null;lm = null;}bool bLoaded = true;database = new Database(false, false);try{// 根据文件扩展名选择打开方式String sExt = sFilePath.Substring(sFilePath.Length - 4);sExt = sExt.ToUpper();if (sExt.EndsWith(".DWG")){// 打开DWG文件database.ReadDwgFile(sFilePath, FileOpenMode.OpenForReadAndAllShare, false, "");}else if (sExt.EndsWith(".DXF")){// 打开DXF文件database.DxfIn(sFilePath, "");}}catch (System.Exception ex){MessageBox.Show(ex.Message);bLoaded = false;}if (bLoaded){// 更新窗口标题this.Title = String.Format("WpfViewDirectXApp - [{0}]", sFilePath);// 初始化绘图控件drawControl.Initialize(database);}}/// <summary>/// 重新初始化图形设备/// 在布局切换时调用/// </summary>private void reinitGraphDevice(object sender, Teigha.DatabaseServices.LayoutEventArgs e){drawControl.Deinitialize();drawControl.Initialize(database);}/// <summary>/// 菜单项点击事件处理/// </summary>private void MenuItem_Click(object sender, RoutedEventArgs e){MenuItem mItem = e.Source as MenuItem;if (mItem.IsEnabled){String sHeader = mItem.Header as String;if ("_Open" == sHeader){// 处理打开文件HandleOpenFile(mItem);}else if ("_Exit" == sHeader){this.Close();}else if (database != null){// 处理保存相关操作HandleSaveOperations(sHeader);}}}/// <summary>/// 处理文件打开操作/// </summary>private void HandleOpenFile(MenuItem mItem){database = new Database(false, false);System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();openFileDialog.Filter = "dwg files|*.dwg|dxf files|*.dxf";openFileDialog.DefaultExt = "dwg";openFileDialog.RestoreDirectory = true;if (System.Windows.Forms.DialogResult.OK == openFileDialog.ShowDialog()){fileOpen(openFileDialog.FileName);MenuItem mPar = mItem.Parent as MenuItem;MenuItemSave.IsEnabled = true;MenuItemSaveAs.IsEnabled = true;}}/// <summary>/// 处理保存相关操作/// </summary>private void HandleSaveOperations(string sHeader){if ("_Save" == sHeader){// 直接保存if (database != null)database.Save();}else if ("_SaveAs" == sHeader){// 另存为操作HandleSaveAs();}}public static ObjectId ActiveViewPortId(Database database){if (database.TileMode){return database.CurrentViewportTableRecordId;}else{using (BlockTableRecord paperBTR = (BlockTableRecord)database.CurrentSpaceId.GetObject(OpenMode.ForRead)){using (Layout layout = (Layout)paperBTR.LayoutId.GetObject(OpenMode.ForRead)){return layout.CurrentViewportId;}}}}public void Dolly(View pView, int x, int y){// helper function transforming parameters from screen to world coordinatesVector3d vector = new Vector3d(-x, -y, 0.0);vector = vector.TransformBy((pView.ScreenMatrix * pView.ProjectionMatrix).Inverse());pView.Dolly(vector);}//Zoom In / Zoom Out functionalityprivate void Window_MouseWheel(object sender, MouseWheelEventArgs parameter){try{System.Windows.Point pointToWindow = Mouse.GetPosition(parameter.MouseDevice.Captured);int delta = (parameter as MouseWheelEventArgs).Delta;using (Transaction tr = database.TransactionManager.StartTransaction()){using (DBObject pVpObj = ActiveViewPortId(database).GetObject(OpenMode.ForWrite)){using (AbstractViewportData pAVD = new AbstractViewportData(pVpObj)){using (View pView = pAVD.GsView){// camera position in world coordinatesPoint3d positionCamera = pView.Position;// TransformBy() returns a transformed copypositionCamera = positionCamera.TransformBy(pView.WorldToDeviceMatrix);double vx = pointToWindow.X - positionCamera.X;double vy = pointToWindow.Y - positionCamera.Y;Dolly(pView, (int)-vx, (int)-vy);pView.Zoom(delta > 0 ? 1.0 / 0.9 : 0.9);Dolly(pView, (int)vx, (int)vy);pAVD.SetView(pView);}}}tr.Commit();}drawControl.Resize();}catch (System.Exception ex){MessageBox.Show("Error on Zoom: " + ex.Message, "Error");}}
} // class MainWindow

} // namespace WpfViewDirectX


http://www.ppmy.cn/ops/152374.html

相关文章

深入理解 Java 并发编程中的锁机制

深入理解 Java 并发编程中的锁机制 在 Java 并发编程中&#xff0c;锁是一个至关重要的概念&#xff0c;它用于确保多个线程在访问共享资源时能够遵循正确的顺序和互斥规则。锁机制的设计和使用直接影响到程序的效率、正确性和可维护性。本文将从锁的基本概念讲起&#xff0c;…

Node.js使用教程

Node.js使用教程 Node.js是一个基于Chrome V8引擎的JavaScript运行环境&#xff0c;它让JavaScript运行在服务器端。以下是一个简单的Node.js使用教程&#xff1a; 一、 Node.js开发环境和编译 1.1 安装Node.js 访问Node.js官网下载并安装适合您操作系统的Node.js版本。 1…

FPGA与ASIC:深度解析与职业选择

IC&#xff08;集成电路&#xff09;行业涵盖广泛&#xff0c;涉及数字、模拟等不同研究方向&#xff0c;以及设计、制造、封测等不同产业环节。其中&#xff0c;FPGA&#xff08;现场可编程门阵列&#xff09;和ASIC&#xff08;专用集成电路&#xff09;是两种重要的芯片类型…

C++ ——— 模拟实现 vector 类

目录 vector 类的框架 无参数的构造函数 析构函数 获取有效数据个数 获取容量 重载 [] 运算符 可读可写版本 只可读版本 扩容 尾插 实现迭代器 可读可写版本 只可读版本 自定义设置size长度和内容 在任意位置插入 删除任意位置的数据 赋值重载 vector 类的框…

在Mac上安装Brew(Homebrew)——适用于Apple芯片(M1/M2系列)

在Mac上安装Brew&#xff08;Homebrew&#xff09;——适用于Apple芯片&#xff08;M1/M2系列&#xff09; Homebrew 是 macOS 上最受欢迎的包管理工具&#xff0c;它允许你轻松地安装和管理各种软件包和工具。对于使用 Apple Silicon 芯片&#xff08;如 M1 或 M2 芯片&#…

【HarmonyOS NAPI 深度探索6】使用 N-API 创建第一个 Hello World 原生模块

【HarmonyOS NAPI 深度探索6】使用 N-API 创建第一个 Hello World 原生模块 开发一个 N-API 模块听起来可能有点技术感十足&#xff0c;但实际上入门并不复杂。本文&#xff0c;我们来一步步实现一个简单的 Hello World 原生模块&#xff0c;感受一下 N-API 开发的魅力&#xf…

OpenHarmony OTA升级参考资料记录

OpenHarmony 作为一个开源分布式操作系统,通过其强大的 OTA(Over-The-Air)升级能力,为开发者和厂商提供了一套灵活而安全的系统升级方案。 OTA升级方式 根据升级包的应用方式,OpenHarmony 的 OTA 升级可以分为两种:本地升级和网络OTA升级。 本地升级 本地升级是将已制作…

【21】Word:德国旅游业务❗

目录 题目 NO1.2.3 NO4 NO5.6 NO7 NO8.9.10.11 题目 NO1.2.3 F12&#xff1a;另存为布局→页面设置→页边距&#xff1a;上下左右选中“德国主要城市”→开始→字体对话框→字体/字号→文本效果&#xff1a;段落对话框→对齐方式/字符间距/段落间距 NO4 布局→表对话框…