using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Windows.Forms;
// 为避免命名冲突,创建别名
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
using SystemException = System.Exception;
using SystemImage = System.Drawing.Image;
using SystemBitmap = System.Drawing.Bitmap;
[assembly: CommandClass(typeof(CadLibraryPlugin.LibraryCommands))]
namespace CadLibraryPlugin
{
public class LibraryCommands
{
[CommandMethod("TK")]
public void ShowLibrary()
{
try
{
AcadApp.ShowModelessDialog(AcadApp.MainWindow.Handle, new LibraryForm(), false);
}
catch (SystemException ex)
{
MessageBox.Show($"打开图库时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
// 图块信息类
public class BlockInfo
{
public string Name { get; set; }
public string Path { get; set; }
public bool IsSystemBlock { get; set; }
public string OriginalFileName { get; set; }
public ObjectId BlockId { get; set; }
public string DisplayName { get; set; }
}
public partial class LibraryForm : Form
{
private string _userBlocksPath;
private string _selectedBlockName = string.Empty;
private bool _isSystemBlock = false;
private string _selectedBlockPath = string.Empty;
private ObjectId _selectedBlockId = ObjectId.Null;
private Document _currentDoc;
// 缩放功能变量
private float _zoomFactor = 1.0f;
private const float _zoomStep = 0.1f;
private const float _minZoom = 0.1f;
private const float _maxZoom = 5.0f;
private SystemImage _originalPreviewImage;
// 当前显示模式:0=系统图块,1=用户图块
private int _currentDisplayMode = 0;
// 系统图块名称列表(从嵌入图块中获取)
private readonly HashSet<string> _systemBlockNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"90度阳角型钢",
"ScaffoldPole90度阳角型钢",
"ScaffoldPole90度阳角配件",
"ScaffoldPole三角架",
"ScaffoldPole传统连墙件",
"ScaffoldPole单片钢踏板",
"ScaffoldPole卸料平台立面布置大样图",
"ScaffoldPole卸料钢平台大样图",
"ScaffoldPole双槽钢拖梁",
"ScaffoldPole双槽钢拖梁1350mm",
"ScaffoldPole双槽钢拖梁1650mm",
"ScaffoldPole右45度角型钢",
"ScaffoldPole固定桩",
"ScaffoldPole外架临时支撑大样图",
"ScaffoldPole外架剖面大样图",
"ScaffoldPole外架斜拉杆1200mm",
"ScaffoldPole外架斜拉杆1500mm",
"ScaffoldPole外架斜拉杆1800mm",
"ScaffoldPole外架斜拉杆600mm",
"ScaffoldPole外架斜拉杆900mm",
"ScaffoldPole工字钢与联梁加固节点图",
"ScaffoldPole工字钢连梁",
"ScaffoldPole左45度角型钢",
"ScaffoldPole底托",
"ScaffoldPole底托1",
"ScaffoldPole底托螺母",
"ScaffoldPole悬挑型钢",
"ScaffoldPole悬挑架用材和拉杆大样图",
"ScaffoldPole扣件",
"ScaffoldPole扣件2",
"ScaffoldPole扣件900mm",
"ScaffoldPole新型连墙件",
"ScaffoldPole方钢",
"ScaffoldPole方钢1000mm",
"ScaffoldPole方钢50x50x3",
"ScaffoldPole施工电梯平面大样图",
"ScaffoldPole施工电梯立面大样图",
"ScaffoldPole木方40x90",
"ScaffoldPole横杆1200mm",
"ScaffoldPole横杆1500mm",
"ScaffoldPole横杆1800mm",
"ScaffoldPole横杆300mm",
"ScaffoldPole横杆600mm",
"ScaffoldPole横杆900mm",
"ScaffoldPole水平斜拉杆1200mm",
"ScaffoldPole水平斜拉杆1500mm",
"ScaffoldPole水平斜拉杆1800mm",
"ScaffoldPole水平斜拉杆600mm",
"ScaffoldPole水平斜拉杆900mm",
"ScaffoldPole爬梯样板",
"ScaffoldPole立杆",
"ScaffoldPole立杆1000mm",
"ScaffoldPole立杆1500mm",
"ScaffoldPole立杆2000mm",
"ScaffoldPole立杆200mm",
"ScaffoldPole立杆2500mm",
"ScaffoldPole立杆350mm",
"ScaffoldPole立杆500mm",
"ScaffoldPole立横杆1200mm",
"ScaffoldPole立横杆1500mm",
"ScaffoldPole立横杆1800mm",
"ScaffoldPole立横杆300mm",
"ScaffoldPole立横杆600mm",
"ScaffoldPole立横杆900mm",
"ScaffoldPole竖向斜拉杆1200mm",
"ScaffoldPole竖向斜拉杆1500mm",
"ScaffoldPole竖向斜拉杆1800mm",
"ScaffoldPole竖向斜拉杆600mm",
"ScaffoldPole竖向斜拉杆900mm",
"ScaffoldPole钢管+扣件",
"ScaffoldPole钢管",
"ScaffoldPole钢踏板1200mm",
"ScaffoldPole钢踏板1500mm",
"ScaffoldPole钢踏板1800mm",
"ScaffoldPole钢踏板900mm",
"ScaffoldPole阳角斜拉大样图",
"ScaffoldPole顶托",
"ScaffoldPole顶托1",
"ScaffoldPole顶托2",
"ScaffoldPole顶托剖面",
"ScaffoldPole顶托螺母"
};
public LibraryForm()
{
InitializeComponent();
InitializeForm();
}
private void InitializeForm()
{
try
{
// 为预览控件添加鼠标滚轮事件处理
pictureBoxPreview.MouseWheel += pictureBoxPreview_MouseWheel;
pictureBoxPreview.MouseEnter += (s, e) => pictureBoxPreview.Focus();
// 绑定按钮事件
btnSystemBlocks.Click += btnSystemBlocks_Click;
btnUserBlocks.Click += btnUserBlocks_Click;
btnRefresh.Click += btnRefresh_Click;
btnInsert.Click += btnInsert_Click;
btnDelete.Click += btnDelete_Click;
btnAdd.Click += btnAdd_Click;
// 绑定树形视图事件
treeViewDirectory.AfterSelect += treeViewDirectory_AfterSelect;
InitializePaths();
_currentDoc = AcadApp.DocumentManager.MdiActiveDocument;
// 默认显示系统图块
LoadSystemBlocks();
// 初始禁用删除按钮
btnDelete.Enabled = false;
}
catch (SystemException ex)
{
MessageBox.Show($"初始化图库窗体时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void InitializePaths()
{
try
{
// 改进用户图块路径处理,优先使用无中文路径
_userBlocksPath = GetBestUserPath();
Directory.CreateDirectory(_userBlocksPath);
// 显示当前使用的路径,方便用户确认
System.Diagnostics.Debug.WriteLine($"当前用户图库路径: {_userBlocksPath}");
}
catch (SystemException ex)
{
MessageBox.Show($"初始化路径时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private string GetBestUserPath()
{
// 尝试多个路径,优先选择无中文的路径
List<string> potentialPaths = new List<string>
{
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "CADLibrary"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CADLibrary"),
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "CADLibrary")
};
foreach (var path in potentialPaths)
{
try
{
// 检查路径是否可写
string testFile = Path.Combine(path, "test_write_permission.tmp");
Directory.CreateDirectory(path);
File.WriteAllText(testFile, "test");
File.Delete(testFile);
// 检查路径是否包含中文字符
if (!ContainsChineseCharacters(path))
{
return path;
}
}
catch
{
continue;
}
}
return potentialPaths[0];
}
private bool ContainsChineseCharacters(string text)
{
return text.Any(c => c >= 0x4e00 && c <= 0x9fff);
}
private void LoadSystemBlocks()
{
try
{
treeViewDirectory.Nodes.Clear();
_currentDisplayMode = 0;
// 更新按钮状态
UpdateButtonStates();
TreeNode systemNode = new TreeNode("系统图库");
treeViewDirectory.Nodes.Add(systemNode);
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
if (doc == null)
{
systemNode.Nodes.Add("没有打开的AutoCAD文档");
return;
}
using (DocumentLock docLock = doc.LockDocument())
using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
if (bt == null)
{
systemNode.Nodes.Add("无法访问块表");
return;
}
int loadedCount = 0;
var systemBlocks = new List<(string Name, ObjectId BlockId)>();
foreach (ObjectId blockId in bt)
{
BlockTableRecord btr = tr.GetObject(blockId, OpenMode.ForRead) as BlockTableRecord;
if (btr != null && !btr.IsLayout && _systemBlockNames.Contains(btr.Name))
{
systemBlocks.Add((btr.Name, blockId));
loadedCount++;
}
}
// 按名称排序
systemBlocks.Sort((x, y) => string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase));
if (loadedCount == 0)
{
systemNode.Nodes.Add("未找到系统图块");
systemNode.Nodes.Add("请使用 QUICKINSERT 命令预加载图块");
}
else
{
// 添加排序后的图块,显示为"序号.图块名称"
for (int i = 0; i < systemBlocks.Count; i++)
{
try
{
string displayName = $"{i + 1}.{GetOptimizedBlockDisplayName(systemBlocks[i].Name)}";
TreeNode node = new TreeNode(displayName);
node.Tag = new BlockInfo
{
Name = systemBlocks[i].Name,
Path = null, // 系统图块没有文件路径
IsSystemBlock = true,
OriginalFileName = systemBlocks[i].Name,
BlockId = systemBlocks[i].BlockId,
DisplayName = displayName
};
systemNode.Nodes.Add(node);
}
catch (SystemException ex)
{
System.Diagnostics.Debug.WriteLine($"加载系统图块失败 {systemBlocks[i].Name}: {ex.Message}");
}
}
}
tr.Commit();
}
treeViewDirectory.ExpandAll();
}
catch (SystemException ex)
{
MessageBox.Show($"加载系统图块时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private string GetOptimizedBlockDisplayName(string originalName)
{
// 移除 ScaffoldPole 前缀
const string prefix = "ScaffoldPole";
if (!string.IsNullOrEmpty(originalName) &&
originalName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
string trimmedName = originalName.Substring(prefix.Length);
// 特殊处理:如果去除前缀后为空,则返回原名称
if (string.IsNullOrEmpty(trimmedName))
return originalName;
return trimmedName;
}
return originalName;
}
// ==================== 用户图块相关功能 ====================
private void LoadUserBlocks()
{
try
{
treeViewDirectory.Nodes.Clear();
_currentDisplayMode = 1;
// 更新按钮状态
UpdateButtonStates();
TreeNode userNode = new TreeNode("用户图库");
treeViewDirectory.Nodes.Add(userNode);
if (Directory.Exists(_userBlocksPath))
{
string[] userFiles = Directory.GetFiles(_userBlocksPath, "*.dwg");
if (userFiles.Length == 0)
{
userNode.Nodes.Add("暂无用户图块");
userNode.Nodes.Add("点击\"新图入库\"按钮添加图块");
}
else
{
foreach (string file in userFiles)
{
try
{
string blockName = Path.GetFileNameWithoutExtension(file);
TreeNode node = new TreeNode(blockName);
node.Tag = new BlockInfo
{
Name = blockName,
Path = file,
IsSystemBlock = false,
OriginalFileName = blockName,
BlockId = ObjectId.Null,
DisplayName = blockName
};
userNode.Nodes.Add(node);
}
catch (SystemException ex)
{
System.Diagnostics.Debug.WriteLine($"加载用户图块失败 {file}: {ex.Message}");
}
}
}
}
else
{
userNode.Nodes.Add("用户图库目录不存在");
}
treeViewDirectory.ExpandAll();
}
catch (SystemException ex)
{
MessageBox.Show($"加载用户图块时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnAdd_Click(object sender, EventArgs e)
{
Document doc = null;
try
{
doc = AcadApp.DocumentManager.MdiActiveDocument;
if (doc == null)
{
MessageBox.Show("没有打开的AutoCAD文档!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Editor ed = doc.Editor;
PromptSelectionOptions selOpts = new PromptSelectionOptions();
selOpts.MessageForAdding = "选择要入库的对象: ";
PromptSelectionResult selRes = ed.GetSelection(selOpts);
if (selRes.Status != PromptStatus.OK) return;
if (selRes.Value.Count == 0)
{
MessageBox.Show("没有选择任何对象!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
PromptPointOptions ptOpts = new PromptPointOptions("\n请选择图块基点: ");
PromptPointResult ptRes = ed.GetPoint(ptOpts);
if (ptRes.Status != PromptStatus.OK) return;
Point3d basePoint = ptRes.Value;
using (InputBlockNameForm inputForm = new InputBlockNameForm())
{
if (inputForm.ShowDialog() == DialogResult.OK && !string.IsNullOrEmpty(inputForm.BlockName))
{
string blockName = inputForm.BlockName.Trim();
if (string.IsNullOrEmpty(blockName))
{
MessageBox.Show("图块名称不能为空!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 检查图块名称长度
if (blockName.Length < 2)
{
MessageBox.Show("图块名称至少需要2个字符!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
blockName = CleanBlockName(blockName);
string filePath = Path.Combine(_userBlocksPath, $"{blockName}.dwg");
if (File.Exists(filePath))
{
if (MessageBox.Show($"图块 '{blockName}' 已存在,是否覆盖?", "确认覆盖",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
{
return;
}
}
// 使用简化版的保存方法,避免复杂操作导致的错误
bool saveSuccess = SimpleSaveBlock(doc, selRes.Value, basePoint, filePath, blockName);
if (saveSuccess)
{
// 如果当前显示的是用户图块,则刷新显示
if (_currentDisplayMode == 1)
{
LoadUserBlocks();
}
ed.WriteMessage($"\n图块 '{blockName}' 已成功入库!");
MessageBox.Show($"图块 '{blockName}' 已成功入库!", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
// 如果保存失败,尝试使用备用方法
if (TryAlternativeSaveMethod(doc, selRes.Value, basePoint, filePath, blockName))
{
if (_currentDisplayMode == 1)
{
LoadUserBlocks();
}
ed.WriteMessage($"\n图块 '{blockName}' 已成功入库!");
MessageBox.Show($"图块 '{blockName}' 已成功入库!", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show($"图块 '{blockName}' 保存失败!请检查文件路径和权限。", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
}
catch (SystemException ex)
{
MessageBox.Show($"保存图块时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private bool SimpleSaveBlock(Document doc, SelectionSet selectionSet, Point3d basePoint, string filePath, string blockName)
{
try
{
string directory = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
using (Database newDb = new Database(true, true))
{
using (Transaction tr = newDb.TransactionManager.StartTransaction())
{
// 设置单位
newDb.Insunits = doc.Database.Insunits;
// 克隆选择的对象到新数据库
ObjectIdCollection objectIds = new ObjectIdCollection(selectionSet.GetObjectIds());
IdMapping mapping = new IdMapping();
// 使用WblockCloneObjects克隆对象
doc.Database.WblockCloneObjects(objectIds, newDb.CurrentSpaceId, mapping,
DuplicateRecordCloning.Replace, false);
// 重要:将所有对象移动到以原点为中心
MoveAllEntitiesToOrigin(newDb, basePoint);
tr.Commit();
}
// 保存新数据库到文件
newDb.SaveAs(filePath, DwgVersion.Current);
}
return File.Exists(filePath) && new FileInfo(filePath).Length > 0;
}
catch (SystemException ex)
{
System.Diagnostics.Debug.WriteLine($"简单保存方法失败: {ex.Message}");
return false;
}
}
// 将所有实体移动到原点
private void MoveAllEntitiesToOrigin(Database db, Point3d originalBasePoint)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord modelSpace = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord;
if (modelSpace != null)
{
// 计算移动向量(从原始基点到原点)
Vector3d moveVector = new Vector3d(-originalBasePoint.X, -originalBasePoint.Y, -originalBasePoint.Z);
foreach (ObjectId objId in modelSpace)
{
Entity entity = tr.GetObject(objId, OpenMode.ForWrite) as Entity;
if (entity != null)
{
entity.TransformBy(Matrix3d.Displacement(moveVector));
}
}
}
tr.Commit();
}
}
private bool TryAlternativeSaveMethod(Document doc, SelectionSet selectionSet, Point3d basePoint, string filePath, string blockName)
{
try
{
// 备用方法:使用命令行操作
string escapedPath = filePath.Replace("\\", "\\\\");
// 先创建块定义
string tempBlockName = "_TEMP_SAVE_" + Guid.NewGuid().ToString("N").Substring(0, 8);
// 构建命令序列
string commands = $@"
(command ""_-BLOCK"" ""{tempBlockName}"" ""{basePoint.X},{basePoint.Y},0"" ""Previous"" """" )
(command ""_-WBLOCK"" ""{escapedPath}"" ""{tempBlockName}"" )
(command ""_-PURGE"" ""Blocks"" ""{tempBlockName}"" ""N"" )
";
doc.SendStringToExecute(commands, true, false, true);
// 等待文件创建
int retryCount = 0;
while (retryCount < 20)
{
if (File.Exists(filePath))
{
try
{
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.Length > 100)
{
return true;
}
}
catch
{
// 继续等待
}
}
System.Threading.Thread.Sleep(500);
retryCount++;
}
return File.Exists(filePath);
}
catch (SystemException ex)
{
System.Diagnostics.Debug.WriteLine($"备用保存方法失败: {ex.Message}");
return false;
}
}
private string CleanBlockName(string name)
{
char[] invalidChars = Path.GetInvalidFileNameChars();
string cleaned = string.Join("_", name.Split(invalidChars, StringSplitOptions.RemoveEmptyEntries));
// 确保名称不为空
if (string.IsNullOrEmpty(cleaned))
{
cleaned = "Block_" + Guid.NewGuid().ToString("N").Substring(0, 6);
}
return cleaned;
}
private void btnDelete_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrEmpty(_selectedBlockName) || _isSystemBlock)
{
MessageBox.Show("请选择一个用户图块进行删除!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (MessageBox.Show($"确定要删除图块 '{_selectedBlockName}' 吗?", "确认删除",
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
if (File.Exists(_selectedBlockPath))
{
File.Delete(_selectedBlockPath);
LoadUserBlocks();
ClearPreview();
MessageBox.Show("图块已成功删除!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("图块文件不存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
catch (SystemException ex)
{
MessageBox.Show($"删除图块时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnInsert_Click(object sender, EventArgs e)
{
try
{
if (string.IsNullOrEmpty(_selectedBlockName))
{
MessageBox.Show("请先选择一个图块!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
if (doc == null)
{
MessageBox.Show("没有打开的AutoCAD文档!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
using (DocumentLock docLock = doc.LockDocument())
{
Editor ed = doc.Editor;
PromptPointOptions ptOpts = new PromptPointOptions("\n请指定插入点: ");
PromptPointResult ptRes = ed.GetPoint(ptOpts);
if (ptRes.Status != PromptStatus.OK) return;
Point3d insertPoint = ptRes.Value;
if (_isSystemBlock)
{
// 插入系统图块(从当前文档的块表中)
if (InsertSystemBlock(doc, insertPoint, _selectedBlockId, _selectedBlockName))
{
ed.WriteMessage($"\n系统图块 '{_selectedBlockName}' 已成功插入!");
}
else
{
MessageBox.Show($"系统图块 '{_selectedBlockName}' 插入失败!", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
// 插入用户图块(从文件)
if (!File.Exists(_selectedBlockPath))
{
MessageBox.Show("图块文件不存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (InsertUserBlock(doc, insertPoint, _selectedBlockPath, _selectedBlockName))
{
ed.WriteMessage($"\n用户图块 '{_selectedBlockName}' 已成功插入!");
}
else
{
MessageBox.Show($"用户图块 '{_selectedBlockName}' 插入失败!", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
catch (SystemException ex)
{
MessageBox.Show($"插入图块时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private bool InsertSystemBlock(Document doc, Point3d insertPoint, ObjectId blockId, string blockName)
{
try
{
using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
if (bt == null) return false;
// 创建块引用
BlockTableRecord currentSpace = tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
if (currentSpace == null) return false;
BlockReference blockRef = new BlockReference(insertPoint, blockId);
currentSpace.AppendEntity(blockRef);
tr.AddNewlyCreatedDBObject(blockRef, true);
tr.Commit();
return true;
}
}
catch (SystemException ex)
{
System.Diagnostics.Debug.WriteLine($"插入系统块失败: {ex.Message}");
return false;
}
}
private bool InsertUserBlock(Document doc, Point3d insertPoint, string blockPath, string blockName)
{
try
{
using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
if (bt == null) return false;
// 使用原始文件名作为块名
string originalBlockName = Path.GetFileNameWithoutExtension(blockPath);
// 检查块是否已存在
if (!bt.Has(originalBlockName))
{
// 从文件插入块定义
using (Database sourceDb = new Database(false, true))
{
try
{
sourceDb.ReadDwgFile(blockPath, FileShare.Read, true, "");
// 插入块定义到当前数据库
ObjectIdCollection mapping = new ObjectIdCollection();
doc.Database.Insert(originalBlockName, sourceDb, true);
}
catch (SystemException ex)
{
System.Diagnostics.Debug.WriteLine($"插入块定义失败: {ex.Message}");
return false;
}
}
}
// 创建块引用
BlockTableRecord currentSpace = tr.GetObject(doc.Database.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
if (currentSpace == null) return false;
BlockReference blockRef = new BlockReference(insertPoint, bt[originalBlockName]);
currentSpace.AppendEntity(blockRef);
tr.AddNewlyCreatedDBObject(blockRef, true);
tr.Commit();
return true;
}
}
catch (SystemException ex)
{
System.Diagnostics.Debug.WriteLine($"插入用户块失败: {ex.Message}");
return false;
}
}
// ==================== 通用功能 ====================
private void UpdateButtonStates()
{
// 更新按钮外观以反映当前模式
if (_currentDisplayMode == 0)
{
// 系统图块模式:禁用"新图入库"和"删除"按钮
btnSystemBlocks.BackColor = SystemColors.Highlight;
btnSystemBlocks.ForeColor = SystemColors.HighlightText;
btnUserBlocks.BackColor = SystemColors.Control;
btnUserBlocks.ForeColor = SystemColors.ControlText;
btnAdd.Enabled = false;
btnDelete.Enabled = false;
// 设置禁用状态的视觉效果
btnAdd.BackColor = SystemColors.Control;
btnAdd.ForeColor = SystemColors.GrayText;
btnDelete.BackColor = SystemColors.Control;
btnDelete.ForeColor = SystemColors.GrayText;
}
else
{
// 用户图块模式:启用"新图入库"按钮,"删除"按钮根据选择状态决定
btnUserBlocks.BackColor = SystemColors.Highlight;
btnUserBlocks.ForeColor = SystemColors.HighlightText;
btnSystemBlocks.BackColor = SystemColors.Control;
btnSystemBlocks.ForeColor = SystemColors.ControlText;
btnAdd.Enabled = true;
// 设置启用状态的视觉效果
btnAdd.BackColor = SystemColors.Control;
btnAdd.ForeColor = SystemColors.ControlText;
// 删除按钮状态由当前选择决定
btnDelete.Enabled = !_isSystemBlock && !string.IsNullOrEmpty(_selectedBlockName);
if (btnDelete.Enabled)
{
btnDelete.BackColor = SystemColors.Control;
btnDelete.ForeColor = SystemColors.ControlText;
}
else
{
btnDelete.BackColor = SystemColors.Control;
btnDelete.ForeColor = SystemColors.GrayText;
}
}
// 选用按钮始终可用
btnInsert.Enabled = !string.IsNullOrEmpty(_selectedBlockName);
}
private void treeViewDirectory_AfterSelect(object sender, TreeViewEventArgs e)
{
try
{
if (e.Node.Tag is BlockInfo blockInfo)
{
_selectedBlockName = blockInfo.Name;
_selectedBlockPath = blockInfo.Path;
_selectedBlockId = blockInfo.BlockId;
_isSystemBlock = blockInfo.IsSystemBlock;
UpdateBlockPreview(blockInfo);
// 更新按钮状态
UpdateButtonStates();
}
else
{
ClearPreview();
_selectedBlockName = string.Empty;
_selectedBlockPath = string.Empty;
_selectedBlockId = ObjectId.Null;
// 更新按钮状态
UpdateButtonStates();
}
}
catch (SystemException ex)
{
MessageBox.Show($"选择图块时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void UpdateBlockPreview(BlockInfo blockInfo)
{
ClearPreview();
try
{
// 显示图块名称
string displayText = $"预览: {blockInfo.DisplayName}";
labelPreviewInfo.Text = displayText;
if (blockInfo.IsSystemBlock)
{
// 系统图块预览 - 从当前文档的块定义生成预览
GenerateSystemBlockPreview(blockInfo);
}
else
{
// 用户图块预览 - 从文件生成预览
if (!File.Exists(blockInfo.Path))
{
labelPreviewInfo.Text = $"{displayText} (文件不存在)";
return;
}
// 使用AutoCAD的数据库获取缩略图
using (Database db = new Database(false, true))
{
db.ReadDwgFile(blockInfo.Path, FileShare.Read, true, "");
using (SystemBitmap thumbnail = db.ThumbnailBitmap)
{
if (thumbnail != null)
{
_originalPreviewImage = new SystemBitmap(thumbnail);
pictureBoxPreview.Image = new SystemBitmap(_originalPreviewImage);
_zoomFactor = 1.0f;
}
else
{
labelPreviewInfo.Text = $"{displayText} (无法生成预览)";
}
}
}
}
}
catch (SystemException ex)
{
labelPreviewInfo.Text = $"预览加载失败: {ex.Message}";
}
}
private void GenerateSystemBlockPreview(BlockInfo blockInfo)
{
try
{
Document doc = AcadApp.DocumentManager.MdiActiveDocument;
if (doc == null) return;
using (DocumentLock docLock = doc.LockDocument())
using (Transaction tr = doc.Database.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable;
if (bt == null) return;
if (bt.Has(blockInfo.Name))
{
BlockTableRecord btr = tr.GetObject(bt[blockInfo.Name], OpenMode.ForRead) as BlockTableRecord;
if (btr != null)
{
// 使用块定义的缩略图
using (SystemBitmap thumbnail = btr.PreviewIcon)
{
if (thumbnail != null)
{
_originalPreviewImage = new SystemBitmap(thumbnail);
pictureBoxPreview.Image = new SystemBitmap(_originalPreviewImage);
_zoomFactor = 1.0f;
}
else
{
labelPreviewInfo.Text = $"预览: {blockInfo.DisplayName} (系统图块,无法生成预览)";
}
}
}
else
{
labelPreviewInfo.Text = $"预览: {blockInfo.DisplayName} (系统图块,无法访问块定义)";
}
}
else
{
labelPreviewInfo.Text = $"预览: {blockInfo.DisplayName} (系统图块,块定义不存在)";
}
tr.Commit();
}
}
catch (SystemException ex)
{
labelPreviewInfo.Text = $"预览: {blockInfo.DisplayName} (系统图块预览生成失败)";
System.Diagnostics.Debug.WriteLine($"系统图块预览失败 {blockInfo.Name}: {ex.Message}");
}
}
private void pictureBoxPreview_MouseWheel(object sender, MouseEventArgs e)
{
if (_originalPreviewImage == null) return;
if (!pictureBoxPreview.Focused)
{
pictureBoxPreview.Focus();
return;
}
if (e.Delta > 0)
_zoomFactor = Math.Min(_zoomFactor + _zoomStep, _maxZoom);
else
_zoomFactor = Math.Max(_zoomFactor - _zoomStep, _minZoom);
ApplyZoom(e);
}
private void ApplyZoom(MouseEventArgs e)
{
if (_originalPreviewImage == null) return;
if (pictureBoxPreview.Image != null && pictureBoxPreview.Image != _originalPreviewImage)
{
pictureBoxPreview.Image.Dispose();
}
int newWidth = (int)(_originalPreviewImage.Width * _zoomFactor);
int newHeight = (int)(_originalPreviewImage.Height * _zoomFactor);
SystemBitmap scaledImage = new SystemBitmap(newWidth, newHeight);
using (Graphics g = Graphics.FromImage(scaledImage))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawImage(_originalPreviewImage, 0, 0, newWidth, newHeight);
}
pictureBoxPreview.Image = scaledImage;
}
private void ClearPreview()
{
if (pictureBoxPreview.Image != null && pictureBoxPreview.Image != _originalPreviewImage)
{
pictureBoxPreview.Image.Dispose();
}
if (_originalPreviewImage != null)
{
_originalPreviewImage.Dispose();
}
pictureBoxPreview.Image = null;
_originalPreviewImage = null;
labelPreviewInfo.Text = "预览: 无";
_zoomFactor = 1.0f;
}
private void btnRefresh_Click(object sender, EventArgs e)
{
try
{
if (_currentDisplayMode == 0)
LoadSystemBlocks();
else
LoadUserBlocks();
ClearPreview();
MessageBox.Show("图库已刷新!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (SystemException ex)
{
MessageBox.Show($"刷新图库时发生错误: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void btnSystemBlocks_Click(object sender, EventArgs e)
{
LoadSystemBlocks();
ClearPreview();
}
private void btnUserBlocks_Click(object sender, EventArgs e)
{
LoadUserBlocks();
ClearPreview();
}
}
public partial class InputBlockNameForm : Form
{
public string BlockName { get; private set; }
public InputBlockNameForm()
{
InitializeComponent();
InitializeForm();
}
private void InitializeForm()
{
// 绑定按钮事件
btnSave.Click += btnSave_Click;
btnCancel.Click += btnCancel_Click;
textBoxBlockName.KeyPress += textBoxBlockName_KeyPress;
}
private void btnSave_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(textBoxBlockName.Text))
{
MessageBox.Show("请输入图块名称!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
// 检查名称长度
if (textBoxBlockName.Text.Trim().Length < 2)
{
MessageBox.Show("图块名称至少需要2个字符!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
BlockName = textBoxBlockName.Text.Trim();
DialogResult = DialogResult.OK;
Close();
}
private void btnCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
private void textBoxBlockName_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
btnSave_Click(sender, e);
else if (e.KeyChar == (char)Keys.Escape)
btnCancel_Click(sender, e);
}
}
}
自动将以下图块导出为*.TKW格式至插件目录下“ScaffoldBlocks”文件夹内(导出文件名称去除“ScaffoldPole”),以上预览功能预览的图像路径改为插件目录下“ScaffoldBlocks”文件夹内*.TKW格式;例如:系统图库目录中选择“90度阳角型钢”预览窗口就会显示“90度阳角型钢.TKW”图形进行预览
// 系统图块名称列表(从嵌入图块中获取)
private readonly HashSet<string> _systemBlockNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"90度阳角型钢",
"ScaffoldPole90度阳角型钢",
"ScaffoldPole90度阳角配件",
"ScaffoldPole三角架",
"ScaffoldPole传统连墙件",
"ScaffoldPole单片钢踏板",
"ScaffoldPole卸料平台立面布置大样图",
"ScaffoldPole卸料钢平台大样图",
"ScaffoldPole双槽钢拖梁",
"ScaffoldPole双槽钢拖梁1350mm",
"ScaffoldPole双槽钢拖梁1650mm",
"ScaffoldPole右45度角型钢",
"ScaffoldPole固定桩",
"ScaffoldPole外架临时支撑大样图",
"ScaffoldPole外架剖面大样图",
"ScaffoldPole外架斜拉杆1200mm",
"ScaffoldPole外架斜拉杆1500mm",
"ScaffoldPole外架斜拉杆1800mm",
"ScaffoldPole外架斜拉杆600mm",
"ScaffoldPole外架斜拉杆900mm",
"ScaffoldPole工字钢与联梁加固节点图",
"ScaffoldPole工字钢连梁",
"ScaffoldPole左45度角型钢",
"ScaffoldPole底托",
"ScaffoldPole底托1",
"ScaffoldPole底托螺母",
"ScaffoldPole悬挑型钢",
"ScaffoldPole悬挑架用材和拉杆大样图",
"ScaffoldPole扣件",
"ScaffoldPole扣件2",
"ScaffoldPole扣件900mm",
"ScaffoldPole新型连墙件",
"ScaffoldPole方钢",
"ScaffoldPole方钢1000mm",
"ScaffoldPole方钢50x50x3",
"ScaffoldPole施工电梯平面大样图",
"ScaffoldPole施工电梯立面大样图",
"ScaffoldPole木方40x90",
"ScaffoldPole横杆1200mm",
"ScaffoldPole横杆1500mm",
"ScaffoldPole横杆1800mm",
"ScaffoldPole横杆300mm",
"ScaffoldPole横杆600mm",
"ScaffoldPole横杆900mm",
"ScaffoldPole水平斜拉杆1200mm",
"ScaffoldPole水平斜拉杆1500mm",
"ScaffoldPole水平斜拉杆1800mm",
"ScaffoldPole水平斜拉杆600mm",
"ScaffoldPole水平斜拉杆900mm",
"ScaffoldPole爬梯样板",
"ScaffoldPole立杆",
"ScaffoldPole立杆1000mm",
"ScaffoldPole立杆1500mm",
"ScaffoldPole立杆2000mm",
"ScaffoldPole立杆200mm",
"ScaffoldPole立杆2500mm",
"ScaffoldPole立杆350mm",
"ScaffoldPole立杆500mm",
"ScaffoldPole立横杆1200mm",
"ScaffoldPole立横杆1500mm",
"ScaffoldPole立横杆1800mm",
"ScaffoldPole立横杆300mm",
"ScaffoldPole立横杆600mm",
"ScaffoldPole立横杆900mm",
"ScaffoldPole竖向斜拉杆1200mm",
"ScaffoldPole竖向斜拉杆1500mm",
"ScaffoldPole竖向斜拉杆1800mm",
"ScaffoldPole竖向斜拉杆600mm",
"ScaffoldPole竖向斜拉杆900mm",
"ScaffoldPole钢管+扣件",
"ScaffoldPole钢管",
"ScaffoldPole钢踏板1200mm",
"ScaffoldPole钢踏板1500mm",
"ScaffoldPole钢踏板1800mm",
"ScaffoldPole钢踏板900mm",
"ScaffoldPole阳角斜拉大样图",
"ScaffoldPole顶托",
"ScaffoldPole顶托1",
"ScaffoldPole顶托2",
"ScaffoldPole顶托剖面",
"ScaffoldPole顶托螺母"
};