CAD二次开发 快速选择插入其他项目块

需求:选择其他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; // 参数用于恢复最小化的窗口

}

总结

代码中还存在不完善的地方,只是搭了一个简单的框架,可以自行扩展。没有设置块覆盖等问题,可以自己添加的。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baobao熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值