newer 发表于 2021-1-11 20:38:40

Adding A Block Using ActiveX Client In C++

问题:
How do I add a block to a drawing through an ActiveX Client in C++?

解答:
There are two interface objects that are mirrored to their ObjectARX
counterparts: IAcadBlocks to AcDbBlockTable and IAcadBlock to
AcDbBlockTableRecord. You then need to get to the interface objects and call the
appropriate methods.

These are the key steps to doing this:

1. Create a standalone MFC AppWiard EXE that is dialog-based.
2. Use the ClassWizard to import the following interfaces (from acad.tlb) and
declare them as private member variables of the dialog class:


IAcadApplication m_IApp;
    IAcadDocument   m_IDoc;

    IAcadBlock    m_IBlock;
    IAcadBlocks    m_IBlocks;

3. In the dialog's OnInitDialog(), assign a separate button handler, and get
the application and document object (a button with handler code shown below).


void CClientDlg::OnStart()
{
    HRESULT hr = NOERROR;
    CLSID clsid;
    LPUNKNOWN pUnk = NULL;
    LPDISPATCH pDisp = NULL;

    BeginWaitCursor();
    CoInitialize(NULL);
    hr = ::CLSIDFromProgID(L"AutoCAD.Application", &clsid);

    if (SUCCEEDED(hr))
    {
      if(::GetActiveObject(clsid, NULL, &pUnk) == S_OK)
      {
            VERIFY(pUnk->QueryInterface(IID_IDispatch,(LPVOID*)&pDisp) == S_OK);
            m_IApp.AttachDispatch(pDisp);
            pUnk->Release();
      }
      else
            VERIFY(m_IApp.CreateDispatch(clsid) == TRUE);

      m_IApp.SetVisible(TRUE);

      pDisp = m_IApp.GetActiveDocument();
      m_IDoc.AttachDispatch(pDisp);
    }
    else
      AfxMessageBox("Acad.Application is not registered!");
            //CoUninitialize(); // do this in the dialog's exit code
    EndWaitCursor();
}

4. Create a button and its handler, then add the following code:


void CClientDlg::OnAddBlock()
{
    VARIANT var;
    double pt = {2, 2, 0};
    getVariantFromDblArray(&var, pt);
    const char blkName[] = "TEST";
    LPDISPATCH p = m_IDoc.GetBlocks();
    m_IBlocks.AttachDispatch(p);
    p = m_IBlocks.Add(var, blkName);
    m_IBlock.AttachDispatch(p);
}

HRESULT getVariantFromDblArray(VARIANT* pVal, const double pt)
{
    pVal->vt = VT_ARRAY | VT_R8;

    SAFEARRAYBOUND rgsaBound;
    rgsaBound.lLbound = 0L;
    rgsaBound.cElements = 3;

    pVal->parray = SafeArrayCreate(VT_R8, 1, &rgsaBound);
    if (! pVal->parray)
      return E_OUTOFMEMORY;

    HRESULT hr;
    for (long i = 0; i < 3; i++)
      if ((hr = SafeArrayPutElement(pVal->parray, &i,
(void*)&pt))!=S_OK)
            return hr;
    return S_OK;
}


页: [1]
查看完整版本: Adding A Block Using ActiveX Client In C++