常規的使用以下方法html
BEGIN_OPMPROP_MAP() OPMPROP_ENTRY(0, DispID, PROPCAT_Data,0, 0, 0, 「」, 0, 1, IID_NULL, IID_NULL, 「」) END_OPMPROP_MAP()
其中DispIDP是R屬性的 顯示ID;OPCAT_爲前綴的就是已經預約義的屬性分類,其數值範圍是-1~-25。cookie
若是須要自定義分類,則須要在PROPCAT_的位置上設爲自定義的數值,而後 在頭文件中改寫app
STDMETHODIMP GetCategoryName( /* [in] */ PROPCAT propcat, /* [in] */ LCID lcid, /* [out] */ BSTR* pbstrName) { if (propcat == 1) { *pbstrName = ::SysAllocString(L」SQSize」); return S_OK; } else return S_FALSE; }
注意看原來例程的寫法,按照那個寫法程序不會調用這個函數。我也不知道爲何。
執行完這個函數後,GetElementStrings函數被調用。
這個函數的做用就是分解複雜的屬性,如當你所描述的屬性是一個點時,你須要將x,y,z的座標同時顯示在屬性窗
口中。 這個函數就是你實現如何分解這些屬性。固然也能夠不實現它。
AsdkSquareWrapper例程裏沒寫清楚地好像就是這些了。個人表達能力很差,但願你們能看明白。ide
擴展屬性中實現 下拉列表函數
接口須要繼承this
public IOPMPropertyExtensionImpl
實現其中的idea
//OPM calls this function for each property to obtain a list of strings and cookies if they are available. //For our textstyle property we would like to display all the textstyles currently available in the database. //This function is declared on the IPerPropertyBrowsing interface. Our IOPMPropertyExtensionImpl //class implements this member by reading the values in the OPM property map. (You set this up in your //head file when you use BEGIN_OPMPROP_MAP, OPMPROP_ENTRY, END_OPMPROP_MAP macros.) //Since we need a dynamic list of entries in this drop down list and a static map cannot implement this, //we need to override this function a provide dynamic list of text styles to OPM. STDMETHOD(GetPredefinedStrings)( /* [in] */ DISPID dispID, /* [out] */ CALPOLESTR *pCaStringsOut, /* [out] */ CADWORD *pCaCookiesOut); //OPM calls this function when the user selects an element from a drop down list. OPM provides //the cookie that we associated with the element in the GetPredefinedStrings function. We are //responsible for mapping this cookie back to a value that the properties corresponding put_ function //can understand. //In this particular case all we need to do is to provide the name of the text style as //the put_TextStyle method needs that. STDMETHOD(GetPredefinedValue)( /* [in] */ DISPID dispID, /* [out] */ DWORD dwCookie, /* [out] */ VARIANT *pVarOut);
具體實現的思路就是根據不一樣的 dispID 設置不一樣的列表
具體實現方法能夠參考polysamp
注意:上述函數返回值是和get/put系列函數的形參嚴格對應,自動過濾掉不符合的項。3d
http://adndevblog.typepad.com/autocad/2012/12/how-to-create-a-polyline-like-vertex-edit-with-a-spin-control-in-opm.html
By Gopinath Tagetcode
The following snippets of code can be used to implement a polyline-like vertex edit in OPM (Object Property Manager) using IOPMPropertyExpander interface for a custom entity.htm
Lets assume the custom object (called AsDkRings) has two new variables to reflect an array of vertices:
AcGePoint3d m_polyline[5]; int m_numbervertices;
For simplicity, lets say the custom entity has a maximum of five vertices.
The custom class also has two corresponding access functions. (Note the vertex number parameter):
Acad::ErrorStatus AsDkRings::polyline(AcGePoint3d& vertex, int vertexNumber) Acad::ErrorStatus AsDkRings::setPolyline(AcGePoint3d vertex,int vertexNumber)
In AsDkRings:: subWoldDraw()
, we draw a polyline connecting the five vertices.
The key to getting a spin control in OPM is to return a grouping number. This number will determine the number of elements to group together.
//IOPMPropertyExpander STDMETHODIMP CRings::GetElementGrouping( /* [in] */ DISPID dispID, /* [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 into one 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 3 remaining grouped items (which is Vertex X, Y and Z).
Next, we should specify the number of items that the property is going to display. Here this would be the number of vertices = 5
. This would mean that the spin contol can go up to a maximum of 5 steps, for five vertices.
//IOPMPropertyExpander STDMETHODIMP CRings::GetGroupCount( /* [in] */ DISPID dispID, /* [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 STDMETHODIMP CRings::GetElementStrings( /* [in] */ DISPID dispID, /* [out] */ OPMLPOLESTR __RPC_FAR *pCaStringsOut, /* [out] */ OPMDWORD __RPC_FAR *pCaCookiesOut) { ................................ ................................ } else if (dispID == 5) { // For the Vertices 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 each property item that will be used to get and set values. The table below will give you an idea of cookie value for each vertex value. Please remember that vertex entry has a spin control that goes like 1, 2, 3, 4.........and so on.
Property String | Cookie Value | |||||
---|---|---|---|---|---|---|
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 vertex number and find out if it is an x, y, or z coordinate. The following code does that.
// Get the coordinate index (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; } }
index will return 0 for vertex X, 1 for vertex Y and 2 for vertex Z for the corrosponding cookie values.
So this is all that is needed to implement a poly-line vertex edit.