需求:选择其他CAD文件,展示选择CAD文件中所有的块定义,然后选择需要插入的块,鼠标有块定义的跟随,点击放置块定义。
实现效果
代码
1.定义BlockJig拖拽类
public class BlockJig : EntityJig
{
private Point3d _currentPosition;
private Point3d _originalPosition;
public BlockJig(Entity entity, Point3d originalPosition) : base(entity)
{
_originalPosition = originalPosition;
_currentPosition = originalPosition;
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions opts = new JigPromptPointOptions("\n指定放置点:");
opts.UseBasePoint = true;
opts.BasePoint = _originalPosition;
opts.UserInputControls = UserInputControls.Accept3dCoordinates | UserInputControls.NullResponseAccepted;
PromptPointResult result = prompts.AcquirePoint(opts);
if (result.Status == PromptStatus.OK)
{
_currentPosition = result.Value;
return SamplerStatus.OK;
}
else if (result.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
return SamplerStatus.NoChange;
}
protected override bool Update()
{
try
{
(Entity as BlockReference).Position = _currentPosition;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ex.StackTrace);
}
return true;
}
}
2.界面
界面使用了handycontrol控件库,大家使用的时候记得先安装handycontrol的NuGet包
<Window
x:Class="CADTools.Views.InsertExternalBlockView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:hc="https://handyorg.github.io/handycontrol"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:CADTools.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="插入外部图纸中的块"
Width="400"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml" />
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closed">
<i:InvokeCommandAction Command="{Binding ClosedCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Margin="10,0" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="CAD图纸位置:" />
<TextBox
Width="200"
Height="30"
Margin="10,0"
Text="{Binding CADPath, UpdateSourceTrigger=PropertyChanged}" />
<Button
Command="{Binding SelectCommand}"
Content="选择"
Style="{StaticResource ButtonPrimary}" />
</StackPanel>
<ListBox
Grid.Row="1"
Margin="10"
ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Button
Width="110"
Height="110"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding DataContext.BlockClikCommand, RelativeSource={RelativeSource AncestorType=Window, AncestorLevel=1, Mode=FindAncestor}}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, AncestorLevel=1, Mode=FindAncestor}, Path=DataContext}">
<Button.Background>
<ImageBrush ImageSource="{Binding Image}" />
</Button.Background>
</Button>
<TextBlock
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding BlockName, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
3.定义ViewModel类
public class InsertExternalBlockViewModel : BaseNotify
{
#region UI
private string cadPath;
public string CADPath
{
get { return cadPath; }
set { cadPath = value; this.RaisePropertyChanged(); }
}
private ObservableCollection<BlockModel> items = new ObservableCollection<BlockModel>();
public ObservableCollection<BlockModel> Items
{
get { return items; }
set { items = value; this.RaisePropertyChanged(); }
}
#endregion
#region Method
/// <summary>
/// 选择按钮
/// </summary>
public DelegateCommand SelectCommand { get; set; }
/// <summary>
/// 图片点击按钮
/// </summary>
public DelegateCommand BlockClikCommand { get; set; }
/// <summary>
/// 关闭按钮
/// </summary>
public DelegateCommand ClosedCommand { get; set; }
private void ClosedExecute(object obj)
{
_loadDB?.Dispose();
}
private void BlockCilkExecute(object obj)
{
BlockModel model = obj as BlockModel;
if (model == null) return;
Document doc = Application.DocumentManager.MdiActiveDocument;
WindowMethod.SetFocus(doc.Window.Handle);
Database db = doc.Database;
Editor ed = doc.Editor;
DocumentLock l = doc.LockDocument();
using (Transaction trans = _loadDB.TransactionManager.StartTransaction())
{
try
{
BlockTable bt = trans.GetObject(_loadDB.BlockTableId, OpenMode.ForRead) as BlockTable;
ObjectIdCollection ids = new ObjectIdCollection
{
bt[model.BlockName]
};
//复制临时数据库中的块到当前数据库的块表中
_loadDB.WblockCloneObjects(ids, db.BlockTableId, new IdMapping(), DuplicateRecordCloning.Ignore, false);
trans.Commit();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + ex.StackTrace);
}
}
using (Transaction trans2 = db.TransactionManager.StartTransaction())
{
BlockTable bt = trans2.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
ObjectId targetID = bt[model.BlockName];
BlockReference blockRef = new BlockReference(new Point3d(0, 0, 0), targetID);
BlockJig blockJig = new BlockJig(blockRef, new Point3d(0, 0, 0));
PromptPointResult jigResult = ed.Drag(blockJig) as PromptPointResult;
if (jigResult.Status == PromptStatus.OK)
{
blockRef = new BlockReference(jigResult.Value, targetID);
BlockTableRecord currentSpace = trans2.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
var nwID = currentSpace.AppendEntity(blockRef);
trans2.AddNewlyCreatedDBObject(blockRef, true);
trans2.Commit();
}
}
l.Dispose();
}
private void SelectExecute(object obj)
{
System.Windows.Forms.OpenFileDialog dialog = new System.Windows.Forms.OpenFileDialog();
dialog.Multiselect = false;
dialog.Title = "选择CAD文件";
dialog.Filter = "CAD 文件 (*.dwg)|*.dwg";
if (dialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
return;
if (string.IsNullOrEmpty(dialog.FileName)) return;
CADPath = dialog.FileName;
Items = new ObservableCollection<BlockModel>();
_loadDB = new Database(false, true);
try
{
_loadDB.ReadDwgFile(dialog.FileName, FileOpenMode.OpenForReadAndReadShare, true, null);
_loadDB.CloseInput(true);
using (Transaction trans = _loadDB.TransactionManager.StartTransaction())
{
BlockTable bt = trans.GetObject(_loadDB.BlockTableId, OpenMode.ForRead) as BlockTable;
ObjectIdCollection ids = new ObjectIdCollection();
foreach (ObjectId btrId in bt)
{
BlockTableRecord btr = trans.GetObject(btrId, OpenMode.ForRead) as BlockTableRecord;
if (!btr.IsLayout && !btr.IsAnonymous)
{
BlockModel model = new BlockModel();
model.Id = btrId;
model.BlockName = btr.Name;
model.Image = GetBlockImage(btr, 110, 110, Autodesk.AutoCAD.Colors.Color.FromRgb(0, 0, 0));
Items.Add(model);
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, ex.StackTrace);
}
}
/// <summary>
/// 得到块定义的图片
/// </summary>
/// <param name="blockRecord"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="backgroundColor"></param>
/// <returns></returns>
/// <exception cref="NullReferenceException"></exception>
private BitmapSource GetBlockImage(BlockTableRecord blockRecord, int width, int height, Autodesk.AutoCAD.Colors.Color backgroundColor)
{
if (blockRecord == null)
throw new NullReferenceException(nameof(blockRecord));
var image = Utils.GetBlockImage(blockRecord.Id, width, height, backgroundColor);
if (image == IntPtr.Zero) return null;
BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(image, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
return bitmapSource;
}
#endregion
#region private
private Database _loadDB;
#endregion
public InsertExternalBlockViewModel()
{
SelectCommand = new DelegateCommand()
{
ExecuteCommand = SelectExecute
};
BlockClikCommand = new DelegateCommand()
{
ExecuteCommand = BlockCilkExecute
};
ClosedCommand = new DelegateCommand()
{
ExecuteCommand = ClosedExecute
};
}
}
public class BlockModel
{
public string BlockName { get; set; }
public BitmapSource Image { get; set; }
public ObjectId Id { get; set; }
public BlockModel() { }
}
4.定义CAD命令类
using Autodesk.AutoCAD.Runtime;
using CADTools.Commands.插入外部块;
using CADTools.ViewModels;
using CADTools.Views;
[assembly: CommandClass(typeof(InsertExternalBlockCmd))]
namespace CADTools.Commands.插入外部块
{
public class InsertExternalBlockCmd
{
[CommandMethod("InsertExternalBlock")]
public void InsertExternalBlock()
{
InsertExternalBlockViewModel vm = new InsertExternalBlockViewModel();
InsertExternalBlockView win = new InsertExternalBlockView();
win.DataContext = vm;
win.Show();
}
}
}
补充WindowMethod类
/// <summary>
/// 界面辅助方法
/// </summary>
public class WindowMethod
{
[DllImport("user32.dll", EntryPoint = "SetFocus")]
public static extern int SetFocus(IntPtr hWnd);
// 定义ShowWindow函数和常量
public static int SW_SHOWMINIMIZED = 2; // 参数,用于最小化窗口
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public static int SW_RESTORE = 9; // 参数用于恢复最小化的窗口
}
总结
代码中还存在不完善的地方,只是搭了一个简单的框架,可以自行扩展。没有设置块覆盖等问题,可以自己添加的。