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

在这里插入图片描述

🎨 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 显示控件
主窗口类,包含以下关键组件:
```csharp

using 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 logo
            drawImage.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:Control
      x: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 coordinates

        Vector3d vector = new Vector3d(-x, -y, 0.0);

        vector = vector.TransformBy((pView.ScreenMatrix * pView.ProjectionMatrix).Inverse());

        pView.Dolly(vector);
    }



    //Zoom In / Zoom Out functionality

    private 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 coordinates

                            Point3d positionCamera = pView.Position;

                            // TransformBy() returns a transformed copy

                            positionCamera = 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/956744.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode100】--- 寻找重复数

题目传送门 方法一&#xff1a;暴力解法&#xff08;超时&#xff09; 算法原理 双重循环&#xff0c;每次固定一个数&#xff0c;再遍历别的数。比较这两个数是否相等&#xff0c; 若相等则返回这个数。就是重复数。 复杂度分析 时间复杂度&#xff1a;O&#xff08;N方&…

doris 2.1 Queries Acceleration-Hints 学习笔记

1 Hint Classification 1.1 Leading Hint:Specifies the join order according to the order provided in the leading hint. 1.2 Ordered Hint:A specific type of leading hint that specifies the join order as the original text sequence. 1.3 Distribute Hint:Speci…

【2024博客之星】我的年度技术总结:Netty渡劫指南--从线程暴走到百万长连接,这一年我踩过的坑比写的代码还多

时间过得真快&#xff0c;作为一名十年的技术老鸟&#xff0c;这一年来跟Netty打交道打得不少。今天就聊聊这一年来我跟Netty的那些事儿&#xff0c;还有我在学习它技术原理时的一些总结。 导读 Netty再相见&#xff1a;捡起来、用起来Netty原理学习&#xff1a;边啃边写变总结…

Tomcat下载配置

目录 Win下载安装 Mac下载安装配置 Win 下载 直接从官网下载https://tomcat.apache.org/download-10.cgi 在圈住的位置点击下载自己想要的版本 根据自己电脑下载64位或32位zip版本 安装 Tomcat是绿色版,直接解压到自己想放的位置即可 Mac 下载 官网 https://tomcat.ap…

【CSDN博客之星2024】主题创作《总结2024,为了遇见更好的2025》

【博客之星2024】主题创作《总结2024&#xff0c;为了更好的2025》 一、AI技术变革日新月异二、总结我的CSDN2024三、技术深耕&#xff0c;从实践中汲取力量3.1、在数据库技术方面3.2、在javavue前后端开发领域3.3、在项目运维领域3.4、在GIS开发方面 四、2025工作计划五、2025…

MySQL 事务及MVCC机制详解

目录 什么是事务 事务的隔离级别 数据库并发的三种场景 读-写 什么是事务 事务就是一组DML语句组成&#xff0c;这些语句在逻辑上存在相关性&#xff0c;这一组DML语句要么全部成功&#xff0c;要么全部失败&#xff0c;是一个整体。MySQL提供一种机制&#xff0c;保证我们…

数据库存储上下标符号,sqlserver 2008r2,dm8

sqlserver 2008r2&#xff1a; 数据类型需要用nvarchar插入数据时字符串前需要用N create table test( col1 varchar(50), col2 nvarchar(50) ) insert into test(col1,col2) values(U⁴⁵⁶⁷⁸⁹⁰D₁₂₃₄₅₆₇₈₉₀,U⁴⁵⁶⁷⁸⁹⁰D₁₂₃₄₅₆₇₈₉₀) insert into…

Java高频面试之SE-15

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; String 怎么转成 Integer 的&#xff1f;它的原理是&#xff1f; 在 Java 中&#xff0c;要将 String 转换为 Integer 类型&#xff0c;可…

nacos2.3.0 接入pgsql或其他数据库

首先尝试使用官方插件进行扩展&#xff0c;各种报错后放弃&#xff0c;不如自己修改源码吧。 一、官方解决方案 1、nocos 文档地址&#xff1a;Nacos 配置中心简介, Nacos 是什么 | Nacos 官网 2、官方解答&#xff1a;nacos支持postgresql数据库吗 | Nacos 官网 3、源码下载地…

城市电动出行的智慧升级:充电桩可视化管理

通过图扑可视化管理平台&#xff0c;实时监控与优化城市充电桩网络&#xff0c;提高运维效率与用户满意度&#xff0c;支撑绿色交通体系发展&#xff0c;为电动出行打造更加智能化的基础设施解决方案。

关于 Cursor 的一些学习记录

文章目录 1. 写在最前面2. Prompt Design2.1 Priompt v0.1&#xff1a;提示设计库的首次尝试2.2 注意事项 3. 了解 Cursor 的 AI 功能3.1 问题3.2 答案 4. cursor 免费功能体验5. 写在最后面6. 参考资料 1. 写在最前面 本文整理了一些学习 Cursor 过程中读到的或者发现的感兴趣…

idea中远程调试中配置的参数说明

Ⅰ 远程调试中配置的端口号与服务本身端口号区别 一、远程调试中配置端口号的作用 在 IDEA 中进行远程调试时配置的端口号主要用于建立开发工具&#xff08;如 IDEA&#xff09;和远程服务之间的调试连接。当你启动远程调试时&#xff0c;IDEA 会监听这个配置的端口号&#xf…

基于 MDL 行情插件的中金所 L1 数据处理最佳实践

本文介绍了如何通过 DolphinDB 的 MDL 插件订阅并处理中金所 Level 1 实时数据。首先&#xff0c;文章简要介绍了 MDL 插件的功能和作用。它是基于 MDL 官方提供的行情数据服务 C SDK&#xff08;即 TCP 版本 MDL &#xff09;实现&#xff0c;提供了实时数据获取和处理的能力。…

JupyterLab 安装以及部分相关配置

安装 JupyterLab pip install jupyter启动 JupyterLab jupyter lab [--port <指定的端口号>] [--no-browser] # --port 指定端口 # --no-browser 启动时不打开浏览器安装中文 首先安装中文包 pip install jupyterlab-language-pack-zh-CN安装完成后重启 JupyterLab 选…

LabVIEW电源纹波补偿

在电子设备的电源管理中&#xff0c;电源纹波的存在可能会对设备的稳定性和性能产生负面影响。以某精密电子仪器的电源纹波补偿为例&#xff0c;详细阐述如何运用 LabVIEW 编写程序进行电源纹波补偿。将从电源纹波特点、测量采样、滤波、反馈控制等多个方面展开介绍。 ​ 电源…

嵌入式硬件篇---基本组合逻辑电路

文章目录 前言基本逻辑门电路1.与门&#xff08;AND Gate&#xff09;2.或门&#xff08;OR Gate&#xff09;3.非门&#xff08;NOT Gate&#xff09;4.与非门&#xff08;NAND Gate&#xff09;5.或非门&#xff08;NOR Gate&#xff09;6.异或门&#xff08;XOR Gate&#x…

使用rpc绕过咸鱼sign校验

案例网站是咸鱼 找到加密函数i()&#xff0c;发现参数是由token时间戳appkeydata构成的 js客户端服务 考虑到网站可能有判断时间戳长短而让请求包失效的可能&#xff0c;我们请求包就直接用它的方法生成 下面我们先把token和h置为键值对tjh123 再把方法i()设为全局变量my_…

鸿蒙安装HAP时提示“code:9568344 error: install parse profile prop check error” 问题现象

在启动调试或运行应用/服务时&#xff0c;安装HAP出现错误&#xff0c;提示“error: install parse profile prop check error”错误信息。 解决措施 该问题可能是由于应用使用了应用特权&#xff0c;但应用的签名文件发生变化后未将新的签名指纹重新配置到设备的特权管控白名…

Pix2Pix :用于图像到图像转换的条件生成对抗网络

1. 背景与问题 图像到图像的转换&#xff08;Image-to-Image Translation&#xff09;是计算机视觉中的一个重要任务&#xff0c;指的是在输入一张图像的情况下&#xff0c;生成一张风格、内容或其他条件不同但语义一致的图像。随着深度学习的发展&#xff0c;尤其是生成对抗网…

【大数据2025】Hadoop 万字讲解

文章目录 一、大数据通识大数据诞生背景与基本概念大数据技术定义与特征大数据生态架构概述数据存储数据计算与易用性框架分布式协调服务和任务调度组件数仓架构流处理架构 二、HDFSHDFS 原理总结一、系统架构二、存储机制三、数据写入流程四、心跳机制与集群管理 安全模式&…