Jump to content

VB to toggle viewports with layers


jaredmccullough

Recommended Posts

I have no experience with VB in Autocad but have used it quite often in other word based applications and know the abilities it has. I was wondering if it could be applied in Autocad as a Macro based function to key on MVIEW of certain things.

 

Background: Viewport 1 is assigned to "Viewport 1" Layer (the frame of it) I am currently applying the layer in which the viewport frame appears. I MVIEW = ON for that viewport frame and the viewport appears. This works vice versa as well. In general this is similar throughout the whole file. What I am wondering is if you could use a Macro that would function in a way that "Viewport" Layer is turned on that frame which is assigned to it appears. Then eIther by the turning on of the layer or by the frame appearing could this trigger MVIEW = ON and for the turning off of layer or frame disappearing MVIEW = OFF.

Link to comment
Share on other sites

  • Replies 22
  • Created
  • Last Reply

Top Posters In This Topic

  • jaredmccullough

    12

  • BlackBox

    11

A simple Reactor (read Event Handler) can do this... I know Visual LISP, and .NET can do this handily; not sure about VBA.

 

You'd want to hook the ObjectModified Event for the Layer Object, and based on the resultant change in status, modify the Viewport accordingly.

Link to comment
Share on other sites

Blackbox thank you for the quick response.....As stated my knowledge with Autocad is limited. Could you provide me with a little more insight into how to approach this or learn about the applications you are discussing? Would you be my guide in the direction of what I am looking towards?

Link to comment
Share on other sites

I would add though, since you're relatively new to AutoCAD, that most instead find it simpler to just make the Viewport's layer 'No Plot' then it can be on all of the time, and still not, well, 'plot'.

 

HTH

Link to comment
Share on other sites

Blackbox thank you for the quick response.....As stated my knowledge with Autocad is limited. Could you provide me with a little more insight into how to approach this or learn about the applications you are discussing? Would you be my guide in the direction of what I am looking towards?

 

You're welcome.

 

AutoCAD supports a small handful of developer APIs... To better help you, perhaps you could first provide me a bit more info?

 

You mentioned being adept at VB... Is that VBA (Visual Basic for Applications), or VB.NET?

 

I personally learned Visual LISP, which is an ActiveX COM extension to AutoLISP, and have since jumped to .NET (mostly C#)... I'd hate to further confuse by not first asking the above.

Link to comment
Share on other sites

Blackbox sorry for not getting back to you yesterday. As far as VB experience goes it is mostly related to developing macros for Microsoft based applications (excel, word, etc...).

 

Attached is an example of something similar to what I am trying to achieve. If you look there are 2 viewports. Each viewport frame is assigned to a seperate layer ("Viewport 1" and "Viewport 2"). In my file their are quite a few viewports all with their frames assigned to different layers. Currently how I toggle them is to apply the layer>MVIEW>ON>Select the Viewport Frame>Enter this makes the viewport visable and similary to turn it off MVIEW>OFF>Select Viewport Frame>Enter>Then unapply layer.

 

What I am trying to do is make it so when I apply the layer the viewport frame appears as well as the objects in it but when I disapply the layer they turn off. I began to think and figured that there is the potential to maybe use VB to make it that when a layer is applied all the viewport frames will appear pertaining to that layer and if you could some how use this either the layer or the frames appearing to trigger the MVIEW>ON and MVIEW>OFF function this would solve my issue. But I am willing to any suggestions as far as this Visual LISP or VB.net that you speak off that would do the same. And thank you for all your help.

Link to comment
Share on other sites

I'm still not sure I understand your goal, or at least why VBA is necessary (sorry).

 

If you want to be able to toggle the ViewportOn Property, just do so, there's no need for this complex apply layer, remove layer supplement, which sounds like it's being added only as a mechanism to react to (think event-driven code) when not necessary... If I am mistaken and the separate layers for each Viewport are necessary please correct me.

 

If I am correct, and all you want to do is to toggle the ViewportOn Property, without needing to invoke the MVIEW Command, specify On/Off, then consider these simple LISP examples:

(defun c:Test1 ()
 (command "._mview" "off")
 (princ)
)

(defun c:Test2 ()
 (command "._mview" "on")
 (princ)
)

(defun c:Test3 (/ *error* acDoc)

 (defun *error* (msg)
   (if acDoc
     (vla-endundomark acDoc)
   )
   (cond ((not msg))                                                   ; Normal exit
         ((member msg '("Function cancelled" "quit / exit abort")))    ; <esc> or (quit)
         ((princ msg))                                                 ; Fatal error, display it
   )
   (princ)
 )

 (if (= 0 (getvar 'tilemode))
   (if (ssget "_:L" '((0 . "VIEWPORT")))
     (progn
       (vla-startundomark
         (setq acDoc (vla-get-activedocument (vlax-get-acad-object)))
       )
       (vlax-for x (vla-get-activeselectionset acDoc)
         (vla-put-viewporton x (~ (vlax-get x 'viewporton)))
       )
     )
   )
   (*error* "\n** Command not allowed in Model Tab **")
 )
 (*error* nil)
)

 

Test1, and Test2 prompts the user for an 'On/Off' specification, and then invokes the MVIEW Command, which allows the user to select any Viewport in Layout.

 

Test3 effectively does the same as Test1, and Test 2 combined (if ViewportOn is enabled, it disables, etc.), using ActiveX instead of Command call.

 

HTH

Link to comment
Share on other sites

The issue that I guess I feel that this application would be needed for is that the drawing consists of a multitude of XREF drawings and their is quite a variance between the importance of certain viewports. Thus I have assigned viewports to layers related to their functions within the drawing. Some layers may contain 6 viewports while others contain 1. As I stated previously the intent of the file relates closely to being able to turn on and off viewports. So at that point say I apply a layer with 5 viewports on it. All these viewports frames "Toggle" on now I have to indivdually MVIEW>ON each indivdual one. Then similarly I have to MVIEW>OFF each individual one when I want to turn that layer off to apply another layer to that viewport.

 

I understand that this sounds simplistic in a sense and their are other ways of doing it especially if I was only dealing with a few viewports but I was more looking for something that would make navigating through my drawing easier. If this function you feel is to complicated and I would be more hindering becasue of it I will listen to your advice and continue with the MVIEW process I just thought that potentially VB or this VisualLISP could be used to control this function of layers, viewports, and MVIEW

Link to comment
Share on other sites

A couple of things that would help to clarify....

 

One can only apply (put) a Viewport on one layer.

 

When you say 'say I apply a layer with 5 viewports on it', do you mean that you've modified the layer to be Thawed, or On (from being Frozen, or Off)?

 

I cannot open your drawing as I do not have 2013+ at present (only at home).

Link to comment
Share on other sites

Sorry for the poor terminology essentially when I say apply I mean to "Turn On" or "Turn Off" a layer. Just an example of one aspect that this would benefit.

 

I have a layer say "Department Viewports" it has 5 Viewports.... I "Turn On" that layer all 5 of the viewport frames appear. But then I have to individually go to each viewport frame and MVIEW>ON to have the viewport objects appear. Hopefully this clarifies a little better. The file itself is to large for this website that is why I made the example to that I could potentially describe my intents with

Link to comment
Share on other sites

Sorry for the poor terminology essentially when I say apply I mean to "Turn On" or "Turn Off" a layer. Just an example of one aspect that this would benefit.

 

No worries; perhaps it was I who was getting hung up on terminology. Thanks for clarifying.

 

I have a layer say "Department Viewports" it has 5 Viewports.... I "Turn On" that layer all 5 of the viewport frames appear. But then I have to individually go to each viewport frame and MVIEW>ON to have the viewport objects appear.

 

Again, perhaps I'm just getting hung up on path of least resistance here... Why set MVIEW-->OFF in the first place?

 

I only ask, as when a layer is Off, nothing on that layer is visible, or plottable... This is the reason most simply set their assigned layers for Viewports as 'No Plot', so that they may remain visible at all times, yet the Viewport frames themselves do not plot.

 

Code can do what you're after, I'm just trying to understand the logic first in the event there's a simpler solution.

 

HTH

Link to comment
Share on other sites

Ill give you a little something for your imagination, Picture this:

 

A single square viewport in the middle of a Layout1 its frame is set layer

"Viewport 1", currently this layer is active and the viewport MVIEW>ON. Now I have created 5 other viewports (small circular viewports around it). These frames for these viewports are set on layer "Department Viewports" this layer is only needed for a handful of purposes and is only "Turned On" when needed but is "Turned Off" right now. If I didnt not MVIEW>OFF these smaller viewports only the frames will disappear when I turn the layer off but not the objects so to have them turn of I have to MVIEW>OFF each of these individually then turn "Department Viewports" layer off.

 

This theory is used in many other layouts and viewports throughout thats why I was really hoping to come up with something.

Link to comment
Share on other sites

Is it safe to assume that you're modifying these Viewport layers by built-in Commands/Menus/Buttons, etc.?

Link to comment
Share on other sites

I currently have not done anything to the layers besides assigned viewport frames to them and using MVIEW to either turn OFF or ON the objects withing them.

Link to comment
Share on other sites

  • 4 weeks later...

Blackbox are you still around... sorry I was on an extended business trip.....or can anyone else help me?

Link to comment
Share on other sites

Still here... So just getting back into this, using your example....

 

When on "Viewport 1" all Viewports not on "Viewport 1" MVIEW--> OFF... Then when switching from "Viewport 1" to "Department Viewports" (or any other layer), all Viewports on "Viewport 1" become MVIEW-->OFF, and Viewports on "Department Viewports" become MVIEW-->ON?

 

If I am understanding you correctly; Lemon squeezy.

 

(vl-load-com)
;;;--------------------------------------------------------------------;
(defun ViewportReactor:Start ()
 (or *ViewportReactor*
     (setq *ViewportReactor*
            (vlr-sysvar-reactor
              "My viewport reactor "
              '(
                (:vlr-sysvarchanged . ViewportCallback:SysVarChanged)
               )
            )
     )
 )
 (princ)
)
;;;--------------------------------------------------------------------;
(defun ViewportCallback:SysVarChanged (rea var / clayer)
 (if (and (= "CLAYER" (strcase (car var))) (cadr var))
   (vlax-for x (vla-get-paperspace
                 (vla-get-activedocument
                   (vlax-get-acad-object)
                 )
               )
     (if (= "AcDbViewport" (vla-get-objectname x))
       (progn
         (setq clayer (strcase (getvar 'clayer)))
         (vl-catch-all-apply
           'vla-put-viewporton
           (list
             x
             (if (= clayer (strcase (vla-get-layer x)))
               :vlax-true
               :vlax-false
             )
           )
         )
         (vla-update x)
       )
     )
   )
 )
 (princ)
)
;;;--------------------------------------------------------------------;
(ViewportReactor:Start)
(princ)

 

[Edit] ** Does not account for locked layers at this time.

Edited by BlackBox
Link to comment
Share on other sites

... And in .NET (including the locked layer check); written quickly, and untested:

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;

using acApp = Autodesk.AutoCAD.ApplicationServices.Application;

using System.Collections.Generic;

[assembly: ExtensionApplication(typeof(CADTutor.Sample.ViewportsToggle.Events))]

namespace CADTutor.Sample.ViewportsToggle
{
   class Events : IExtensionApplication
   {
       void IExtensionApplication.Initialize()
       {
           acApp.DocumentManager.DocumentCreated += onDocumentCreated;

           Document doc = acApp.DocumentManager.MdiActiveDocument;

           doc.Database.SystemVariableChanged += onSystemVariableChanged;
       }
       void IExtensionApplication.Terminate()
       {
       }
       static void onDocumentCreated(object sender, DocumentCollectionEventArgs e)
       {
           Document doc = e.Document;

           if (doc != null)
               doc.Database.SystemVariableChanged += onSystemVariableChanged;
       }
       static void onSystemVariableChanged(object sender, 
           Autodesk.AutoCAD.DatabaseServices.SystemVariableChangedEventArgs e)
       {
           if (e.Changed == true && e.Name.ToUpper() == "CLAYER")
           {
               Database db = HostApplicationServices.WorkingDatabase;

               using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
               {
                   BlockTableRecord btr =
                       (BlockTableRecord)tr.GetObject(
                           SymbolUtilityServices.GetBlockPaperSpaceId(db),
                           OpenMode.ForRead);

                   string clayer = db.Clayer.ToString().ToUpper();

                   List<LayerTableRecord> layersToLock = new List<LayerTableRecord>();

                   foreach (ObjectId id in btr)
                   {
                       Viewport vp =
                           tr.GetObject(id, OpenMode.ForRead) as Viewport;

                       if (vp != null)
                       {
                           string vpLayer = vp.Layer.ToUpper();

                           LayerTableRecord ltr =
                               (LayerTableRecord)tr.GetObject(vp.LayerId, OpenMode.ForWrite);

                           if (ltr.IsLocked == true)
                           {
                               layersToLock.Add(ltr);

                               ltr.IsLocked = false;
                           }

                           vp.UpgradeOpen();

                           if (clayer == vp.Layer.ToUpper())
                               vp.On = true;

                           else
                               vp.On = false;
                       }
                   }

                   foreach (LayerTableRecord ltr in layersToLock)
                       ltr.IsLocked = true;

                   tr.Commit();
               }
           }
       }
   }
}

Link to comment
Share on other sites

I may have forgot to mention my lack of knowledge or interaction with VLISP or coding in Autocad since my first post but where exactly do I drop these codes into? I have seen the VLISP Editor and was wondering if that was where the code was to be inserted. Again thank you for helping me with this project BlackBox

Link to comment
Share on other sites

LISP, unlike .NET, is Document resident, and must be loaded into each Drawing for the code to be functional... This is why you see so many LISP developers speak affectionately of Acad.lsp (loaded once per session by default), AcadDoc.lsp (loaded each time a Drawing is opened), and the Autoload function (which allows for demand-loading, as each .LSP loaded takes up memory, and a bit a time to actually load).

 

To try LISP posted here in the forums, simply paste the code into a new, empty text file, and save it with a ".lsp" file extension... Then you can drag and drop it into your AutoCAD session to test, or use the LOAD function within AcadDoc.lsp, etc... Some use Appload Startup Suite, but I always prefer Acad.lps, and AcadDoc.lsp instead (both user-defined files).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...