Author Topic: Passing reactors/callbacks to COM object and calling them from the COM object  (Read 4715 times)

0 Members and 1 Guest are viewing this topic.

Daniel Eiszele

  • Newt
  • Posts: 85
I don't have autocad so the visual lisp activex module is only something I found online. It appears to be a dll you can reference in your  com project which gives direct access to the available lisp functions bypassing the command line. You will have to google it if you want to find out more as I don't have access to acad and can't test anything I find anyway.

As far as a Com addin is concerned; it is basically the same activex object but you implement the Iextensibility2 interface.  Then you add entries in the registry so that it loads automatically when autocad starts.  From there on in any functions that you register with autocad are automatically available from the command line. You can also add these functions to toolbars and menu items and react to application and document events.  And because it is in process you should see a big speed difference in computation intensive operations.

Something to think about maybe?

SIDESHOWBOB

  • Guest
Cheers will have to investigate further.  Don't think I need to make a COM addin - my vlisp handles the interface quite nicely now and the dll when called is fast enough.

SIDESHOWBOB

  • Guest
For future reference - over COM, I just found the Update method on the application object which causes it to, er, update.

This can be combined with ActiveDocument.Utility.Prompt to display messages synchronously in the Autocad window over COM.

If you begin each message with "\r" then it will overwrite the "Command:" prompt, though not the previous message sent to Prompt (any ideas on how to do this welcome!)

So, it's not quite a progress bar, but it'll do the job.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
If it's a progress bar you want ... and you're using the command-line to show a text representation of it, you don't need C++/ActiveX/COM for that. Here's a pure lisp function of mine which does much the same - but in the status bar:
Code - Auto/Visual Lisp: [Select]
  1. ;;; -------------------------------------------------------------------------------------
  2. ;;; Show a progress bar message in the status bar
  3. ;;; -------------------------------------------------------------------------------------
  4. (defun TextProgressBar (msg n / l i s)
  5.   (if n
  6.     (progn
  7.       ;; Get the mode tile's length
  8.       (setq l (- (atoi (menucmd "M=$(linelen)")) (strlen msg)))
  9.       ;; Get the numnber of characters simulating the number n (0.0= none, 1.0=all)
  10.       (setq i (fix (* l n)))
  11.       (repeat l
  12.         (if (> (setq i (1- i)) 0)
  13.           (setq s (cons 33 s))
  14.           (setq s (cons 46 s))
  15.         )
  16.       )
  17.       (grtext -1 (strcat msg (vl-list->string (reverse s))))
  18.     )
  19.     (grtext -1 msg)
  20.   )
  21. )
  22.  
If you want a true progress bar, then you could import a function call from the acad.exe file (as if it's a dll): http://through-the-interface.typepad.com/through_the_interface/2007/05/displaying_a_pr.html

BTW, while you're in C++, why're you making an ActiveX connection? I'd have thought you'd be better off going with C# & DotNet ... see some of the comments on the bottom of that page.

Edit: And if you want to call a lisp function directly, the the P/Invoke method (as explained in Kean's blog) can also work: http://www.theswamp.org/index.php?topic=35714.0
« Last Edit: April 01, 2012, 04:28:52 AM by irneb »
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

BlackBox

  • King Gator
  • Posts: 3770
If you don't mind the .ARX requirement, there's always the Dos_GetProgress function too.
"How we think determines what we do, and what we do determines what we get."

SIDESHOWBOB

  • Guest
@irneb - cheers - displaying a progress bar from lisp was never the issue.  My app architecture is autocad -> vlisp -> COM -> C++ because I was hoping to gain wide compatibility over different autocad versions, rather than taking the .net approach where I have to recompile the plugin for each autocad version I would like to support.  The progress bar however has to call functions in the reverse direction (C++ to autocad) so whether I'll have actually achieved version independence (given I'm now using undocumented COM calls) is another matter..!

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Yes, if you're using P/Invoke you might find there's some issues between versions - seeing as the function entry point may be different in 2 acad.exe files. I think the major one would be at the 2006 split when ADesk changed to using UniCode.

The DotNet stuff doesn't need recompiling all the time. It depends on the versions, some versions work perfectly fine with the same DLL file (e.g. I've got some which work on both 2008 and 2012). The issue is that you need to compile using the lowest common DotNet version - e.g. instead of 3.5 use 2.0. Also try to steer clear of API functions newly introduced into newer versions. Apparently there's some new requirement with 2013, though I've not tested it yet.

The ARX's need recompiling between major versions. Every time the "true" version number's integer portion changes. Thus 2007/8/9 may work fine with the same ARX, but a new one would be required for 2010/11/12. Thus far ADesk's grouped their major versions into 3 consecutive releases.

All that said, I'm unsure why you're going with COM outside of lisp. Is there some reason? AFAIK all acad's com interfaces are also available in VLisp. And the stuff you can't get to in ALisp/VLisp is definitely also impossible to get to through COM.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

SIDESHOWBOB

  • Guest
All that said, I'm unsure why you're going with COM outside of lisp. Is there some reason?

Yes.  The app backend is CPU heavy, and is already written in native c++ (for another frontend, not autocad).  I wrapped it in COM so I could call it from lisp.  This is all fine until I need a progress bar - the backend has to make 'update progress' calls, but as vlisp doesn't support callbacks over COM, another method was needed so the C++ could communicate to the autocad user how much progress had been made (at intervals chosen by the algorithm running in C++).  This eventually led me to autocad's COM interface which allows me to put messages in the display directly over COM, bypassing the lisp environment (which I can't access from there in any case).

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Have you thought of popping up a modal dialog box with a message & windows progress bar? That way you don't need to fiddle with strange ways of getting acad's progress bar to display - just use a normal windows form which you can create direct in C++.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

SIDESHOWBOB

  • Guest
Yes, though I'm happy with the Prompt and Update COM calls for now.

SIDESHOWBOB

  • Guest
Have you thought of popping up a modal dialog box with a message & windows progress bar? That way you don't need to fiddle with strange ways of getting acad's progress bar to display - just use a normal windows form which you can create direct in C++.

Irneb,

I'm coming back around to this idea.  If I want to do this, don't I need to get the HWND of autocad from somewhere?  Do you know how to do that?


Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
If I want to do this, don't I need to get the HWND of autocad from somewhere?  Do you know how to do that?

In LISP:

Code - Auto/Visual Lisp: [Select]

Or, for the Active Document window:

Code - Auto/Visual Lisp: [Select]

BlackBox

  • King Gator
  • Posts: 3770

I also use this (vla-get-hwnd) with the Shell.Application Object's BrowseForFolder Method.  :wink:
"How we think determines what we do, and what we do determines what we get."