这里写目录标题
- 🎯 项目概述
- 项目结构
- 核心文件说明
- 🛠️ 环境搭建
- 1. 基础环境准备
- 2. 项目创建
- 📝 开发步骤
- 1. 设计主窗口界面
- DrawControl.cs
- DrawControl.Designer.cs代码
- 下载Teigha SDK 21.6 FOR C#
🎯 项目概述
这是一个基于Winform的CAD文件查看器,支持WPF,可以打开和查看DWG/DXF格式的CAD文件。对于新手开发者来说,这是一个很好的学习项目,可以了解:
- WPF应用和Winform程序开发,
- CAD文件处理
- 图形渲染基础
- Windows窗体应用
项目结构
📁 WpfViewWinForms
├── 📄 MainWindow.xaml.cs # 主窗口逻辑代码
├── 📄 MainWindow.xaml # 主窗口界面设计
├── 📄 DrawControl.cs # 绘图控件核心代码
├── 📄 DrawControl.resx # 绘图控件资源文件
└── 📄 DrawControl.Designer.cs # 设计器生成的代码
核心文件说明
-
MainWindow.xaml
- 这是应用程序的主界面
- 包含菜单栏和绘图区域
- 使用XAML语言描述界面布局
-
MainWindow.xaml.cs
- 主窗口的后台代码
- 处理文件打开、保存等操作
- 管理用户界面交互
-
DrawControl.cs
- CAD图纸显示的核心控件
- 处理图形渲染
- 管理视图操作
🛠️ 环境搭建
1. 基础环境准备
-
安装开发工具
- 下载并安装 Visual Studio 2019或更高版本
- 在Visual Studio Installer中选择:
- ✅ .NET桌面开发
- ✅ Visual Studio扩展开发
-
下载Teigha SDK
- 下载Teigha SDK 21.6 FOR C#
2. 项目创建
-
创建新项目
- 打开Visual Studio
- 文件 -> 新建 -> 项目
- 选择"WPF应用程序(.NET Framework)"
- 项目名称:WpfViewWinForms
- 框架:.NET Framework 4.7.2
-
添加引用
- 在解决方案资源管理器中右键"引用"
- 添加以下引用:
✓ Teigha.Common ✓ Teigha.Db ✓ Teigha.Ge ✓ System.Windows.Forms
📝 开发步骤
1. 设计主窗口界面
- 打开MainWindow.xaml
- 添加以下XAML代码:
<Window x:Class="WpfViewWinForms.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="MainWindow" Height="360" Width="564"><Grid><Menu Name = "MainMenu"><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><WindowsFormsHost Height="258" HorizontalAlignment="Left" Margin="0,22,0,0" Name="winFormsHost" VerticalAlignment="Top" Width="542" /></Grid>
</Window>
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 WpfViewWinForms
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : Window{// Teigha服务实例Teigha.Runtime.Services tdSrv;// 数据库实例,用于存储和管理CAD图纸数据Database database = null;// 布局管理器LayoutManager lm;public MainWindow(){InitializeComponent();// 为所有菜单项添加点击事件处理foreach (MenuItem topLevelMenu in MainMenu.Items){foreach (MenuItem itemMenu in topLevelMenu.Items){itemMenu.Click += new RoutedEventHandler(MenuItem_Click);}}// 设置环境变量PATHString strPath = Environment.GetEnvironmentVariable("PATH");String strPathModules = ""; Environment.SetEnvironmentVariable("PATH", strPathModules + ";" + strPath);// 激活Teigha服务Teigha.Runtime.Services.odActivate(odActivate.UserInfo, odActivate.UserSignature);tdSrv = new Teigha.Runtime.Services();// 创建并设置绘图控件DrawControl drawCtrl = new DrawControl();winFormsHost.Child = drawCtrl;}internal class odActivate{public const string UserInfo = "购买许可请联系微信 me1070202228";public const string UserSignature = "购买许可请联系微信 me1070202228";}protected override void OnClosing(System.ComponentModel.CancelEventArgs e){((DrawControl)winFormsHost.Child).Deinitialize();if (database != null)database.Dispose();tdSrv.Dispose();}/// <summary>/// 打开CAD文件的方法/// </summary>/// <param name="sFilePath">文件路径</param>private void fileOpen(String sFilePath){// 如果已存在布局管理器,清理之前的设置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("WpfViewWinFormsApp - [{0}]", sFilePath);((DrawControl)winFormsHost.Child).Reinitialize(database);/* userSt.LastOpenedFile = sFilePath;UpdateMenuFile();userSt.Save();HostApplicationServices.WorkingDatabase = database;lm = LayoutManager.Current;lm.LayoutSwitched += new Teigha.DatabaseServices.LayoutEventHandler(reinitGraphDevice);String str = HostApplicationServices.Current.FontMapFileName;//menuStrip.exportToolStripMenuItem.Enabled = true;zoomToExtentsToolStripMenuItem.Enabled = true;zoomWindowToolStripMenuItem.Enabled = true;setAvtiveLayoutToolStripMenuItem.Enabled = true;fileDependencyToolStripMenuItem.Enabled = true;panel1.Enabled = true;pageSetupToolStripMenuItem.Enabled = true;printPreviewToolStripMenuItem.Enabled = true;printToolStripMenuItem.Enabled = true;*/}}private void reinitGraphDevice(object sender, Teigha.DatabaseServices.LayoutEventArgs e){//disableCommand();((DrawControl)winFormsHost.Child).Reinitialize(database);}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){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;}}//if ("_Open" == sHeader)if ("_Exit" == sHeader){this.Close();}if (database != null){if ("_Save" == sHeader){if (database != null)database.Save();}if ("_SaveAs" == sHeader){System.Windows.Forms.SaveFileDialog saveAsFileDialog = new System.Windows.Forms.SaveFileDialog();saveAsFileDialog.Filter = "dwg R24 file format(*.dwg)|*.dwg|dwg R24 file format(*.dwg)|*.dwg|dwg R21 file format(*.dwg)|*.dwg|dwg R18 file format(*.dwg)|*.dwg|dwg R15 file format(*.dwg)|*.dwg|dwg R14 file format(*.dwg)|*.dwg|dwg R13 file format(*.dwg)|*.dwg|dwg R12 file format(*.dwg)|*.dwg";saveAsFileDialog.DefaultExt = "dwg";saveAsFileDialog.RestoreDirectory = true;if (System.Windows.Forms.DialogResult.OK == saveAsFileDialog.ShowDialog()){int version = saveAsFileDialog.FilterIndex % 7;DwgVersion vers = DwgVersion.Current;if (0 == version)vers = DwgVersion.vAC12;else{if (1 == version)vers = DwgVersion.vAC24;else{if (2 == version)vers = DwgVersion.vAC21;else{if (3 == version)vers = DwgVersion.vAC18;else{if (4 == version)vers = DwgVersion.vAC15;else if (5 == version)vers = DwgVersion.vAC14;}}}}//else if (0 == version)if (Math.Truncate((double)saveAsFileDialog.FilterIndex / 7) == 0)database.SaveAs(saveAsFileDialog.FileName, vers);elsedatabase.DxfOut(saveAsFileDialog.FileName, 16, vers);}//if (System.Windows.Forms.DialogResult.OK == saveAsFileDialog.ShowDialog())}//if ("_SaveAs" == sHeader)}//if (database != null)}//if (mItem.IsEnabled)}private void MenuItem_Click_1(object sender, RoutedEventArgs e){}}}
DrawControl.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.Forms;
using Teigha;
using Teigha.DatabaseServices;
using Teigha.GraphicsInterface;
using Teigha.GraphicsSystem;
using Teigha.Runtime;namespace WpfViewWinForms
{public partial class DrawControl : UserControl{// 用于绘图的Graphics对象Graphics graphics;// 布局辅助设备LayoutHelperDevice helperDevice;public DrawControl(){InitializeComponent();}/// <summary>/// 初始化绘图控件/// </summary>/// <param name="database">CAD数据库实例</param>public void Initialize(Database database){try{graphics = Graphics.FromHwnd(this.Handle);// 加载预定义的渲染模块(可以是WinDirectX, WinGLES2或WinOpenGL)using (GsModule gsModule = (GsModule)SystemObjects.DynamicLinker.LoadModule("WinDirectX.txv", false, true)){// 创建图形设备using (Teigha.GraphicsSystem.Device graphichsDevice = gsModule.CreateDevice()){// 设置设备属性using (Dictionary props = graphichsDevice.Properties){// 设置窗口句柄(DirectX设备需要)if (props.Contains("WindowHWND"))props.AtPut("WindowHWND", new RxVariant(this.Handle));// 设置DC句柄(位图设备需要)if (props.Contains("WindowHDC"))props.AtPut("WindowHDC", new RxVariant(graphics.GetHdc()));// 启用双缓冲if (props.Contains("DoubleBufferEnabled"))props.AtPut("DoubleBufferEnabled", new RxVariant(true));// 启用软件隐线消除if (props.Contains("EnableSoftwareHLR"))props.AtPut("EnableSoftwareHLR", new RxVariant(true));// 启用背面剔除if (props.Contains("DiscardBackFaces"))props.AtPut("DiscardBackFaces", new RxVariant(true));}// 设置数据库上下文ContextForDbDatabase ctx = new ContextForDbDatabase(database);ctx.UseGsModel = true;// 设置活动布局视图helperDevice = LayoutHelperDevice.SetupActiveLayoutViews(graphichsDevice, ctx);}}// 设置调色板helperDevice.SetLogicalPalette(Device.DarkPalette);// 设置输出范围Resize();}catch (System.Exception ex){MessageBox.Show(ex.ToString());}}public void Reinitialize(Database database){if (graphics != null)graphics.Dispose();if (helperDevice != null)helperDevice.Dispose();Initialize(database);}public void Deinitialize(){if (graphics != null)graphics.Dispose();if (helperDevice != null)helperDevice.Dispose();}public new void Resize(){if (helperDevice != null){Rectangle r = this.Bounds;r.Offset(-this.Location.X, -this.Location.Y);// HDC assigned to the device corresponds to the whole client area of the panelhelperDevice.OnSize(r);Invalidate();}}private void DrawControl_Paint(object sender, PaintEventArgs e){if (helperDevice != null){try{helperDevice.Update();}catch (System.Exception ex){graphics.DrawString(ex.ToString(), new Font("Arial", 16), new SolidBrush(Color.Black), new PointF(150.0F, 150.0F));}}}}
}
DrawControl.Designer.cs代码
namespace WpfViewWinForms
{partial class DrawControl{/// <summary> /// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <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 (graphics != null)graphics.Dispose();if (helperDevice != null)helperDevice.Dispose();if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Component Designer generated code/// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor./// </summary>private void InitializeComponent(){this.SuspendLayout();// // DrawControl// this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.Name = "DrawControl";this.Paint += new System.Windows.Forms.PaintEventHandler(this.DrawControl_Paint);this.ResumeLayout(false);}#endregion}
}