找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 2835|回复: 4

[分享] VS2008使用ObjectArx2010创建块属性查看对话框

[复制链接]

已领礼包: 859个

财富等级: 财运亨通

发表于 2017-2-13 19:52:41 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
本帖最后由 csharp 于 2017-2-13 20:05 编辑

原帖地址 : http://blog.csdn.net/ufe_1/article/details/8080211

在张帆老师的教程中,有VC6.0+ObjectArx2002创建对话框的详细指导,但由于项目需要,开发环境选择了Win7+VC2008+ObjectArx2010+CAD2010,虽然基本思路和流程依然可以参考张帆老师的教程,但事过境迁,完全照着教程做已经走不通了!本文将创建一个在对话框中查看块定义图标的程序,通过对实现流程和源代码的讲解,详细介绍ObjectArx2010+VC2008开发MFC对话框程序的方法和过程。
要实现在对话框中显示块定义的缩略图,就需要读者熟悉VC位图编程的基本知识,你也可以参考文章VC打开并缩放显示位图(.BMP)文件的方法以及VC编程实现位图处理类(显示位图、加载位图、获取/设置像素点颜色)。本文还用到了CComboBox控件罗列当前图形中用户定义的所有块表记录,关于CComboBox的更多用法,读者可以参考MFC程序使用CComboBox控件详解。好了,准备工作已经完成,我们正式开始创建属性定义查看对话框。
Step 1:新建项目
创建一个ObjectArx项目,点击MFC Support选项卡,在MFC Support的设置选中Extension DLL Using Shared DLL,如图所示: ObjectArx2010_MFC_20120411.jpg

其余设置保持默认,点击Finish完成项目的创建。
Step 2:添加对话框资源
在新建的项目上点击鼠标右键,在添加子菜单选择资源,添加一个Dialog资源到项目中,对话框的最终布局如图:
ObjectArx2010_20120411.jpg

各控件的ID设置为:
       对话框:IDD_BLKPREVIEWICON。
       列表框:IDC_BLKDEF_LIST。
       图片框:IDC_BITMAP。
       块参照数量文本框:IDC_NUM_BLKDEF。
       是否包含属性文本框:IDC_HAS_ATT。
       “关闭”按钮:IDCANCEL。
Step 3: 添加对话框类
在完成对话框的布局和ID设置以后,就应该开始设计对话框管理的类了,由于本人的ObjectArx2010与VS2008中文版没有很好的兼容,张帆老师所说的“ObjectArx MFC Support”工具栏没有找到,于是我们先创建普通的对话框,最后手动将基类CDialog改成CAcUiDialog即可。在对话框设计区域点右键,选择“添加类”,类名设置成“CPreviewBlkDlg",基类选择CDialog,点完成。
Step 4: 添加控件关联的变量
逐个右击窗体中的控件,在弹出菜单中点”添加变量“,最终的结果如下:

  1. DDX_Control(pDX, IDC_BLKDEF_LIST, m_lstBlkDef);
  2. DDX_Control(pDX, IDC_BITMAP, m_bitmap);
  3. DDX_Text(pDX, IDC_NUM_BLKDEF, m_strBlkRefNum);
  4. DDX_Text(pDX, IDC_HAS_ATT, m_strHasAttribute);
复制代码

变量类型:
  1. CComboBox m_lstBlkDef;
  2. CStatic m_bitmap;
  3. CString m_strBlkRefNum;
  4. CString m_strHasAttribute;
复制代码

Step 5: 添加实现函数
5.1 重写窗体的初始化虚函数OnInitDialog,实现程序启动时在CComboBox控件中加载当前图形的块定义列表,你可以使用向导或者手动添加的方式完成。OnInitDialog函数的完整代码如下:
  1. BOOL CPreviewBlkDlg::OnInitDialog()
  2. {
  3.     CAcUiDialog::OnInitDialog();

  4.     // 获得当前图形的块表
  5.     AcDbBlockTable *pBlkTbl;
  6.     AcDbBlockTableRecord *pBlkTblRcd;
  7.     acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl,AcDb::kForRead);

  8.     //遍历块表,获得用户自定义块表记录的名称,将其添加到组合框中
  9.     AcDbBlockTableIterator *pItr;
  10.     pBlkTbl->newIterator(pItr);
  11.     for(pItr->start();!pItr->done();pItr->step()){      
  12.         pItr->getRecord(pBlkTblRcd,AcDb::kForRead);      
  13.         ACHAR* pName;      
  14.         pBlkTblRcd->getName(pName);      
  15.         CString strName(pName);      
  16.         acutDelString(pName);      
  17.        if(strName.Compare(ACDB_MODEL_SPACE)!=0&&      
  18.           strName.Compare(ACDB_PAPER_SPACE)!=0&&      
  19.           strName.Compare(_T("*Paper_Space0"))!=0){      
  20.              m_lstBlkDef.AddString(strName);      
  21.        }      
  22.        pBlkTblRcd->close();
  23.     }
  24.     delete pItr;
  25.     pBlkTbl->close();
  26.     return TRUE;
  27. }
复制代码

这段代码展示了获得当前图形块表、遍历块表以及组合框控件CComboBox添加元素的方法。
5.2 添加CComboBox控件的CBN_SELCHANGE消息响应函数OnCbnSelchangeBlkdefList,处理CComboBox控件选定内容更改事件,OnCbnSelchangeBlkdefList函数的完整代码如下:
  1. <div>void CPreviewBlkDlg::OnCbnSelchangeBlkdefList()
  2. {
  3.     //显示预览图标
  4.     CPaintDC dc(this);
  5.     AcDbBlockTable *pBlkTbl;
  6.     acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlkTbl,AcDb::kForRead);

  7.     AcDbObjectId blkTblRcdId;
  8.     CString strBlkDefName;
  9.     m_lstBlkDef.GetLBText(m_lstBlkDef.GetCurSel(),strBlkDefName);
  10.     Acad::ErrorStatus es=pBlkTbl->getAt(strBlkDefName,blkTblRcdId);
  11.     HBITMAP hBitmap=BlockIconToBMP(blkTblRcdId,dc.GetSafeHdc());

  12.     m_bitmap.SetBitmap(hBitmap);

  13.     //获得块表记录的指针
  14.     AcDbBlockTableRecord *pBlkTblRcd;
  15.     pBlkTbl->getAt(strBlkDefName,pBlkTblRcd,AcDb::kForRead);
  16.     //获得块参照的数量
  17.     AcDbBlockReferenceIdIterator *pItr;
  18.     pBlkTblRcd->newBlockReferenceIdIterator(pItr);
  19.     int number=0;
  20.     for(pItr->start();!pItr->done();pItr->step()){      
  21.         number++;
  22.     }
  23.     m_strBlkRefNum.Format(_T("%d"),number);

  24.     //获得块参照是否包含属性
  25.     if(pBlkTblRcd->hasAttributeDefinitions()){      
  26.          m_strHasAttribute=_T("是");</div><div>   }    </div><div>   else{      
  27.       m_strHasAttribute=_T("否");
  28.     }

  29.     pBlkTblRcd->close();
  30.     pBlkTbl->close();

  31.     UpdateData(FALSE);</div><div>}
  32. </div>
复制代码

这段代码展示了在对话框中显示位图的简单方法,也给出了获取当前图形中指定块参照数量的具体实现。在代码中,使用了函数BlockIconToBMP根据ID获取指定块定义的缩略图,下面将给出函数BlockIconToBMP的完整代码:

  1. // 获得指定的块表记录的预览图像,输入参数:块表记录的ID、设备描述表句柄
  2. HBITMAP CPreviewBlkDlg::BlockIconToBMP(const AcDbObjectId&
  3. blkId, HDC hdc)
  4. {
  5.     Acad::ErrorStatus es;
  6.     //块表记录指针
  7.     AcDbBlockTableRecord *pBlkTblRcd=NULL;
  8.     //保存预览图标的数组
  9.     AcArray<Adesk::UInt8> icon;

  10.     //获得保存块表记录的预览图标的数组
  11.     try{      
  12.          es=acdbOpenObject(pBlkTblRcd,blkId,AcDb::kForRead);      
  13.          if(es!=Acad::eOk)      
  14.              throw 1;      
  15.          //如果块表定义不包含预览图标      
  16.          if(!pBlkTblRcd->hasPreviewIcon()){      
  17.              pBlkTblRcd->close();      
  18.             return NULL;      
  19.          }      
  20.         es=pBlkTblRcd->getPreviewIcon(icon);      
  21.      if(es!=Acad::eOk)      
  22.       throw 2;      
  23.   es=pBlkTblRcd->close();      
  24.   if(es!=Acad::eOk)      
  25.       throw 3;
  26.     }catch(...){      
  27.   pBlkTblRcd->close();      
  28.   return NULL;
  29.     }

  30.     //由icon数组获得可显示的位图
  31.     BITMAPINFOHEADER
  32. ih;    //位图信息头
  33.     memcpy(&ih,icon.asArrayPtr(),sizeof(ih));
  34.     size_t memsize=sizeof(BITMAPINFOHEADER)+((1<<ih.biBitCount)*sizeof(RGBQUAD));
  35.     LPBITMAPINFO
  36. bi=(LPBITMAPINFO)malloc(memsize);  
  37.   //位图信息
  38.     memcpy(bi,icon.asArrayPtr(),memsize);
  39.     HBITMAP hbm=CreateDIBitmap(hdc,&ih,CBM_INIT,icon.asArrayPtr()+memsize,bi,DIB_RGB_COLORS);
  40.     free(bi);

  41.     return hbm;
  42. }
复制代码

Step 6: 注册AutoCAD命令
使用ObjectArx集成的工具栏注册一个新命令ViewBlk,在响应函数中完成模态对话框的调用,最终代码如下:

  1. // - CHAP3._ViewBlk command (do not rename)
  2. static void CHAP3_ViewBlk(void)
  3. {
  4.     // 显示 “块定义查看器”对话框
  5.     CAcModuleResourceOverride resOverride;    //防止资源冲突
  6.     CPreviewBlkDlg dlg;
  7.     dlg.DoModal();
  8. }
复制代码

由于使用了类CAcModuleResourceOverride,你需要添加头文件:
#include "AcExtensionModule.h"
到此,查看当前图形块定义属性的ObjectArx对话框应用程序便完成了,最终程序的运行效果如图:
ObjectArx2010_20120411_1.jpg
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 859个

财富等级: 财运亨通

 楼主| 发表于 2017-2-13 19:52:42 | 显示全部楼层
本帖最后由 csharp 于 2017-2-13 20:07 编辑

学过了 C# 的 WPF,不过用 ARX 这个 MFC 还是绕不开了,按照上面的教程这个程序编译运行正常,不过中间出了个小插曲,对有C++ MFC基础的可能不是问题,就是插入的 Picture Box 控件要修改为 位图 属性,拖进来的默认是 框架 属性,运行时怎么都不出现图标,憋了半天搜索才知道了 ARX 这个 HBITMAP 要 位图 属性

另外在 VS2002 下 DDX_TEXT 提示没有了,统一都是 DDX_Control
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 6569个

财富等级: 富甲天下

发表于 2017-2-14 00:26:12 | 显示全部楼层
谢谢提供,学习了版主
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 17个

财富等级: 恭喜发财

发表于 2017-2-14 08:48:08 | 显示全部楼层
啥也不说了,感谢楼主分享哇!
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-11-22 22:38 , Processed in 0.429141 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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