明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 70105|回复: 101

[VBA]利用ObjectDbx技术在当前图形中插入其它未打开的图形中的图块

    [复制链接]
发表于 2003-5-4 20:30 | 显示全部楼层 |阅读模式
本帖最后由 作者 于 2007-1-12 17:27:19 编辑

以前,我们为了做图库,每一个图块均必须保存为一个图形文件,以便在编程时直接插入选定的图形,这样做出来的程序,图形文件的数量就会很多,因为有时你的图库内容很多。
现在利用ObjectDbx技术可以将这些图块放在一个图形中,做到真正的图库,以下为程序内容:

引用:ObjectDbx 1.0类型库(文件为:c:\program files\AutoCAD 2002\AXDB15.TLB)
插入模块1,输入以下代码:
  1. Public Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" _
  2.     (LPOPENFILENAME As OPENFILENAME) As Long
  3. Public Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" _
  4.     (pOpenfilename As OPENFILENAME) As Long
  5. Public Const OFN_PATHMUSTEXIST = &H800
  6. Public Const OFN_FILEMUSTEXIST = &H1000
  7. Public Const OFN_HIDEREADONLY = &H4 '隐蔽只读复选框
  8. Public Type OPENFILENAME
  9.     lStructSize As Long
  10.     hwndOwner As Long '拥有对话框的窗口
  11.     hInstance As Long
  12.     lpstrFilter As String '装载文件过滤器的缓冲区
  13.     lpstrCustomFilter As String
  14.     nMaxCustFilter As Long
  15.     nFilterIndex As Long
  16.     lpstrFile As String
  17.     nMaxFile As Long
  18.     lpstrFileTitle As String
  19.     nMaxFileTitle As Long
  20.     lpstrInitialDir As String
  21.     lpstrTitle As String '对话框的标题
  22.     flags As Long
  23.     nFileOffset As Integer
  24.     nFileExtension As Integer
  25.     lpstrDefExt As String
  26.     lCustData As Long
  27.     lpfnHook As Long
  28.     lpTemplateName As String
  29. End Type
  30. Function GetFile(strTitle As String, strFilter As String, Optional strIniDir As String) As String
  31. On Error Resume Next
  32. Dim FileName As String
  33. Dim OFileBox As OPENFILENAME
  34. With OFileBox
  35.     .lpstrTitle = strTitle '对话框标题
  36.     .lpstrInitialDir = strIniDir '初始目录
  37.     .lStructSize = Len(OFileBox)
  38.     .hwndOwner = ThisDrawing.HWND
  39.     .flags = OFN_PATHMUSTEXIST Or OFN_FILEMUSTEXIST Or OFN_HIDEREADONLY
  40.     .lpstrFile = String$(255, 0)
  41.     .nMaxFile = 255
  42.     .lpstrFileTitle = String$(255, 0)
  43.     .nMaxFileTitle = 255
  44.     .lpstrFilter = strFilter  '过滤器
  45.     .nFilterIndex = 1
  46. End With
  47. lntFile = GetOpenFileName(OFileBox) '执行打开对话框
  48. If lntFile <> 0 Then
  49.     FileName = Left(OFileBox.lpstrFile, InStr(OFileBox.lpstrFile, vbNullChar) - 1)
  50.     GetFile = FileName
  51. Else
  52.     GetFile = ""
  53. End If
  54. End Function
插入窗体userform1,自上而下插入以下控件:
  标签(Label1)
     文本框(TextBox1)
              命令按钮(CommandButton1)
  标签(Label2)
     组合框(ComboBox1)
命令按钮(CommandButton2)  命令按钮(CommandButton3)

然后在窗体的代码窗中输入以下代码:
  1. Option Explicit
  2.     Dim objDbx As AxDbDocument
  3.     Dim elem As Object
  4.     Dim blkName As String
  5.     Dim dwgName As String
  6.     Dim blkObj(0) As Object
  7.     Dim pnt As Variant
  8. Private Sub CommandButton1_Click()
  9.     Me.TextBox1 = GetFile("打开图形", "图形文件(*.dwg)" & vbNullChar & "*.dwg")
  10. End Sub
  11. Private Sub CommandButton2_Click()
  12.     blkName = Me.ComboBox1.SelText
  13.     dwgName = Me.TextBox1.Value
  14.     Me.Hide
  15.    
  16.     pnt = ThisDrawing.Utility.GetPoint(, "选择插入点:")
  17.     Set blkObj(0) = objDbx.Blocks(blkName)
  18.     objDbx.CopyObjects blkObj, ThisDrawing.ModelSpace
  19.     ThisDrawing.ModelSpace.InsertBlock pnt, blkName, 1, 1, 1, 0
  20.     Unload UserForm1
  21.     Set elem = Nothing
  22.     Set objDbx = Nothing
  23.    
  24. End Sub
  25. Private Sub CommandButton3_Click()
  26.     Unload UserForm1
  27.     Set elem = Nothing
  28.     Set objDbx = Nothing
  29. End Sub
  30. Private Sub TextBox1_Change()
  31.     If Dir(Me.TextBox1.Value) <> "" Then
  32.         objDbx.Open Me.TextBox1.Value
  33.         For Each elem In objDbx.Blocks
  34.             If Left(elem.Name, 1) <> "*" Then
  35.                 Me.ComboBox1.AddItem elem.Name
  36.             End If
  37.         Next
  38.     End If
  39.         
  40. End Sub
  41. Private Sub UserForm_Initialize()
  42.     Set objDbx = GetInterfaceObject("ObjectDBX.AxDbDocument")
  43.     Me.CommandButton1.Caption = "浏览"
  44.     Me.CommandButton2.Caption = "插入"
  45.     Me.CommandButton3.Caption = "取消"
  46.     Me.Label1.Caption = "选择图形:"
  47.     Me.Label2.Caption = "选择图块:"
  48.     Me.Caption = "插入外部图形中的图块示例"
  49. End Sub
然后在ThisDrawing代码窗中输入以下代码:
  1. Sub InsBlk()
  2.     Load UserForm1
  3.     UserForm1.Show
  4. End Sub
这样就可以试试你的程序了。
如果觉得麻烦,这个我已经打包成一个文件,大家拿去试试吧:


下载的文件已经改为最新无错版本,可用于2000-2004版本

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 4威望 +2 明经币 +2 金钱 +42 贡献 +1 激情 +2 收起 理由
高_金金金 + 20 很给力!
zzyong00 + 1 + 20 很给力!
3xxx + 1
efan2000 + 2 + 2 + 1 + 2 【好评】好文章

查看全部评分

发表于 2022-12-15 15:15 | 显示全部楼层
新人上路,求大神解答一下。这个帖子里的功能就是我想要的,我想学习下,但是不知道为什么我运行这个程序,点击“浏览文件”按钮的时候就会报错,hwndOwner = ThisDrawing.HWND的类型不匹配,这是什么原因?我用的是AutoCAD2016版本和内置的VB
发表于 2021-11-11 11:12 | 显示全部楼层
哇,看到了知识点,留个位子
发表于 2020-5-23 22:25 | 显示全部楼层
学习一下 谢谢分享
发表于 2003-4-21 16:47 | 显示全部楼层

非常好,這種東西很面熟,我好像有用VLISP寫過,但一直沒有用過

发表于 2003-4-21 21:05 | 显示全部楼层

有个bug,如何解决

运行时出现对话框,提示内容为:
run-time error '-2147221005(800401f3)'
problem in loading application
发表于 2003-4-23 09:08 | 显示全部楼层

可能是你還沒有註冊objectdbx,先註冊吧!程序如內

(defun REGISTEROBJECTDBX (/ DBXSERVER)        ;by Tony Tanzillo - Thanks Tony!
  (cond
    ((vl-registry-read
       "HKEY_CLASSES_ROOT\\ObjectDBX.AxDbDocument\\CLSID"
     )
    )
    ((not (setq DBXSERVER (findfile "AxDb15.dll")))
     (alert "Error: Can't locate ObjectDBX Library (AxDb15.dll)")
    )
    (t
     (startapp "regsvr32.exe" (strcat "/s \"" DBXSERVER "\""))
     (or
       (vl-registry-read
         "HKEY_CLASSES_ROOT\\ObjectDBX.AxDbDocument\\CLSID"
       )
       (alert
         "Error: Failed to register ObjectDBX ActiveX services."
       )
     )
    )
  )
)
发表于 2003-4-23 16:50 | 显示全部楼层

谢谢!

本人是新手,是在明经长大的,以后会多学习的。
发表于 2003-4-27 00:08 | 显示全部楼层

非常有意义,不知道AutoCAD对ObjectDbx 1.0类型库的支持是不是稳定的?

例如,对Office 97类型库的引用在只安装Office 2000/XP的系统中能够自动识别并转换,而不至于出现找不到类型库的警告。
 楼主| 发表于 2003-4-27 12:16 | 显示全部楼层

也同样存在版本问题

这个程序是在2002中写的,应该在2000到2002都可以运行。
而2004版中直接运行则会出错并退出AutoCAD,所以在2004中必须调用ObjectDbx16,也就是与2004版本相同的DBX类型库,但只是这样做还是会出错,要再把
Set objDbx = GetInterfaceObject("ObjectDBX.AxDbDocument")
改为
Set objDbx = GetInterfaceObject("ObjectDBX.AxDbDocument.16")
才能正常运行。
这样的话就要引用两个类型库,并在程序中判断当前ACAD版本以引用不同的类型库了。
发表于 2003-4-27 18:48 | 显示全部楼层

类型库的引用最大的问题就是版本问题。

根据版本判断来引用不同的类型库相当于修改VBA源程序,退出AutoCAD时会提问是否保存DVB,早年曾与老弟探讨过这个问题,不知道现在可有什么妙法解决。
 楼主| 发表于 2003-4-27 18:53 | 显示全部楼层

两个类型库一起引用,但在Set objDbx=这一句前加判断版本

我没试过,不知是否可行
 楼主| 发表于 2003-5-3 13:49 | 显示全部楼层

看看这种方法是否可以彻底解决问题

可以使用CreateObject函数来创建对类型库的引用,这样就可以避开在工具中人工进行引用所带来的版本问题。
也就是这样:
以下为2004版:
    Dim objDbx
    Set objDbx = CreateObject("ObjectDBX.AxDbDocument.16")
以下为2000-2002版:
    Dim objDbx
    Set objDbx = CreateObject("ObjectDBX.AxDbDocument.1")
注意以上使用的方法不需要在工具中引用类型库了,而是直接在程序中完成,这样就可以在程序中判断目前AutoCAD的版本来决定程序的引用了。

以下为改动过的UserForm_Initialize过程:

  1. Private Sub UserForm_Initialize()
  2.     If Left(Version, 2) = "15" Then
  3.         Set objDbx = CreateObject("ObjectDBX.AxDbDocument.1")
  4.     ElseIf Left(Version, 2) = "16" Then
  5.         Set objDbx = CreateObject("ObjectDBX.AxDbDocument.16")
  6.     End If
  7.    
  8.     Me.CommandButton1.Caption = "浏览"
  9.     Me.CommandButton2.Caption = "插入"
  10.     Me.CommandButton3.Caption = "取消"
  11.     Me.Label1.Caption = "选择图形:"
  12.     Me.Label2.Caption = "选择图块:"
  13.     Me.Caption = "插入外部图形中的图块示例"
  14. End Sub
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-27 08:41 , Processed in 0.414614 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表