VS2008使用ObjectArx2010创建块属性查看对话框

在张帆老师的教程中,有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,如图所示:

VS2008使用ObjectArx2010创建块属性查看对话框_第1张图片


其余设置保持默认,点击Finish完成项目的创建。

Step 2:添加对话框资源

在新建的项目上点击鼠标右键,在添加子菜单选择资源,添加一个Dialog资源到项目中,对话框的最终布局如图:



VS2008使用ObjectArx2010创建块属性查看对话框_第2张图片

各控件的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
2
3
4
DDX_Control(pDX, IDC_BLKDEF_LIST, m_lstBlkDef);
DDX_Control(pDX, IDC_BITMAP, m_bitmap);
DDX_Text(pDX, IDC_NUM_BLKDEF, m_strBlkRefNum);
DDX_Text(pDX, IDC_HAS_ATT, m_strHasAttribute);

变量类型:

1
2
3
4
CComboBox m_lstBlkDef;
CStatic m_bitmap;
CString m_strBlkRefNum;
CString m_strHasAttribute;
Step 5: 添加实现函数

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
BOOL CPreviewBlkDlg::OnInitDialog()
{
     CAcUiDialog::OnInitDialog();
 
     // 获得当前图形的块表
     AcDbBlockTable *pBlkTbl;
     AcDbBlockTableRecord *pBlkTblRcd;
     acdbHostApplicationServices()
         ->workingDatabase()
         ->getBlockTable(pBlkTbl,AcDb::kForRead);
 
     //遍历块表,获得用户自定义块表记录的名称,将其添加到组合框中
     AcDbBlockTableIterator *pItr;
     pBlkTbl->newIterator(pItr);
     for (pItr->start();!pItr->done();pItr->step()){
         pItr->getRecord(pBlkTblRcd,AcDb::kForRead);
 
         ACHAR* pName;
         pBlkTblRcd->getName(pName);
         CString strName(pName);
         acutDelString(pName);
 
         if (strName.Compare(ACDB_MODEL_SPACE)!=0&&
             strName.Compare(ACDB_PAPER_SPACE)!=0&&
             strName.Compare(_T( "*Paper_Space0" ))!=0){
                 m_lstBlkDef.AddString(strName);
         }
         pBlkTblRcd->close();
     }
     delete pItr;
     pBlkTbl->close();
 
     return TRUE;
}

这段代码展示了获得当前图形块表、遍历块表以及组合框控件CComboBox添加元素的方法。

5.2 添加CComboBox控件的CBN_SELCHANGE消息响应函数OnCbnSelchangeBlkdefList,处理CComboBox控件选定内容更改事件,OnCbnSelchangeBlkdefList函数的完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void CPreviewBlkDlg::OnCbnSelchangeBlkdefList()
{
     //显示预览图标
     CPaintDC dc( this );
     AcDbBlockTable *pBlkTbl;
     acdbHostApplicationServices()
         ->workingDatabase()
         ->getBlockTable(pBlkTbl,AcDb::kForRead);
 
     AcDbObjectId blkTblRcdId;
     CString strBlkDefName;
     m_lstBlkDef.GetLBText(m_lstBlkDef.GetCurSel(),strBlkDefName);
     Acad::ErrorStatus es=pBlkTbl->getAt(strBlkDefName,blkTblRcdId);
 
     HBITMAP hBitmap=BlockIconToBMP(blkTblRcdId,dc.GetSafeHdc());
 
     m_bitmap.SetBitmap(hBitmap);
 
     //获得块表记录的指针
     AcDbBlockTableRecord *pBlkTblRcd;
     pBlkTbl->getAt(strBlkDefName,pBlkTblRcd,AcDb::kForRead);
 
     //获得块参照的数量
     AcDbBlockReferenceIdIterator *pItr;
     pBlkTblRcd->newBlockReferenceIdIterator(pItr);
     int number=0;
     for (pItr->start();!pItr->done();pItr->step()){
         number++;
     }
     m_strBlkRefNum.Format(_T( "%d" ),number);
 
     //获得块参照是否包含属性
     if (pBlkTblRcd->hasAttributeDefinitions()){
         m_strHasAttribute=_T( "是" );
     } else {
         m_strHasAttribute=_T( "否" );
     }
 
     pBlkTblRcd->close();
     pBlkTbl->close();
 
     UpdateData(FALSE);
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// 获得指定的块表记录的预览图像,输入参数:块表记录的ID、设备描述表句柄
HBITMAP CPreviewBlkDlg::BlockIconToBMP( const AcDbObjectId& blkId, HDC hdc)
{
     Acad::ErrorStatus es;
     //块表记录指针
     AcDbBlockTableRecord *pBlkTblRcd=NULL;
     //保存预览图标的数组
     AcArray icon;
 
     //获得保存块表记录的预览图标的数组
     try {
         es=acdbOpenObject(pBlkTblRcd,blkId,AcDb::kForRead);
 
         if (es!=Acad::eOk)
             throw 1;
 
         //如果块表定义不包含预览图标
         if (!pBlkTblRcd->hasPreviewIcon()){
             pBlkTblRcd->close();
             return NULL;
         }
 
         es=pBlkTblRcd->getPreviewIcon(icon);
         if (es!=Acad::eOk)
             throw 2;
 
         es=pBlkTblRcd->close();
         if (es!=Acad::eOk)
             throw 3;
     } catch (...){
         pBlkTblRcd->close();
         return NULL;
     }
 
     //由icon数组获得可显示的位图
     BITMAPINFOHEADER ih;     //位图信息头
     memcpy (&ih,icon.asArrayPtr(), sizeof (ih));
     size_t memsize= sizeof (BITMAPINFOHEADER)+((1< sizeof (RGBQUAD));
     LPBITMAPINFO bi=(LPBITMAPINFO) malloc (memsize);     //位图信息
     memcpy (bi,icon.asArrayPtr(),memsize);
     HBITMAP hbm=CreateDIBitmap(hdc,&ih,CBM_INIT,icon.asArrayPtr()+memsize,bi,DIB_RGB_COLORS);
     free (bi);
 
     return hbm;
}
Step 6: 注册AutoCAD命令

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

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

由于使用了类CAcModuleResourceOverride,你需要添加头文件:

#include "AcExtensionModule.h"

到此,查看当前图形块定义属性的ObjectArx对话框应用程序便完成了,最终程序的运行效果如图:

VS2008使用ObjectArx2010创建块属性查看对话框_第3张图片

你可能感兴趣的:(ARX,MFC,2010,mfc,图形,colors,extension,bi)