明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 2154|回复: 6

Arx学习心得

  [复制链接]
发表于 2020-9-20 17:47:28 | 显示全部楼层 |阅读模式
我在学arx的一些心得,大家觉得有用就拿去用吧。没有用就当抛砖引玉了。

Arx学习心得
1.  2009年5月14日星期四
ACHAR的初始化应该采用
ACHAR char1[] =  _T( "初始化");
ACHAR *char2;
char2 = _T( "初始化");
的格式,其中因为AutoCAD定义的ACHAR为
          typedef wchar_t ACHAR;
因此ACHAR就具备了wchar_t的属性了,根据这点,有以下函数可以调用,分别是:
     WCSCAT------------------------ACHAR的合并
     WCSCPY------------------------ACHAR的复制
     WCSLEN------------------------ACHAR的长度
     _tcscmp------------------------代替strcmp,比较ACHAR
     StrCpy---------------------------代替strcpy,跟WCSCPY一样

2.  2009年5月15日星期五
对于vlsip中的getpoint来说,可以提示一些东西,比如:
          (setq ptInsert (getpoint (strcat “\n输入下一点/或S进行字高设定” (atoi zigao)))
来提示在获取点的等待中的字高值,但是在ObjectArx中,却不能这么做,这里牵涉到一个非常好用,但上手有点模糊的东西——格式说明符。
     之前模仿过一个
          acutPrintf( _T(“\n当前的字高是:%.2f”, zigao);
我以为这个可以在acedGetPoint中用到,
          Retcode = acedGetPoint( NULL, ( _T(“\n当前的字高是:%d”, zigao), ptInsert);
但上面的代码是错误的,总是提示不能转换。相关的资料也没有说对arx08等支持UNICODE的格式说明。
     我用
          ACHAR prompt[] = ( _T(“\n当前的字高是:%.2f”, zigao);
          Retcode = acedGetPoint( NULL, prompt, ptInsert);
这样也是不行的。
     幸亏有人帮忙,指出合适的操作方法,方法如下
              CString str;
          str.Format(_T("\n指定一点或输入<S>设置字高:%.2f"), scaleFactor);
          Retcode = acedGetPoint( NULL, str, ptInsert);
这样就可以了,看来arx的文字格式说明符的确用途很广。
3.  2009年5月25日星期一
关于默认输入的问题
本来在lisp中,一个变量可以在内存中存在是很简单就可以实现的,如以下的内容就很简单:
(setq aaa ‘1.0)
这样aaa变量就可以在这个图形中存在,直到这个图形关闭为止。
可是在ObjectARX中,如何实现倒是个非常麻烦的事情,因为我不知道怎么搞。在摸索一段时间后,终于明白和实现这部分内容了。以下是步骤:
在CDocData类的头文件中加入一个变量,这里我以ads_real为例。
class CDocData {
public:
     ads_real myReal;
     CDocData () ;
     CDocData (const CDocData &data) ;
     ~CDocData () ;
} ;
         然后在CDocData类的实现文件中添加默认值:
CDocData::CDocData(const CDocData &data) {
     ads_real myReal = 1.5;
}
                  这样就可以用这个全局变量了,下面是测试的函数:
     static voidralftt_rrr(void)
     {
         ads_real oldReal;
         ads_real newReal;
         ads_real inputReal;
         int retcode;
         oldReal = DocVars.docData().myReal; //这里获取了在CDocData中的MyReal值。
         
         if ( oldReal < 0.00000000001 ) //这里实际就是确认原始数是否为0
         {
              oldReal = 1.5;
         }
         CString prompt;
         prompt.Format(_T( "\n当前的real是:%.2f\n输入新的real"), oldReal );
         retcode = acedGetReal( prompt,&newReal );
         if ( retcode == RTNORM )
         {
              DocVars.docData().myReal = newReal;//这里将参数返回到全局变量中。
         }
         
     }

4.  2009年5月26日星期二
关于使用acdbOpenObject
今天想使用acdbOpenObject来打开一个AcDbObjectId,但是怎么编译都不成功,原来是在说明指针的时候不对。
AcDbBlockReference blkRef;
acdbOpenObject( blkRef, blkId, AcDb::kforWrite );
blkRef->erase( true );
上面的代码怎么看都是对的,但就是不能被编译,最后查明问题,就是在说明指针的时候没有使用间接引用,将第一句改为
     AcDbBlockReference *blkRef;
这样就可以了,指针虽然是C++里面最好的东西,但掌握的时候却非常麻烦,学习的时候已经异常花时间去掌握,可是在使用的时候总是忽略,这是亟待解决的问题。
5.  2009年6月15日星期一
如何统计曲线长度的问题
关于曲线长度的计算,原以为有相关函数可以用来直接获得,但查阅了ARX的参考手册,却并没有发现这“应该有”的函数。如果是线段倒是简单,先获得起点坐标,再获得终点的坐标,然后利用distance函数来计算线段的长度。可是对于圆弧、多线段等几何图形来讲,却不能用此方法,因为这些图形的长度跟平面中的路径有关。以下是解决方法:
圆弧、多线段、线段等都属于acdbcurve类,这个类里面几个函数:
pCurve->getEndParam( endParam );
pCurve->getDistAtParam( endParam, length );
上面第一句是获得曲线终点的参数endParam,根据参考的描述,就是:
The implementation of thisfunction in derived classes should return with endParam set to the parameter ofthe endpoint of the curve.
即是:在衍生类中使用这个函数,可以返回这曲线的终点参数。其实点在本段曲线的参数实际上就是从本段起点到参考点的长度与曲线总长的比。如果是复杂曲线,就以像2.50形式存在,其中2表示该段在曲线中是第三段曲线,0.50表示该段起点到参考点的长度与该段曲线长度的比为0.50。(线段的参数就是从起点到该参考点的长度)
第二句是获得曲线的长度,endParam是终点参数,length是曲线长度。
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image002.png
getDistAtParam是获得曲线起点至参考点间的曲线长度,也就是说,当refParamendParam为同一点时,将获得曲线的全部长度。获得指定一点的曲线上点的参数可使用函数getParamAtPoint来获取
6.  2010年7月9日星期五
使用sendStringtoExecute(pDoc, _T(“\003”) )可以清除当前已经选中的实体。
7. 2010年10月10日星期日
使用钩子
使用钩子关键是灵活使用ARX提供的2个函数acedRegisterFilterWinMsg及acedRemoveFilterWinMsg
以下是基本代码:
H
static BOOL registerHook();                //这里是注册钩子
    static BOOL removeHook();                 //这里是移除钩子
    static BOOL callback( MSG *msg );         //这里是回调函数

CPP
BOOL rLockLayerHook::registerHook()
{
    return acedRegisterFilterWinMsg(rLockLayerHook::callback);
}
BOOL rLockLayerHook::removeHook()
{
    return acedRemoveFilterWinMsg(rLockLayerHook::callback);
}
BOOL rLockLayerHook::callback(MSG *msg )
{
    if ( msg->message != WM_KEYDOWN)  //WM_KEYDOWN为需要监视消息
    {
       return FALSE;                   //这里FALSE,表示钩子不会再发送这个消息到cad那里去
    }
    return TRUE;                       //TRUE,钩子失效,发送监视消息到cad那里去
}
8. 2012年4月20日星期五
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image003.png
这个其实就是个comboBox,mfc ex的基类就是CacUiColorComboBox或者是CacUiTrueColorComboBox,区别在于后者在选其他颜色的时候,会出现一个真彩色的选项。弄好基类后,就要在comboBox上设置属性,其中style是droplist,owner draw是fixed,has string是true,之后就OK了
9. 2012年4月27日星期五
    使用 objectARX 函数 acedGetRGB(int color) 可以将cad的颜色索引(ACI)转换成对应的RGB颜色值。
    也可以通过使用AcCmEntityColor来进行转换。
10.2012年9月27日星期四
在各vs版本中,为保持项目工程的一致性,可以将各版本的源文件放置与同一个文件夹里面,这样可以在vs编译的时候迅速优化各个工程,但是必须手动在各个vs版本中添加各个新建的项目,及新的资源h和脚本文件
11.2012年11月23日星期五
从网站上抄的,移除xdata
Thefollowing ObjectARX / Lisp code removes XData that is attached to an entityregardless of the APPNAME. Use it with caution and only if you need to do this,since removing XData from an entity without considering the appname may cause plug-insthat rely on them to misbehave.
Hereis the ObjectARX code :
staticvoid AdskTestCommand(void)
{
   ads_name eNam;
   ads_point pt;
    intret;
    ret =acedEntSel(ACRX_T("\nPick an entity :"), eNam, pt);
    if(RTNORM != ret)
       return;

   AcDbObjectId ObjId;
   acdbGetObjectId(ObjId, eNam);

   AcDbEntity *pEnt = NULL;
   Acad::ErrorStatus es
           =acdbOpenAcDbEntity(pEnt, ObjId, AcDb::kForWrite);

   resbuf *xdata = pEnt->xData(NULL);
    if(xdata)
    {
        xdata->rbnext= NULL;
       pEnt->setXData(xdata);
       acutRelRb(xdata);
    }
   pEnt->close();
}
Hereis the Lisp code:
(defun c:DelXdata()
(setq l (car (entsel "ick object:")))
(if l (progn
     (redraw l 3)
     (setq le (entget l '("*")) )
     (setq xdata (assoc '-3 le))
     (setq le
           (subst (cons (car xdata) (list (list (car (car (cdr xdata))))))
xdata le))
     (entmod le)
     (redraw l 4)
     le
    )
)

12.2012年11月23日星期五
如何炸开文字
Q:
How to explode SHX based AcDbText entities to itsconstituent lines?
A:
You can “explode” or tessellate the text entity using theAcGiTextEngine::tessellate() method. But the method returns raw pointinformation which can be used to create individual lines. The method does nothonor the text style table properties and the text height, width are assumed tobe of one unit.
To get the exact representation of an AcDbText entity, weneed to transform this raw point information depending upon the attributes ofthe text and its text style. In the attached sample, the functionfGeneratematrix() creates a transformation matrix which will place the linesdrawn using the points exactly at the text location. This transformation matrixwill take care of oblique angle, upside down, backward text properties.
NOTE: the true type fonts are not supported.

13.2012年12月19日星期三
获取命令行的文字串
// get the command line CWnd container
CWnd* pDock =(CWnd*)acedGetAcadTextCmdLine();   
// get the child window
CWnd* pChild =pDock->GetWindow(GW_CHILD);   
// loop while we have children
while (pChild!=NULL)
{      
CString str;      
// get thewindow text
pChild->GetWindowText(str);      
// if we don'thave any text
if(str.GetLength() <= 0)
   pChild = pChild->GetNextWindow();   
else
{
   // display the text
   MessageBox(NULL, str);
   break;
}
}  
14.2012年12月27日星期四
创建一个非矩形的视口
AcDbViewport::setNonRecClipEntityId()can be used to associate aviewport with an entity and enabling non-rectangular clipping is done throughAcDbViewport::setNonRectClipOn()
For a clipping entity to be valid, itmust be contained in the same paperspace as the viewport entity and should beone of the entities as explained with ObjectARX help file. Please see thedocumentation for AcDbViewport::setNonRecClipEntityId() method for moredetails.
The sample code snippet below creates anon-rectangular viewport of type circle and assign a specified view to thesame:
void fCreateNonRectangularViewPort()
{
//____create thecircle
ads_point centerPoint;
if(RTNORM !=acedGetPoint(NULL,
L"\nEnterthe Viewport center point:",centerPoint))
return;
ads_real radius;
if(RTNORM !=acedGetDist(centerPoint,
L"\nEnterthe radius of the Viewport:",&radius))
return;
ACHAR viewName[133];
   if (RTNORM != ads_getstring(0,
L"\nEntername of view to use: ", viewName))
       return;
AcDbCircle* pCircle = new AcDbCircle;
//____assigningthe center point
pCircle->setCenter(AcGePoint3d(centerPoint[X],centerPoint[Y],0));
pCircle->setRadius(radius);
AcDbBlockTable *pTable;
AcDbBlockTableRecord *pRecord;
if (Acad::eOk !=acdbHostApplicationServices()->
workingDatabase()->getBlockTable(pTable, AcDb::kForRead)) {
acutPrintf(L"\nCannot get block table.");
delete pCircle;
return;
}
if (Acad::eOk !=pTable->getAt(ACDB_PAPER_SPACE,
pRecord,AcDb::kForWrite)) {
acutPrintf(L"\nCannot access paper space.");
pTable->close();
delete pCircle;
return;
}
pTable->close();
AcDbObjectId circleId;
if (Acad::eOk !=pRecord->appendAcDbEntity(circleId, pCircle)) {
acutPrintf(L"\nCannot append circle to paper space.");
pRecord->close();
delete pCircle;
return;
}
pRecord->close();
pCircle->close();
//____create theviewport entity
AcDbViewport *pViewport = newAcDbViewport;
//___assign thecenter point of circle
//(since thevalue is known directly assigning)
pViewport->setCenterPoint(AcGePoint3d(centerPoint[X],
centerPoint[Y],0));   
//___Append newviewport to the paper space
if (Acad::eOk !=acdbHostApplicationServices()->
workingDatabase()->getBlockTable(pTable, AcDb::kForRead)) {
acutPrintf(L"\nCannot get block table.");
deletepViewport;
return;
}
if (Acad::eOk !=pTable->getAt(ACDB_PAPER_SPACE,
pRecord,AcDb::kForWrite)) {
acutPrintf(L"\nCannot access paper space.");
pTable->close();
deletepViewport;
return;
}
pTable->close();
AcDbObjectId viewportId;
if (Acad::eOk !=pRecord->appendAcDbEntity(viewportId,
pViewport)) {
acutPrintf(L"\nCannot append viewport to paper space.");
pRecord->close();
deletepViewport;
return;
}
pRecord->close();
pViewport->setNonRectClipEntityId(circleId);
pViewport->setNonRectClipOn();
//___set theview
AcDbViewTable *pViewTable;
AcDbViewTableRecord *pView;
if (Acad::eOk !=acdbHostApplicationServices()->
workingDatabase()->getViewTable(pViewTable,
AcDb::kForRead)) {
acutPrintf(L"\nCannot get view table.");
pViewport->close();
return;
}
if (Acad::eOk !=pViewTable->getAt(viewName,
pView,AcDb::kForRead)) {
acutPrintf(L"\nCannot access view '%s'.", viewName);
pViewport->close();
pViewTable->close();
return;
}
pViewTable->close();
if(acedSetCurrentView(pView, pViewport)!=Acad::eOk)
acutPrintf(L"\nFailed to set view");
pViewport->setOn();
pView->close();
pViewport->close();
//update thescreen such the viewport is updated
acedCommand(RTSTR,L"_REGEN",RTNONE,0);
}
15.2012年12月27日星期四
创建有端点导航的OPM
The following snippets of code can be used to implement apolyline-like vertex edit in OPM (Object Property Manager) usingIOPMPropertyExpander interface for a custom entity.
Lets assume the custom object (called AsDkRings) has twonew variables to reflect an array of vertices:
AcGePoint3dm_polyline[5];  
intm_numbervertices;
For simplicity, lets say the custom entity has a maximum offive vertices.
The custom class also has two corresponding accessfunctions. (Note the vertex number parameter):
Acad::ErrorStatusAsDkRings::polyline(AcGePoint3d& vertex,
intvertexNumber)
Acad::ErrorStatusAsDkRings::setPolyline(AcGePoint3d vertex,
intvertexNumber)
In AsDkRings:: subWoldDraw(), we draw a polyline connectingthe five vertices.
The key to getting a spin control in OPM is to return agrouping number. This number will determine the number of elements to grouptogether.
//IOPMPropertyExpander
STDMETHODIMPCRings::GetElementGrouping(
/* [in] */ DISPIDdispID,
/* [out] */ short *groupingNumber)
{
.............
  .............
} else if (dispID ==5)
{
  *groupingNumber= 4;
  return S_OK;
}
return E_NOTIMPL;
}
A grouping number of 4 means there is one entry (called"Vertex") plus 3 entries (Vertex X, Y and Z) to group together intoone property. What this would do is put a spin control into the first item(vertex in this case), so that this could be used to traverse an array of 3remaining grouped items (which is Vertex X, Y and Z).
Next, we should specify the number of items that the propertyis going to display. Here this would be the number of vertices  = 5. Thiswould mean that the spin contol can go up to a maximum of 5 steps, for fivevertices.
//IOPMPropertyExpander
STDMETHODIMPCRings::GetGroupCount(
/* [in] */ DISPIDdispID,
/* [out] */ long*nGroupCnt)
{
................
  ...............
} else if (dispID ==5)
{
  *nGroupCnt =m_numbervertices; // Number of vertices
  return S_OK;
}
return E_NOTIMPL;
}
Next, we set the string to display in the OPM.
//IOPMPropertyExpander
STDMETHODIMPCRings::GetElementStrings(
/* [in] */ DISPIDdispID,
/* [out] */OPMLPOLESTR __RPC_FAR *pCaStringsOut,
/* [out] */ OPMDWORD__RPC_FAR *pCaCookiesOut)
{
................................
................................
} else if (dispID ==5)
{
  // For theVertices
pCaStringsOut->cElems = 4;
pCaStringsOut->pElems = (LPOLESTR*)CoTaskMemAlloc(sizeof(LPOLESTR)*4);
pCaStringsOut->pElems[0] = SysAllocString(L"Vertex");
pCaStringsOut->pElems[1] = SysAllocString(L"Vertex X");
  pCaStringsOut->pElems[2]= SysAllocString(L"Vertex Y");
pCaStringsOut->pElems[3] = SysAllocString(L"Vertex Z");
pCaCookiesOut->cElems = 4;
pCaCookiesOut->pElems = (DWORD*)CoTaskMemAlloc(sizeof(DWORD)*4);

pCaCookiesOut->pElems[0] = 10;
pCaCookiesOut->pElems[1] = 1;
pCaCookiesOut->pElems[2] = 2;
pCaCookiesOut->pElems[3] = 3;
  return S_OK;
}
return E_NOTIMPL;
}
The cookies count is the unique identifier for eachproperty item that will be used to get and set values. The table below willgive you an idea of cookie value for each vertex value. Please remember thatvertex entry has a spin control that goes like 1, 2, 3, 4.........and so on.
Property String  CookieValue      
                Vertex = 1    Vertex = 2   Vertex = 3  Vertex = 4  ....and so on        
Vertex             0            4           8          12        ....and so on        
Vertex X           1            5           9          13        ....and so on        
Vertex Y           2            6          10           14       ....and so on        
Vertex Z           3            7          11          15        ....and so on
So just by using the cookie values, you must get the vertexnumber and find out if it is an x, y, or z coordinate. The following code doesthat.
// Get the coordinateindex (x=0, y= 1, z=2) from dwCookie
for (int i = 1; i< 4; i++) {
vertex = (double(dwCookie)- i) / 4;
if( vertex ==(double(dwCookie) - i) / 4) {
  index = i -1;
  break;
}
}

indexwill return 0 for vertex X, 1 for vertex Y and 2 for vertex Z for thecorrosponding cookie values.
So this is allthat is needed to implement a poly-line vertex edit.
16.2012年12月27日星期四
为实体创建一个自定义的捕捉点
You can define a custom osnap like this:
//-------------------------------------------------------------------
// Osnap classes

class MkrInfo : publicAcDbCustomOsnapInfo
{
public:
   ACRX_DECLARE_MEMBERS(MkrInfo);

    Acad::ErrorStatus  getOsnapInfo(
    AcDbEntity*          pickedObject,
    Adesk::GsMarker       gsSelectionMark,
    constAcGePoint3d&    pickPoint,
    constAcGePoint3d&    lastPoint,
    constAcGeMatrix3d&   viewXform,
    AcArray<AcGePoint3d>& snapPoints,
    AcDbIntArray &     geomIdsForPts,
    AcArray<AcGeCurve3d*>& snapCurves,
    AcDbIntArray &     geomIdsForLines);
};



ACRX_CONS_DEFINE_MEMBERS(MkrInfo,AcDbCustomOsnapInfo, 1);


Acad::ErrorStatus
MkrInfo::getOsnapInfo(
AcDbEntity*          pickedObject,
Adesk::GsMarker      gsSelectionMark,
constAcGePoint3d&    pickPoint,
constAcGePoint3d&    lastPoint,
constAcGeMatrix3d&   viewXform,
AcArray<AcGePoint3d>&snapPoints,
AcDbIntArray&     geomIdsForPts,
AcArray<AcGeCurve3d*>&snapCurves,
AcDbIntArray&     geomIdsForLines
)
{
   AsDkCurve *p = AsDkCurve::cast(pickedObject);
    if (NULL !=p)
    {
       AcGeLineSeg3d *pls1 = new AcGeLineSeg3d;
  AcGePoint3dstartP, endP;
p->startPoint(startP);
p->m_endPoint(endP);
       pls1->set(startP, (endP - startP));
       snapCurves.append(pls1);

       AcGeLineSeg3d *pls2 = new AcGeLineSeg3d;
       pls2->set(endP, (endP - startP));
       snapCurves.append(pls2);
    }
    return Acad::eOk;
}


//static
MkrInfo _mkrInfo;


class MkrMode : publicAcDbCustomOsnapMode
{
public:
    const TCHAR*localModeString() const;
    const TCHAR*globalModeString() const;
    const AcRxClass*entityOsnapClass() const;
   AcGiGlyph* glyph() const;
    constTCHAR*              tooltipString() const;
};

const TCHAR*
MkrMode::localModeString()const
{
    return _T("XTNd");
}

const TCHAR*
MkrMode::globalModeString()const
{
    return _T("_XTNd");
}

const AcRxClass*
MkrMode::entityOsnapClass()const
{
    return MkrInfo::desc();
}

class MyGlyph : public AcGiGlyph
{
public:
   Acad::ErrorStatus setLocation(const AcGePoint3d& dcsPoint);
    voidsubViewportDraw(AcGiViewportDraw* vportDrawContext);
private:
   AcGePoint3d m_point;
};

Acad::ErrorStatus
MyGlyph::setLocation(constAcGePoint3d& dcsPoint)
{
   m_point = dcsPoint;
    return Acad::eOk;
}


void
MyGlyph::subViewportDraw(AcGiViewportDraw*p)
{
    // notneeded for ext-like snaps
}

AcGiGlyph*
MkrMode::glyph() const
{
    static MyGlyphmg;
    return &mg;
}

const TCHAR*
MkrMode::tooltipString()const
{
    return _T("CustomExtend");
}

MkrMode _mkrMode;
And you can register a custom osnap to associate with withan entity as follows:
//Register protocolextension object (customOsnapInfo)
MkrInfo::rxInit();
acrxBuildClassHierarchy();
AcDbEntity::desc()->addX(MkrInfo::desc(),&_mkrInfo);
acdbCustomOsnapManager()->addCustomOsnapMode(&_mkrMode);
And unregister as follows:
//Remove protocolextension object
acdbCustomOsnapManager()->removeCustomOsnapMode(&_mkrMode);
AcDbEntity::desc()->delX(MkrInfo::desc());
deleteAcRxClass(MkrInfo::desc());
17.2013年1月16日星期三
Jig多个实体
Jig more than one entity with AcEdJig class in ObjectARXThe AcEdJig class &#65279;&#65279;only supports the update &#65279;&#65279;&#65279;&#65279;of one &#65279;&#65279;entity&#65279;&#65279;at a time. However, there is a useful trick you can use to jig more than oneentity in ObjectARX.
To do this, you need to define a custom entity class anduse it as a *temporary&#65279;&#65279;&#65279;&#65279;&#65279;&#65279;&#65279;&#65279;&#65279;* jig entity which will be used with to maintaina list of real entities that need to be jigged. You will use this custom entitywith your custom AcEdJig class to update your list of Jigged entities.Following this, you simply need to override the *temporary* jig entity'ssubWorldDraw&#65279;() and inside it,  you can iterate through &#65279;&#65279;your recordedentities &#65279;&#65279;and call worldDraw() on each. This will give the impression ofmultiple entity update.
Please find herea sample application (available for download and migrated to use ARX 2013libraries) which has been written in such a way that it will Jig any number ofentities. You can also provide your own input and update functions for entitythat is required to be jigged. Here is the relevant source:
Header for Jig custom entity and and custom jigdeclaration:
#ifndefASDKMULTIJIG__H
#defineASDKMULTIJIG__H

#endif //ASDKMULTIJIG__H

////////////////////////////////////////////////////////
classasdkEntityList : public AcDbEntity
{
public:

//constructor
asdkEntityList ();
//destructor
~asdkEntityList ();

// flag toindicate that we have
// assignedsome entities to the entity list
boolm_calledSetEntityList;

// array ofAcDbEntities
AcDbVoidPtrArraym_entities;


typedefAdesk::Boolean (*updateFunction) (int mode,
  asdkEntityList&entityList);
// array ofupdate Functions
AcArray<updateFunction>m_updateFuncs;

// entityinput data
AcArray<AcGePoint3d>m_pnts;

// setswhat entities are to be jigged
Acad::ErrorStatussetEntityList(
  constAcDbVoidPtrArray &entities);

// loopthrough m_entities and display the data
virtualAdesk::Boolean subWorldDraw(AcGiWorldDraw *wd);
};

/////////////////////////////////////////////////////////////
classasdkMultiJig : public AcEdJig
{
public:
//constructor
asdkMultiJig ();
//destructor
~asdkMultiJig ();

// mode ofinput, starts at 0 then
//increments until all entities have been
// input,indexes m_entityList
int m_mode;

// classcontaining the list of entities to jig
asdkEntityListm_entityList;
ads_real m_distance;
AcGePoint3dm_originalPnt;

typedefAcEdJig::DragStatus
  (*inputFunction)(asdkMultiJig &jig);
// array ofinput Functions
AcArray<inputFunction>m_inputFuncs;

// get thejig data
virtualAcEdJig::DragStatus sampler();
// returnthe jig entity
virtual AcDbEntity*entity() const;
// updatethe sampler data to the jig entity
virtualAdesk::Boolean update();
// add theobject to the space
AcDbObjectIdappend(AcDbDatabase *dwg=NULL,
  const ACHAR*requiredSpace = ACDB_MODEL_SPACE);

private:
};

Implementation of the custom jig and jig custom entity:
#include "StdAfx.h"
#include "StdArx.h"

///////////////////////////////////////////////////////
Acad::ErrorStatuspostToDwg (AcDbEntity *pEnt,
AcDbDatabase*pDb=NULL,
const ACHAR*requiredSpace=ACDB_MODEL_SPACE);

///////////////////////////////////////////////////////
// constructor
asdkMultiJig::asdkMultiJig()
{
m_mode = 0;
m_distance = 0.0;
}
///////////////////////////////////////////////////////
// destructor
asdkMultiJig::~asdkMultiJig()
{
}
///////////////////////////////////////////////////////
// get the jig data
AcEdJig::DragStatusasdkMultiJig::sampler()
{
// set thecursor to invisible
setSpecialCursorType(AcEdJig::kInvisible);

// call theupdate function
return ((*this->m_inputFuncs[m_mode])(*this));
}
///////////////////////////////////////////////////////
// return the jigentity
AcDbEntity*asdkMultiJig::entity() const
{
// check tomake sure we called setEntityList
if(!m_entityList.m_calledSetEntityList)
  AfxMessageBox(L"Error - You must call setEntityList \
  beforecalling asdkMultiJig::drag()");

return (const_cast<asdkEntityList*>(&m_entityList));
}

///////////////////////////////////////////////////////
// update the samplerdata to the jig entity
Adesk::BooleanasdkMultiJig::update()
{
// call theupdate function
return ((*m_entityList.m_updateFuncs[m_mode])
  (m_mode, this->m_entityList));
}
///////////////////////////////////////////////////////
// add the object tothe space
AcDbObjectIdasdkMultiJig::append(AcDbDatabase *dwg,
const ACHAR*requiredSpace)
{
// get thetotal number of entities registered
int length =m_entityList.m_entities.length ();
// loopround the registered
// entitiesand add the to the space
for (int i=0;i<length; ++i)
{
  postToDwg((AcDbEntity *)m_entityList.m_entities,
   dwg,requiredSpace);
}

// get theid of the first entity drawn
AcDbObjectId id =
  ((AcDbEntity*)m_entityList.m_entities[0])->id ();

// closethe entities added
for (int i=0;i<length; ++i)
  ((AcDbEntity*)m_entityList.m_entities)->close ();
// returnthe object id
return (id);
}
///////////////////////////////////////////////////////
// constructor
asdkEntityList::asdkEntityList()
{
m_calledSetEntityList= false;
}
///////////////////////////////////////////////////////
// destructor
asdkEntityList::~asdkEntityList()
{
}
///////////////////////////////////////////////////////
// set what entitiesare to be jigged
Acad::ErrorStatusasdkEntityList::setEntityList (
constAcDbVoidPtrArray &entities)
{
// recordthat we have called this function correctly
m_calledSetEntityList= true;
// setupour entity list
m_entities = entities;
// ifnothing in there then lets say!
if(m_entities.length() == 0)
  returnAcad::eInvalidInput;
// setupour point storage
m_pnts.setLogicalLength(m_entities.length());
// all ok
return Acad::eOk;
}
///////////////////////////////////////////////////////
Adesk::BooleanasdkEntityList::subWorldDraw (AcGiWorldDraw * wd)
{
int length =m_entities.length ();
// loop thenumber of entities in the entity list
for (int i=0;i<length; ++i)
{
  // lets getthe entity out
  AcDbEntity *ent= (AcDbEntity *)m_entities;
  // if ok
  if (ent !=NULL)
  {
   // thendraw it
  wd->geometry ().draw (ent);
  }
}
return(Adesk::kTrue);
}
///////////////////////////////////////////////////////
// adds an entity tothe required space...
// default is currentdwg and ACDB_MODEL_SPACE.
Acad::ErrorStatuspostToDwg (AcDbEntity *pEnt, AcDbDatabase *pDb,
const ACHAR*requiredSpace)
{
// if thedefault database is to be used
if (pDb ==NULL)
  pDb =acdbHostApplicationServices()->workingDatabase ();
AcDbBlockTable*blockTable = NULL;
// get apointer to the block table
Acad::ErrorStatus es =pDb->getBlockTable (blockTable,
AcDb::kForRead);
// if itfailed then abort
if (es !=Acad::eOk)
  return (es);
AcDbBlockTableRecord*blockTableRecord = NULL;
// now geta pointer to the model space entity records
es =blockTable->getAt (requiredSpace,
blockTableRecord, AcDb::kForWrite);
// canclose the block table
// itselfas we don't need it anymore
blockTable->close();
// if itfailed then abort
if (es !=Acad::eOk)
  return (es);
//otherwise put the entity into the model space
es =blockTableRecord->appendAcDbEntity (pEnt);
// nowclose it up
blockTableRecord->close();
return (es);
}
18.2013年1月31日星期四
用ObjectARX取得当cad 截屏
Capturinga Screen Shot using ObjectARXBy Fenton Webb
Issue

  • How to capture the screen shot of     a Viewport to save it to an image file?
  • Is it possible to temporarily     display an image over the Viewport or alter the Viewport display?
Solution
There are two AcGs functions in ObjectARX SDK that can beused to get the screen shot of the specified Viewport in AutoCAD and also toset an image to be displayed in a specified Viewport.
The functions are:

  • acgsGetScreenShot()
  • acgsDisplayImage()
The function acgsGetScreenShot() will get you the pointerto an AcGsScreenShot object for the specified viewport number. When in TILEMODE1, just specify the Viewport that you are interested in or just specify “0” toget the entire ModelSpace (and same is the case with PaperSpace). Similarlyjust specify the Viewport number you are interested in if the TILEMODE is 0(i.e. in PaperSpace). Also if you specify viewport number of 1 in TILEMODE 0then you will get only the entities that exist in the PaperSpace.
You can get the image data using the method getScanline()of the AcGsScreenShot class. Using this you can fill in an array of truecolorlong words which essentially will be the ARBG data. This data can be used tocreate an image file. You can use the ATIL SDK to create a bitmap or JPG easilyfrom the image data.
The function acgsDisplayImage() on the other hand takes anarray of truecolor long words and displays the image at the specified locationon a specified Viewport. The image will stay till a redraw is called.
This function can be used to:

  • Show a temporary external image     quickly.
  • Blank the entire view port     temporarily.
  • Change the colors of the Viewport.     Say inverting the colors of the Viewport.
Note:The acgsGetScreenShot() does not get you the shaded orrendered view.
Here’s some code which shows how to use the functions, touse the Atil libs you need to link with the headers and libs in the Atil folderof the ObjectARX SDK:
// by Fenton Webb,DevTech, 1/30/2013
// screen shoots theview details as a BMP
bool RecordViewDetails(double &fieldWidth, double &fieldHeight, AcGePoint3d &position, AcGePoint3d &target, AcGeVector3d &upVector, const TCHAR *imagePath)
{
  int iVP = getCVPort();

  // Computethe viewport dimensions.
  int nLeft, nBottom, nRight, nTop;
  int iImageWidth, iImageHeight;
  acgsGetViewportInfo (iVP, nLeft, nBottom, nRight, nTop);

  iImageWidth  = nRight - nLeft + 1;
  iImageHeight = nTop - nBottom + 1;
  Atil::Size size(iImageWidth, iImageHeight);
  int nBytesPerRow = Atil::DataModel::bytesPerRow(iImageWidth,
                               Atil::DataModelAttributes::k32);
  unsigned long nBufferSize = iImageHeight * nBytesPerRow;

  // Createan ATIL image for accepting the rendered image.
  std::auto_ptr<char> autoBuff = std::auto_ptr<char>(new char[nBufferSize]);
  char *pSnapshotData = autoBuff.get();  
  Atil::Image * pImage = NULL;
  // see ifthere is a GS view created
  AcGsView *pView = acgsGetGsView(iVP, false);
  // if not
  if (NULL == pView)
  {
    // then wemust be in 2D wireframe mode, so use acgsGetScreenShot
    std::auto_ptr<AcGsScreenShot> autoScreenShot(acgsGetScreenShot(iVP));
    AcGsScreenShot* screenShot = autoScreenShot.get(); // auto_ptrstill owns the pointer.
    if (screenShot)
    {
     int w = 0, h = 0, d = 0;
     screenShot->getSize(w, h, d);

     char* pBufTemp = pSnapshotData;
     for (int row = 0; row < h; row++)
     {
       memcpy(pBufTemp, screenShot->getScanline(0, row), nBytesPerRow);

       //convert from RGBA to BGRA
       char* pColor = pBufTemp;
       for (int i = 0; i < w; i++)   //Slow but it works
       {
         char temp = *pColor;
         *pColor = *(pColor + 2);
         *(pColor + 2) = temp;
         pColor += 4;
       }
       pBufTemp += nBytesPerRow;
     }
     pImage = constructAtilImg(reinterpret_cast<char*>(pSnapshotData),
                   nBufferSize, nBytesPerRow, w, h, 32, 0);
     std::auto_ptr<Atil::Image> autodeleter = std::auto_ptr<Atil::Image>(pImage); // auto_ptrnow owns the image

     if (!writeImageFile(pImage, kBMP, imagePath))
     {
       acutPrintf(_T("\nFailedto write image file %s"), imagePath);
       return false;
     }
     else
       acutPrintf(_T("\nSuccessfullywritten %s"), imagePath);

    }

    return true;
  }
  else
  {
    return snapGSView(pView, iImageWidth, iImageHeight, fieldHeight, fieldWidth, position, target, upVector, imagePath);
  }
}

bool snapGSView(AcGsView *pView, int width, int height, double &fieldWidth, double &fieldHeight, AcGePoint3d &position, AcGePoint3d &target, AcGeVector3d &upVector, const TCHAR *imagePath)
{
  Atil::Size size(width, height);
  int nBytesPerRow = Atil::DataModel::bytesPerRow(width, Atil::DataModelAttributes::k32);
  unsigned long nBufferSize = height * nBytesPerRow;

  // Createan ATIL image for accepting the rendered image.
  std::auto_ptr<char> apCharBuffer = std::auto_ptr<char>(new char[nBufferSize]);
  char *pSnapshotData = apCharBuffer.get();  // auto_ptr still owns the buffer.

  // inshaded mode (from GS)
  Atil::Image * pImage = NULL;
  pImage = constructAtilImg(pSnapshotData, nBufferSize, nBytesPerRow, width, height, 32, 0);
  std::auto_ptr<Atil::Image> autodeleter = std::auto_ptr<Atil::Image>(pImage); // auto_ptrnow owns the image
  pView->getSnapShot(pImage, AcGsDCPoint(0, 0));

  // add atemp image to invert the image. do we have a better way to turn an imagearound?
  Atil::Image imgTempForInverted(pImage->read(pImage->size(), Atil::Offset(0, 0), Atil::kBottomUpLeftRight));
  *pImage = imgTempForInverted;

  if (!writeImageFile(pImage, kBMP, imagePath))
  {
    acutPrintf(_T("\nFailedto write image file %s"), imagePath);
    return false;
  }
  else
    acutPrintf(_T("\nSuccessfullywritten %s"), imagePath);

  // recordthe view data
  fieldHeight = pView->fieldHeight();
  fieldWidth = pView->fieldWidth();
  position = pView->position();
  target = pView->target();
  upVector = pView->upVector();

  return true;
}

bool writeImageFile (Atil::Image *pImageSource, eFormatType formatType,
  wchar_t const *pFileName)
{
  _ASSERT(NULL != pImageSource);
  if(NULL == pImageSource)
    return false;

  _ASSERT(pImageSource->isValid());
  if(!pImageSource->isValid())
    return false;

  if(PathFileExists(pFileName))
    DeleteFile(pFileName);

  /*if(PathFileExists(pFileName)){
if(IsFileReadOnly(pFileName)) {
RemoveReadonlyAttribute(pFileName);
DeleteFile(pFileName);
  }
  }*/

  if(PathFileExists(pFileName))
    return false;

  Atil::RowProviderInterface* pPipe = pImageSource->read(pImageSource->size(),
    Atil::Offset(0,0));
  _ASSERTE(NULL != pPipe);
  if(!pPipe)
    return false;

  Atil::FileWriteDescriptor  *pFWD = NULL;
  Atil::ImageFormatCodec    *pCodec = NULL;

  if (formatType == kJPG)
    pCodec = new JfifFormatCodec();
  else if (formatType == kPNG)
    pCodec = new PngFormatCodec();
  else if (formatType == kTIF)
    pCodec = new TiffFormatCodec();
  else if (formatType == kBMP)
    pCodec = new BmpFormatCodec();

  _ASSERTE(NULL != pCodec);
  if(NULL == pCodec)
    return false;

  if(!Atil::FileWriteDescriptor::isCompatibleFormatCodec(pCodec,
   &(pPipe->dataModel()), pPipe->size())) {
     delete pCodec;
     return false;
  }

  pFWD = new Atil::FileWriteDescriptor(pCodec);
  _ASSERTE(NULL != pFWD);

#ifdef UNICODE
#ifndef _ADESK_MAC_
  Atil::FileSpecifier fs(Atil::StringBuffer((lstrlen(pFileName) + 1) * sizeof(TCHAR),
    (const Atil::Byte *) pFileName, Atil::StringBuffer::kUTF_16),
    Atil::FileSpecifier::kFilePath);
#else
  Atil::FileSpecifier fs(Atil::StringBuffer((lstrlen(pFileName) + 1) * sizeof(TCHAR),
    (const Atil::Byte *) pFileName, Atil::StringBuffer::kUTF_32),
    Atil::FileSpecifier::kFilePath);

#endif
#else
  Atil::FileSpecifier fs(Atil::StringBuffer(lstrlen(pFileName) + 1,
    (const Atil::Byte *) pFileName, Atil::StringBuffer::kASCII),
    Atil::FileSpecifier::kFilePath);
#endif

  if (!pFWD->setFileSpecifier(fs))
    return false;

  pFWD->createImageFrame(pPipe->dataModel(), pPipe->size());

  if (formatType == kPNG) {
    Atil::FormatCodecPropertyInterface* pProp = pFWD->getProperty(Atil::FormatCodecPropertyInterface::kCompression);
    if (pProp != NULL) {
     PngCompression* pPngComp = (PngCompression*)(pProp);
     if ( pPngComp != NULL ) {
       //Why not compress all we can?
       pPngComp->selectCompression(PngCompressionType::kHigh);
       pFWD->setProperty(pPngComp);
     }
     delete pProp;
     pProp = NULL;
    }
  }
  else if (formatType == kTIF) {
    Atil::FormatCodecPropertyInterface* pProp = pFWD->getProperty(Atil::FormatCodecPropertyInterface::kCompression);
    if (pProp != NULL) {
     TiffCompression* pComp = (TiffCompression*)(pProp);
     if ( pComp != NULL ) {
       //G4 is only valid for 1 bit images.
       if ( pComp->selectCompression(TiffCompressionType::kCCITT_FAX4) == false ) {
         //So if that fails, resort to LZW now that it is patent free
         if ( pComp->selectCompression(TiffCompressionType::kLZW) == false ) {
           //If that fails (and is shouldn't, be) then set none.
           pComp->selectCompression(TiffCompressionType::kNone);
         }
       }
       pFWD->setProperty(pComp);
     }
     delete pProp;
     pProp = NULL;
    }
  }
// get the current vp
int getCVPort()
{
  struct resbuf rb;
  ads_getvar(_T("CVPORT"), &rb);
  return rb.resval.rint;
}

Atil::DataModel* colorSpace (char *&pRGBData, int colorDepth, int paletteSize)
{
  _ASSERT(NULL != pRGBData);

  // Setup acolor space, with palette if needed
  Atil::DataModel *pDm = NULL;
  if (colorDepth == 8) {
    Atil::RgbColor space[256];

    Atil::RgbPaletteModel *pPM = new Atil::RgbPaletteModel();
    _ASSERT(NULL != pPM);
    if(!pPM)
     return NULL;

    pDm = pPM;
    char *palette = pRGBData;
    pRGBData += paletteSize;
    for (int i = 0; i < paletteSize; i += 4)
     space[i / 4] = Atil::RgbColor(palette[i+2],palette[i+1],palette, 255);
    pPM->setEntries(0, 256, (Atil::RgbColor *)&space);
  } else
    pDm = new Atil::RgbModel(32);


  _ASSERT(NULL != pDm);
  return pDm;
}

Atil::Image *constructAtilImg(char *pRGBData,
  unsigned long bufferSize, unsigned long rowBytes,
  unsigned long xSize, unsigned long ySize, int colorDepth, int paletteSize)
{
  if ((8 != colorDepth)&& (32 != colorDepth))
  {
    return NULL;
  }

  if (paletteSize)
  {
    if ((paletteSize < 0) ||(paletteSize > 255))
    {
     return NULL;
    }
  }

  if ((xSize <= 0)|| (ySize <= 0))
  {
    return NULL;
  }

  Atil::Image *pImg = NULL;
  Atil::Size size(xSize, ySize);

  //construct the Atil::Image object
  if (pRGBData) {

    // Checkthe buffer for size and definition
    if (bufferSize) {
     if (!rowBytes) {
       return NULL;
     }

     //did they allocate enough?
     if (rowBytes * ySize > bufferSize) {
       return NULL;
     }
    }
    else {
     return NULL;
   }        

    Atil::DataModel *pM = colorSpace(pRGBData, colorDepth, paletteSize);
    _ASSERT(NULL != pM);
    if(NULL == pM)
     return NULL;

    try {
     //BEWARE: pRGBData may be moved in colorSpace
     pImg = new Atil::Image(pRGBData, bufferSize,
       rowBytes, size, pM);  
    } catch (Atil::ATILException* pExpCon) {
     //image construction failure
     delete pExpCon;
     delete pM;
     pImg = NULL;
     _ASSERT(FALSE);
     return NULL;
    }

    delete pM;
  }
  else {
    Atil::RgbModel    rgbM(32);
    Atil::RgbGrayModel gM;

    Atil::ImagePixel initialColor(colorDepth == 32 ?
     Atil::DataModelAttributes::kRgba :
    Atil::DataModelAttributes::kGray);
    initialColor.setToZero();

    try {
     pImg = new Atil::Image(size,
       colorDepth == 32 ?&rgbM : &gM,
       initialColor);
    } catch (Atil::ATILException* pExpCon) {
     //image construction failure
     delete pExpCon;
     pImg = NULL;
     _ASSERT(FALSE);
     return NULL;
    }
  }

  _ASSERT(NULL != pImg);
  return pImg;
}

bool getTempImgFile(TCHAR * fileName)
{
  // Here wecreate a temp bmp file as a transitional file
  TCHAR tempDic[MAX_PATH];
  ::memset(tempDic,0,MAX_PATH);
  DWORD nRetSize = ::GetTempPath(MAX_PATH,tempDic);
  if (nRetSize > MAX_PATH || nRetSize == 0)
  {
    const TCHAR * tempStr = _T("C:\\temp");
    if (wcscpy_s(tempDic,tempStr) != 0)
    {
     return false;
    }

    if (::PathFileExists(tempStr) == FALSE &&
     ::CreateDirectory(tempStr,NULL) == FALSE)
    {
     return false;
    }
  }

  // createthe temp file whose prefix is "img"
  if (::GetTempFileName(tempDic,_T("tmp"),0,fileName) == 0)
  {
    return false;
  }

  // now splitthe filepath into its individual components
  TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME], ext[_MAX_EXT];
  _tsplitpath (fileName, drive, dir, fname, ext);
  _stprintf(fileName, _T("%s%s%s.bmp"), drive, dir, fname);

  return true;
}
19.2013年6月8日星期六
在文件搜索路径添加指定的目录
void CRInit::addSupportPath(const CString&szNewPath )
{
     const ACHAR* libPath= acdbHostApplicationServices()->getEnv( L"ACAD" );
     CString sysPath;
     sysPath.Format( libPath);
     if ( sysPath.Find( szNewPath ) != -1 )
     {
         acutPrintf(L"已经存在指定路径!\n");
         return;
     }
     sysPath+= L";";
     sysPath+= szNewPath;
     int retcode;
     retcode= acedSetEnv( L"ACAD", sysPath);
     return;
}
20.2013年9月3日星期二
AcAdDoubleClickEdit arx2010 中 变到哪里了?
Solution
The AcDbDoubleClickEdit functionality that was exposed in AcDblClkEditPE.arx isnow rolled up in AcApp.arx and acad.lib.
For AutoCAD 2010 to make double click extension protocol to work.…
1. Remove any loadModule() calls to AcDblClkEditPE.arx
2. Remove any calls to AcDbDoubleClickEdit::rxinit() as this is now doneautomatically for us.
3. Include the AcDblClkEdit.h
4. Add ACRX_DEFINE_MEMBERS(AcDbDoubleClickEdit); in one of your .cpp modules
For AutoCAD2007~2009
file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
21.2014年1月23日星期四
以下代码获取lsp中的变量值:
static void RALFHCDev_pp(void)
    {
        // Add yourcode for command RALFHCDev._pp here
        int i = 0;
        CString str;
        int retcode = RTNORM;
        struct resbuf *result = NULL;
        retcode= acedGetSym( _T("kkk"), &result);
        if ( retcode != RTNORM)
        {
            acutRelRb(result);
            str.Format( _T("Error [%d]"),retcode);
            AfxMessageBox(str );
            return;
        }
        i = result->resval.rint;
        acutRelRb(result);
        str.Format( _T("kkk所ù属?的?值μ为a[%d]"),i);
        AfxMessageBox( str);
    }
22.2016年1月21日 10:05:21
以下代码禁止选择AcDbLine
//AcEdSSGetFilterEx.h
#pragma once
class AcEdSSGetFilterEx:public AcEdSSGetFilter
{
virtual void ssgetAddFilter(
int ssgetFlags,
AcEdSelectionSetService &service,
const AcDbObjectIdArray& selectionSet,
const AcDbObjectIdArray& subSelectionSet);
virtual void
endSSGet(
Acad::PromptStatus returnStatus,
int ssgetFlags,
AcEdSelectionSetService &service,
const AcDbObjectIdArray&selectionSet);
virtual void
endEntsel(
Acad::PromptStatus      returnStatus,
const AcDbObjectId&     pickedEntity,
const AcGePoint3d&      pickedPoint,
AcEdSelectionSetService& service);
//
是否可以选中
virtual bool CanBeSelect(AcDbObjectId id);
//
是否可以选中
virtual bool CanBeSelect(AcDbEntity* pEnt);
};
//AcEdSSGetFilterEx.cpp
#include"StdAfx.h"
#include "AcEdSSGetFilterEx.h"
void
AcEdSSGetFilterEx::ssgetAddFilter(
int ssgetFlags,
AcEdSelectionSetService &service,
const AcDbObjectIdArray& selectionSet,
const AcDbObjectIdArray& subSelectionSet)
{
acutPrintf(_T("\r\nAcEdSSGetFilterEx::ssgetAddFilter\r\n"));
for(int i=subSelectionSet.logicalLength()-1;i>=0;i--)
{
if(CanBeSelect(subSelectionSet.at(i)))
{
continue;
}
service.remove(i);
}
}
void AcEdSSGetFilterEx::endSSGet(
Acad::PromptStatus returnStatus,
int ssgetFlags,
AcEdSelectionSetService &service,
const AcDbObjectIdArray& selectionSet)
{
acutPrintf(_T("\r\nAcEdSSGetFilterEx::endSSGet\r\n"));
for(int i=selectionSet.logicalLength()-1;i>=0;i--)
{
if(CanBeSelect(selectionSet.at(i)))
{
continue;
}
service.remove(i);
}
}
void AcEdSSGetFilterEx::endEntsel(
Acad::PromptStatus       returnStatus,
const AcDbObjectId&      pickedEntity,
const AcGePoint3d&       pickedPoint,
AcEdSelectionSetService& service)
{
acutPrintf(_T("\r\nAcEdSSGetFilterEx::endEntsel\r\n"));
if(CanBeSelect(pickedEntity))
{
return;
}
service.remove(0);
}
//是否可以选中
bool AcEdSSGetFilterEx::CanBeSelect(AcDbObjectId id)
{
AcDbEntity* pEnt=NULL;
Acad::ErrorStatus es=acdbOpenAcDbEntity(pEnt,id,AcDb::kForRead);
if(es!=Acad::eOk)
{
return false;
}
bool rc=CanBeSelect(pEnt);
pEnt->close();
return rc;
}
//是否可以选中
bool AcEdSSGetFilterEx::CanBeSelect(AcDbEntity* pEnt)
{
return true;
}
//MySSGetFilter.h
#pragma once
#include "AcEdSSGetFilterEx.h"
class MySSGetFilter: public AcEdSSGetFilterEx
{
public:
//是否可以选中
virtual bool CanBeSelect(AcDbEntity* pEnt);
};
//MySSGetFilter.cpp
#include"StdAfx.h"
#include "MySSGetFilter.h"
//是否可以选中
bool MySSGetFilter::CanBeSelect(AcDbEntity* pEnt)
{
if(pEnt->isKindOf(AcDbLine::desc()))
{
return false;
}
else
{
return true;
}
}
//acrxEntryPoint.cpp
#include"StdAfx.h"
#include "resource.h"
#include "MySSGetFilter.h"
MySSGetFilter m_filter;
//-----------------------------------------------------------------------------
#define szRDS _RXST("")
//-----------------------------------------------------------------------------
//----- ObjectARX EntryPoint
class CSSGetFilterTestApp : public AcRxArxApp {
public:
CSSGetFilterTestApp () : AcRxArxApp () {}
virtualAcRx::AppRetCode On_kInitAppMsg (void *pkt) {
// TODO: Load dependencies here
// You *must* callOn_kInitAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kInitAppMsg (pkt) ;
addSSgetFilterInputContextReactor(curDoc(),&m_filter);
// TODO: Add yourinitialization code here
return (retCode) ;
}
virtualAcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
// TODO: Add your code here
// You *must* callOn_kUnloadAppMsg here
AcRx::AppRetCode retCode =AcRxArxApp::On_kUnloadAppMsg (pkt) ;
removeSSgetFilterInputContextReactor(curDoc(),&m_filter);
// TODO: Unloaddependencies here
return (retCode) ;
}
virtual voidRegisterServerComponents () {
}
} ;
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CSSGetFilterTestApp)

23.

本帖被以下淘专辑推荐:

  • · 经典|主题: 26, 订阅: 2
发表于 2020-9-22 09:15:03 | 显示全部楼层
顶起,分享不易,谢谢楼主分享,支持一下,让大家都能看到
发表于 2020-9-22 17:12:04 | 显示全部楼层
十多年前的笔记,分享不易!
发表于 2020-11-16 09:24:19 | 显示全部楼层
多谢楼主分享
发表于 2020-11-27 13:33:47 | 显示全部楼层

多谢楼主分享
发表于 2021-10-29 16:36:09 | 显示全部楼层
虽然我不懂,但是…好厉害!
值得收藏的文章!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-12-26 23:10 , Processed in 0.344422 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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