NO

Author Topic: Pelles-C + OLE for access to AutoCAD  (Read 4031 times)

Offline sergey

  • Member
  • *
  • Posts: 97
Pelles-C + OLE for access to AutoCAD
« on: May 27, 2016, 02:29:06 PM »
Continuing the theme:
http://forum.pellesc.de/index.php?topic=6936.0

OLE-Automation allows you to connect to such "heavy" server as AutoCAD.
There is no need to use C ++.
There is no need to connect to the project AutoCAD library such as a *.tlb or *.dll
To this end it is necessary and sufficient to know AutoCAD objects available from the Windows registry.
It is enough to know the names of the objects and the names of the methods of these objects.
Console application written in Pelles-C, is connected to the AutoCAD and is further AutoCAD dialog box - Drawing-templates.
This means that AutoCAD objects actually available for programming.

Important features:
1. The absence of complex (and often obscure) programming constructs.
2. assume that the program does not depend on the version of AutoCAD (almost every following post-2000-year version of AutoDesk that any changes in the program access to your product).

Of course there is not the program, but only a 'template', have to learn the basics of OLE-Automation.

There is another interesting tool for OLE-Automation - 'disphelper'.
But it is poorly documented.
Here is an example of using 'disphelper' for access to MS-Excel from C-lang.
Unfortunately I was not able to compile this example in Pelles-C.
In MS-VC2005 environment it works.

References:
https://support.microsoft.com/en-us/kb/181473
https://en.wikipedia.org/wiki/IDispatch
http://disphelper.sourceforge.net/

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1583
Re: Pelles-C + OLE for access to AutoCAD
« Reply #1 on: May 28, 2016, 09:55:57 AM »
« Last Edit: May 28, 2016, 10:10:16 AM by TimoVJL »
May the source be with you

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #2 on: May 28, 2016, 09:15:41 PM »
Good examples.
However, Word and Excel Microsoft products.
Therefore, these examples demonstrate quite well themselves and Microsoft.

I am interested in a different problem: how to get to the object model of AutoCAD?
And along the way there is an insurmountable obstacle: the initialization of the object 'AutoCAD.Document'.
Because almost all of the objects needed to work/programming in AutoCAD, only available as a 'AutoCAD.Document.<ALL_OBJECTS_OF_THE_AutoCAD>'.

I rewrote your example for MS-WORD eg for AutoCAD.
But as in the previous examples, the object initialization 'AutoCAD.Document' NOT occurs.
It does not occur even when the project has acax17enu.h file (in which almost the entire object model AutoCAD).
But I have not found a way to connect to the file.

From this I conclude: all of these examples to work exclusively through Windows registry.
And there is no object 'AutoCAD.Document'.

If anyone knows the solution to this problem (?).
With the example of a few lines of code, not blah-blah-blah ...

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1583
Re: Pelles-C + OLE for access to AutoCAD
« Reply #3 on: May 29, 2016, 11:40:12 AM »
DispHelper test:
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include "disphelper.h"
#include <stdio.h>
#pragma comment(lib, "user32")

#define HR_TRY(func) if (FAILED(func)) { printf("\n## Fatal error on line %d.\n", __LINE__); goto cleanup; }

int ACadSample1(void)
{
DISPATCH_OBJ(pApp);
dhInitialize(TRUE);
dhToggleExceptions(TRUE);

HR_TRY( dhCreateObject(L"AutoCAD.Application", NULL, &pApp) );
dhPutValue(pApp, L".Visible = %b", TRUE);
HR_TRY( dhCallMethod(pApp, L".Documents.Add") );
DISPATCH_OBJ(pDoc);
HR_TRY( dhGetValue(L"%o", &pDoc, pApp, L".ActiveDocument") );

cleanup:
dhToggleExceptions(FALSE);
SAFE_RELEASE(pApp);
dhUninitialize(TRUE);
return 0;
}

int main(void)
{
ACadSample1();
return 0;
}
Look acadauto.chm for objects.

For old IntelliCAD 6.x engine (progeCAD Smart 2009) AutoWrap example too:
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <ole2.h>
#include <stdio.h>

#pragma lib "user32.lib"
#pragma lib "ole32.lib"
#pragma lib "oleaut32.lib"
#pragma lib "uuid.lib"

HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
      WCHAR* ptName, int cArgs, ...);

//int main(int argc, char* argv[])
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
// Initialize COM for this thread...
   CoInitialize(NULL);

   // Get CLSID for our server...
   CLSID clsid;
   HRESULT hr = CLSIDFromProgID(L"ICad.Application", &clsid);

   if(FAILED(hr)) {

      MessageBox(NULL, "CLSIDFromProgID() failed", "Error", 0x10010);
      return -1;
   }

   // Start server and get IDispatch...
   IDispatch *pApp;
   hr = CoCreateInstance(&clsid, NULL, CLSCTX_LOCAL_SERVER, &IID_IDispatch, (void **)&pApp);
   if(FAILED(hr)) {
      MessageBox(NULL, "ICad not registered properly", "Error", 0x10010);
      return -2;
   }

   // Make it visible (i.e. app.visible = 1)
   {
      VARIANT x;
      x.vt = VT_I4;
      x.lVal = 1;
      AutoWrap(DISPATCH_PROPERTYPUT, NULL, pApp, L"Visible", 1, x);
   }
   IDispatch *pLib = NULL;
   {
      VARIANT result;
      VariantInit(&result);
      AutoWrap(DISPATCH_PROPERTYGET, &result, pApp, L"Library", 0);
      pLib = result.pdispVal;
   }
   IDispatch *pDoc = NULL;
   {
      VARIANT result;
      VariantInit(&result);
      AutoWrap(DISPATCH_PROPERTYGET, &result, pApp, L"ActiveDocument", 0);
      pDoc = result.pdispVal;
   }
   IDispatch *pModelSpace = NULL;
   {
      VARIANT result;
      VariantInit(&result);
      AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, L"ModelSpace", 0);
      pModelSpace = result.pdispVal;
   }

   IDispatch *pPoint1 = NULL;
   {
      VARIANT result;
      VariantInit(&result);
      VARIANT parm1, parm2, parm3;
      parm1.vt = VT_R8; parm1.dblVal = 0.0; // Z
      parm2.vt = VT_R8; parm2.dblVal = 0.0; // Y
      parm3.vt = VT_R8; parm3.dblVal = 0.0; // X
      AutoWrap(DISPATCH_PROPERTYGET | DISPATCH_METHOD, &result, pLib, L"CreatePoint", 3, parm1, parm2, parm3);
      pPoint1 = result.pdispVal;
   }
   IDispatch *pPoint2 = NULL;
   {
      VARIANT result;
      VariantInit(&result);
      VARIANT parm1, parm2, parm3;
      parm1.vt = VT_R8; parm1.dblVal =   0.0; // Z
      parm2.vt = VT_R8; parm2.dblVal = 100.0; // Y
      parm3.vt = VT_R8; parm3.dblVal = 100.0; // X
      AutoWrap(DISPATCH_PROPERTYGET | DISPATCH_METHOD, &result, pLib, L"CreatePoint", 3, parm1, parm2, parm3);
      pPoint2 = result.pdispVal;
   }
   IDispatch *pLine1 = NULL;
   {
      VARIANT result;
      VariantInit(&result);
      VARIANT parm1, parm2;
      parm1.vt = VT_DISPATCH; parm1.pdispVal = pPoint2;
      parm2.vt = VT_DISPATCH; parm2.pdispVal = pPoint1;
      AutoWrap(DISPATCH_PROPERTYGET | DISPATCH_METHOD, &result, pModelSpace, L"AddLine", 2, parm1, parm2);
      pLine1 = result.pdispVal;
   }
   {
      VARIANT x;
      x.vt = VT_I4;
      x.lVal = 1;
      AutoWrap(DISPATCH_PROPERTYPUT | DISPATCH_METHOD, NULL, pDoc, L"Regen", 1, x);
   }


   // Release references...
   if (pModelSpace) pApp->lpVtbl->Release(pModelSpace);
   if (pDoc) pApp->lpVtbl->Release(pDoc);
   if (pLib) pApp->lpVtbl->Release(pLib);
   if (pApp) pApp->lpVtbl->Release(pApp);
   // Uninitialize COM for this thread...
   CoUninitialize();
      return 0;
}

//
// AutoWrap() - Automation helper function...
//
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp,
      WCHAR* ptName, int cArgs, ...)
{
      // Begin variable-argument list...
      va_list marker;
      va_start(marker, cArgs);

      if(!pDisp) {
            MessageBox(NULL, "NULL IDispatch passed to AutoWrap()",
                       "Error", 0x10010);
            exit(0);
      }

      // Variables used...
      DISPPARAMS dp = { NULL, NULL, 0, 0 };
      DISPID dispidNamed = DISPID_PROPERTYPUT;
      DISPID dispID;
      HRESULT hr;
      char buf[200];
      char szName[200];

      // Convert down to ANSI
      WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);

      // Get DISPID for name passed...
      hr = pDisp->lpVtbl->GetIDsOfNames(pDisp, &IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT,
                                &dispID);
      if(FAILED(hr)) {
            sprintf(buf,
                    "IDispatchGetIDsOfNames(\"%s\") failed w/err0x%08lx",
                    szName, hr);
            MessageBox(NULL, buf, "AutoWrap()", 0x10010);
            return hr;
      }

      // Allocate memory for arguments...
      VARIANT *pArgs = malloc((cArgs+1) * sizeof(VARIANT));

      // Extract arguments...
      for(int i=0; i<cArgs; i++) {
            pArgs[i] = va_arg(marker, VARIANT);
      }

      // Build DISPPARAMS
      dp.cArgs = cArgs;
      dp.rgvarg = pArgs;

      // Handle special-case for property-puts!
      if(autoType & DISPATCH_PROPERTYPUT) {
            dp.cNamedArgs = 1;
            dp.rgdispidNamedArgs = &dispidNamed;
      }

      // Make the call!
      hr = pDisp->lpVtbl->Invoke(pDisp, dispID, &IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType,
                         &dp, pvResult, NULL, NULL);
      if(FAILED(hr)) {
            free(pArgs);
            sprintf(buf,
                    "IDispatchInvoke(\"%s\"=%08lx) failed w/err 0x%08lx",
                    szName, dispID, hr);
            MessageBox(NULL, buf, "AutoWrap()", 0x10010);
            return hr;
      }
      // End variable-argument section...
      va_end(marker);

      free(pArgs);

      return hr;
}
« Last Edit: May 31, 2016, 04:18:36 PM by TimoVJL »
May the source be with you

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #4 on: May 30, 2016, 07:21:51 PM »
Another great example! Thank you for your attention.

I want to note: 'ProgeCAD' draws the 'Line' but does not draw 'Poin1' and 'Poin2'.
It would be good to add a strings for connection to the existing 'ICad' object (i.e. check out 'ICad' that is already running on your computer).

'ACADAUTO.CHM' documents and other reading since 2005 (I was something written in VBA and VB6.

All my attempts to adapt your code to AutoCAD failed.
Chain:
'Application' -> 'ActiveDocument' -> 'ModelSpace'
does not work, 'Point' and 'Line' are NOT created.
I have added the 'Documents' and 'Document' that through the chain:
'Application' -> 'Documents' -> 'Document' -> 'ModelSpace'
create a 'Point' and 'Line' - it did not happen.
Formally all of the objects 'AutoCAD' up to 'ModelSpace' are created.

Of course I can throw this venture.
Object Model 'IntelliCad' more accessible than the 'AutoCAD'.
I can write the right things on VisualBasic-6 for the 'AutoCAD'.
But I'm haunted by a complete lack of information about what 'AutoCAD' is available for the programming of 'Plain-C'.
Even not-free 'Object-ARX VC ++' from AutoDesk work as VBA within 'AutoCAD' and change (obsolete) every three years.
Some success in this business reached only Delphi-programmers. But it 'OOP'.

If you have the opportunity and have a desire to look my code in the 'AutoCAD'.
Maybe things are not so hopeless and you can fix the code to make it work.

Thanks again for your attention and good advice.

Here my example:

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #5 on: May 31, 2016, 12:39:06 AM »
Yes, but ...  so:
To create a point, use the AddPoint method.
-------------------------------------------
Creates a Point object at a given location.
Signature
---------
RetVal = object.AddPoint(Point)
Object
------
ModelSpace Collection, PaperSpace Collection, Block
The object or objects this method applies to.
Point
-----
Variant (three-element array of doubles); input-only
The coordinates of the point to be created.
RetVal
------
Point object - The newly created Point object.

Sub Example_AddPoint()
    ' This example creates a point in model space.
    Dim pointObj As AcadPoint
    Dim location(0 To 2) As Double
   
    ' Define the location of the point
    location(0) = 5#: location(1) = 5#: location(2) = 0#
   
    ' Create the point
    Set pointObj = ThisDrawing.ModelSpace.AddPoint(location)
    ZoomAll
   
End Sub

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #6 on: May 31, 2016, 11:51:00 PM »
Add some code ProgeCAD:
Code: [Select]
   IDispatch *pAddPnts = NULL;
   {
VARIANT result;
VariantInit(&result);
VARIANT parm1, parm2;
parm1.vt = VT_DISPATCH; parm1.pdispVal = pPoint1;
parm2.vt = VT_DISPATCH; parm2.pdispVal = pPoint2;
AutoWrap(DISPATCH_PROPERTYGET | DISPATCH_METHOD, &result, pModelSpace, L"AddPointEntity", 1, parm1);
AutoWrap(DISPATCH_PROPERTYGET | DISPATCH_METHOD, &result, pModelSpace, L"AddPointEntity", 1, parm2);
pAddPnts = result.pdispVal;
   }

2 small 'Points' on ends of the 'Line':

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1583
Re: Pelles-C + OLE for access to AutoCAD
« Reply #7 on: June 01, 2016, 08:40:07 AM »
I think in older IntelliCAD (<7)/progeCAD uses Library.CreatePoint result Point only as location for other functions.
AutoCAD use Utility.CreateTypedArray Point1, vbDouble, 0,0,0 for creating array of 3 doubles for same purpose.
May the source be with you

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #8 on: June 06, 2016, 09:45:58 AM »
1. AutoCAD plases in Windows-registry ONLY 'CLSID_AcadApplication'
   but to programming AutoCAD you need also (as minimum) 2 objects:
   CLSID_AcadDocument
   CLSID_AcadModelSpace
   wich missing (not presents) in Windows-registry.

2. Script-lang Python has module named 'comtypes-1.1.2',
   wich helpfully connect to AutoCAD and programmin it.
   https://github.com/enthought/comtypes/releases

3. sample-code Python (ver.2.7):
Code: [Select]
   c:\cmd.exe python
   import array
   import comtypes.client
   #Get running instance of the AutoCAD application
   app = comtypes.client.GetActiveObject("AutoCAD.Application")
   #Get the ModelSpace object
   ms = app.ActiveDocument.ModelSpace
   #Add a POINT in ModelSpace
   pt = array.array('d', [0,0,0])
   point = ms.AddPoint(pt)
   #Add a LINE in ModelSpace
   pt1 = array.array('d', [1.0,1.0,0])
   pt2 = array.array('d', [2.0,2.0,0])
   line = ms.AddLine(pt1, pt2)
4. Roman Haritonov wrote Python-application
   https://github.com/reclosedev/pyautocad
   http://readthedocs.org/docs/pyautocad
   to 'manage' AutoCAD by 'comtypes-1.1.2':
   pyautocad.api: api.py types.py utils.py compat.py cache.py tables.py
   
5. Thomas Heller wrote by MS-VisuaStudio 'comtypes-1.1.2' (in 2005--2015)
   https://github.com/enthought/comtypes
   https://pypi.python.org/pypi/comtypes
   comtypes-1.1.2.zip\comtypes-1.1.2\source\ has 2 files:
   AvmcIfc.tlb and AvmcIfc.dll
   to enable write C/C++ applications for COM-OLE Automation,
   that enable also programming AutoCAD.
« Last Edit: June 06, 2016, 09:48:24 AM by sergey »

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1583
Re: Pelles-C + OLE for access to AutoCAD
« Reply #9 on: June 06, 2016, 04:55:13 PM »
Quite awful with C >:(
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define INITGUID
#include <ole2.h>

#define COBJMACROS
#define __AutoCAD_INCLUDEALIAS
typedef DWORD OLE_COLOR;
//line 3197: //typedef INT64 LONG_PTR ; /// allready in basetsd.h
//#include "acax17enu.h" // from acax18enu.tlb
#include "acad.h"

#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "oleaut32.lib")

char *szAppName = "AutoCadTest";

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
HRESULT hr;
CLSID clsid;
IUnknown *pUnk = NULL;
IAcadApplication *pACad = NULL;
IAcadDocument *pACadDoc = NULL;
IAcadUtility* pUtility = NULL;
IAcadDatabase *pDataBase = NULL;
IAcadModelSpace *pModelSpace = NULL;

CoInitialize(NULL);
hr = CLSIDFromProgID(L"AutoCAD.Application", &clsid);
hr = GetActiveObject(&clsid, NULL, (IUnknown **)&pUnk);
if (pUnk) hr = pUnk->lpVtbl->QueryInterface(pUnk, &IID_IAcadApplication, (void **)&pACad);
if (!pACad) hr = CoCreateInstance(&clsid, NULL, CLSCTX_ALL, &IID_IAcadApplication, (void **)&pACad);
if (pACad) {
IAcadApplication_put_Visible(pACad, -1);
IAcadApplication_get_ActiveDocument(pACad, &pACadDoc);
if (pACadDoc) {
IAcadDocument_get_Utility(pACadDoc, &pUtility);
IAcadDocument_get_Database(pACadDoc, &pDataBase);
if (pDataBase) {
IAcadDatabase_get_ModelSpace(pDataBase, &pModelSpace);
if (pModelSpace) {
IAcadLine *pLine;
VARIANT vpt1, vpt2; // for points
SAFEARRAY sarray1, sarray2; // for arrays
SAFEARRAYBOUND sab1[1], sab2[1];
sab1[0].lLbound = 0; sab1[0].cElements = 3;
sab2[0].lLbound = 0; sab2[0].cElements = 3;

VARIANT parm1[3], parm2[3];
parm1[0].vt = VT_R8; parm1[0].dblVal = 0.0; // X
parm1[1].vt = VT_R8; parm1[1].dblVal = 0.0; // Y
parm1[2].vt = VT_R8; parm1[2].dblVal = 0.0; // Z
parm2[0].vt = VT_R8; parm2[0].dblVal = 100.0; // X
parm2[1].vt = VT_R8; parm2[1].dblVal = 100.0; // Y
parm2[2].vt = VT_R8; parm2[2].dblVal = 0.0; // Z

sarray1.cDims = 1;
sarray1.fFeatures = FADF_VARIANT | FADF_HAVEVARTYPE | FADF_FIXEDSIZE | FADF_STATIC;
sarray1.cbElements = sizeof(VARIANT);
sarray1.cLocks = 0;
sarray1.pvData = &parm1;
sarray1.rgsabound[0].lLbound = 0;
sarray1.rgsabound[0].cElements = 3;

sarray2.cDims = 1;
sarray2.fFeatures = FADF_VARIANT | FADF_HAVEVARTYPE | FADF_FIXEDSIZE | FADF_STATIC;
sarray2.cbElements = sizeof(VARIANT);
sarray2.cLocks = 0;
sarray2.pvData = &parm2;
sarray2.rgsabound[0].lLbound = 0;
sarray2.rgsabound[0].cElements = 3;

IAcadUtility_CreateTypedArray(pUtility, &vpt1, VT_R8, &sarray1);
IAcadUtility_CreateTypedArray(pUtility, &vpt2, VT_R8, &sarray2);

IAcadModelSpace_AddLine(pModelSpace, vpt1, vpt2, &pLine);
if (pLine) {
MessageBox(0,"Line",0,0);
} else MessageBox(0,"No Line",0,0);
}
}
}
IAcadApplication_Release(pACad);
} else
MessageBox(0, "No AutoCAD.Application ?", szAppName, MB_OK);
CoUninitialize();
return 0;
}
« Last Edit: June 06, 2016, 09:09:02 PM by TimoVJL »
May the source be with you

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #10 on: June 06, 2016, 09:23:03 PM »
I see:
#include "acad.h"
It is from acad.exe ?
But can't compile acad.exe by 'FtypeLib.exe' - ERROR!

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1583
Re: Pelles-C + OLE for access to AutoCAD
« Reply #11 on: June 06, 2016, 10:01:46 PM »
No, it's from ACAD.TLB (v. 2000) created with FTypeLib.
Use your version of header, as example still needs IID_IAcadApplication from there.
« Last Edit: June 10, 2016, 05:45:27 PM by TimoVJL »
May the source be with you

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #12 on: June 06, 2016, 10:58:45 PM »
Paste from the previous 'acax17enu.h' ...
It really works!
And while AutoCadTest.exe = 22.5 kB

I did not know which way to look.
Even I started to do something in Python and VC ++.
But it did not work.

Now, for the expansion of this program. I will write functions.

I do not know how to thank you for your help.
THANK YOU! THANK YOU! THANK YOU!

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1583
Re: Pelles-C + OLE for access to AutoCAD
« Reply #13 on: June 10, 2016, 07:15:57 PM »
If someone don't want to include needlessly GUIDs to exe, here is some ideas :
Code: [Select]
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

const IID IID_ACAD_15 = {0x8e75d910,0x3d21,0x11d2,{0x85,0xc4,0x08,0x00,0x09,0xa0,0xc6,0x26}};
const IID IID_ACAD_16 = {0x93bc4e71,0xafe7,0x4aa7,{0xbc,0x07,0xf8,0x0a,0xcd,0xb6,0x72,0xd5}};
const IID IID_ACAD_17 = {0x8f17437c,0x2efb,0x4fc4,{0x81,0x88,0xee,0xfa,0x50,0xfe,0x71,0x47}};
const IID IID_ACAD_18 = {0x84f323fc,0xc179,0x4704,{0x87,0xe7,0xe3,0xd5,0x76,0xc2,0x59,0x9e}};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
{
HKEY hk;
TCHAR szTmp[260];
//ReadRegStr(HKEY_CLASSES_ROOT, "AutoCAD.Application\\CurVer", NULL, szTmp, sizeof(szTmp));
//if (RegOpenKey(HKEY_CLASSES_ROOT, TEXT("AutoCAD.Application\\CurVer"), &hk) == ERROR_SUCCESS) {
if (RegOpenKey(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Classes\\AutoCAD.Application\\CurVer"), &hk) == ERROR_SUCCESS) {
DWORD dwType, dwSize;
dwSize = sizeof(szTmp);
RegQueryValueEx(hk, NULL, 0, &dwType, (BYTE *)szTmp, &dwSize);
RegCloseKey(hk);
}
//int nVer = *(WORD*)&szTmp[20];
IID *pIID = NULL;
if (*(WORD*)&szTmp[20] == 0x3531) pIID = (IID*)&IID_ACAD_15;
else if (*(WORD*)&szTmp[20] == 0x3631) pIID = (IID*)&IID_ACAD_16;
else if (*(WORD*)&szTmp[20] == 0x3731) pIID = (IID*)&IID_ACAD_17;
else if (*(WORD*)&szTmp[20] == 0x3831) pIID = (IID*)&IID_ACAD_18;
pIID = NULL;
if (szTmp[21] == '5') pIID = (IID*)&IID_ACAD_15;
else if (szTmp[21] == '6') pIID = (IID*)&IID_ACAD_16;
else if (szTmp[21] == '7') pIID = (IID*)&IID_ACAD_17;
else if (szTmp[21] == '8') pIID = (IID*)&IID_ACAD_18;
if (pIID) MessageBox(0,szTmp,0,MB_OK);

return 0;
}
BOOL ReadRegStr(HKEY hKey, const TCHAR *szKey, const TCHAR *szSubKey, TCHAR *szValue, DWORD nSize)
{
HKEY hk;
DWORD dwType, dwSize;
if (RegOpenKey(hKey, szKey, &hk) == ERROR_SUCCESS)
{
dwSize = nSize;
RegQueryValueEx(hk, szSubKey, 0, &dwType, (BYTE *)szValue, &dwSize);
RegCloseKey(hk);
return TRUE;
}
return FALSE;
}
 
May the source be with you

Offline sergey

  • Member
  • *
  • Posts: 97
Re: Pelles-C + OLE for access to AutoCAD
« Reply #14 on: June 11, 2016, 07:44:38 PM »
Interesting idea, I will read and think.
In the meantime, here's what happens.

Practical work in AutoCAD often associated with any drawing, which already has some of the objects.
The program that loads AutoCAD with a blank drawing less in demand.
But I could not do so at the start of the program checked already downloaded copy AutoCAD (with the right to work drawing) and connect to the copy.

Therefore, I chose another way.
After loading AutoCAD with a blank drawing, the program calls the built-in in AutoCAD dialogue <FileOpen>.
And loads selected for the work a drawing.
After that will work functions that perform something in the user-selected drawing.

I left in a line of code, a program that creates 2 points and the line.
They do not interfere with the future work program, but it's nice please me - reminding help prfessionalny programmer on the most difficult stage of the creation of this program.
Thanks to him.

For some unknown reason to me the macro-command only works when you double call.
That line of code:
Code: [Select]
if (pACadDoc) {
IAcadDocument_SendCommand(pACadDoc, L"_open ");
IAcadDocument_SendCommand(pACadDoc, L"_OPEN");
}
And here are the options that do not work:
Code: [Select]
/*
if (pUtility) {
IAcadUtility_Prompt(pUtility, L"_open ");
IAcadUtility_Prompt(pUtility, L"_OPEN ");
// variants of:
//(pUtility)->lpVtbl->Prompt(pUtility, L"_open ");
//IAcadUtility_Prompt(pUtility, L"_open \\n");
}
*/