📋 目录
🎯 项目概述
这是一个基于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
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代码:
csharp
<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>
csharp
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);
}
}
// 设置环境变量PATH
String 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);
else
database.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
csharp
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 panel
helperDevice.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代码
csharp
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
}
}