需求:选择其他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包
<Windowx: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图纸位置:" /><TextBoxWidth="200"Height="30"Margin="10,0"Text="{Binding CADPath, UpdateSourceTrigger=PropertyChanged}" /><ButtonCommand="{Binding SelectCommand}"Content="选择"Style="{StaticResource ButtonPrimary}" /></StackPanel><ListBoxGrid.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><ButtonWidth="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><TextBlockGrid.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 UIprivate 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 privateprivate Database _loadDB;#endregionpublic 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; // 参数用于恢复最小化的窗口}
总结
代码中还存在不完善的地方,只是搭了一个简单的框架,可以自行扩展。没有设置块覆盖等问题,可以自己添加的。