sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    SU to VB6.0 (Or there and back again.) :)

    Scheduled Pinned Locked Moved Developers' Forum
    9 Posts 4 Posters 7.4k Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • G Offline
      Gruff
      last edited by

      Figured out how to build a bridge finally.

      The answer I came up may not be the only way to go but it is the only one I've found to date.

      In this solution I wrote the VB6 application as an ActiveX dll.
      I use a stub ruby program with win32ole to instantiate the dll.
      I pass whatever instantiated SU object I wish to the dll as a reference through a public sub routine in the dll.

      From the dll I manipulate SU API object.
      A couple of things to note.

      1. Any objects passed back to SU must be passed as variant data types.
        If datatypes cannot be converted implicitly you will have to do it manually.
      2. All objects passed must be destroyed in the dll before the sub routine exits. (Set them to nothing)
      3. if the SU API defines a method as returning a value the VB implementation must do so also.
      4. Variants and UDT's are mutually exclusive so work arounds will have to be used.
      5. I only have the VB.NET 2008 Express version at home so I will not be able to test with VB.NET for now. (I assume that the generic 'Object' datatype will stand in for the Variant data type.

      Listing 1: SU stub code

      
      require 'sketchup'
      require 'win32ole'
      #---
      
      def testbed
        model = Sketchup.active_model
        entities = model.entities  
        tb = WIN32OLE.new('TestSUApp.clsTestSUApp') 
        # Pass the entities object to the DLL   
        tb.createblock(entities)     
      end
      
      #---
      if( not file_loaded?("testbed.rb") )
          add_separator_to_menu("Tools")    
          UI.menu("Tools").add_item($exStrings.GetString("Test Bed")) { testbed }
      end
      
      file_loaded("testbed.rb")
      
      

      Listing 2: VB Dll code (Compile with instancing = multiuse)

      
      Option Explicit
      
      Public Sub createblock(ents As Variant)
        Dim wt As Single
        Dim dp As Single
        Dim ht As Single
        
        Dim sVals As String
        Dim s() As String
       
        Dim rect As Variant
        Dim face As Variant
        Dim vstatus As Variant
        
        
        ' The following dippy dimension entry technique is just for the test.
        ' No error checking is supplied
        
        sVals = InputBox("Enter Width, Depth, Height", "Create Box", "")
        If sVals = "" Then GoTo CleanUp
        s = Split(sVals, ",")
        wt = CSng(Trim(s(0)))
        dp = CSng(Trim(s(1)))
        ht = -CSng(Trim(s(2)))
        
        rect = To_Rect(To_Pt(0, 0, 0), To_Pt(wt, 0, 0), To_Pt(wt, dp, 0), To_Pt(0, dp, 0))
        
        Set face = ents.add_face(rect)
        
        vstatus = face.pushpull(ht, False)
      
      CleanUp;
        Set vstatus = Nothing
        Set face = Nothing
        Set ents = Nothing
      End Sub
      
      Private Function To_Rect(ByVal pt1 As Variant, ByVal pt2 As Variant, ByVal pt3 As Variant, ByVal pt4) As Variant
        Dim v As Variant
        v = Array(pt1, pt2, pt3, pt4)
        To_Rect = v
      End Function
      
      Private Function To_Pt(ByVal x As Single, ByVal y As Single, ByVal z As Single) As Variant
        Dim v As Variant
        v = Array(x, y, z)
        To_Pt = v
      End Function
      
      

      Resistance is .... Character Forming. Grin

      1 Reply Last reply Reply Quote 0
      • G Offline
        Gruff
        last edited by

        SU to VB and Back. Part II

        a) Added a windows form to the dll. Not a big deal.
        b) Made the window a modal dialog. This is to stop the ruby code from falling through to the end of the script.
        c) Added a global module to pass the SU API objects and the dll host object into the form. The form may now process SU API objects directly and/or pass properties back to the host. (Where the ruby script can read them.)

        UI.messagebox( vbdll["propertyname"] )

        Utilizing this method we can have a VB form pop up on top of SU and disallow interaction with the SU environment while still driving the SU API from the form real time.

        No splats, crashes, or blue screens.

        Full power of Visual Basic 6.0 available to SU now.

        Resistance is .... Character Forming. Grin

        1 Reply Last reply Reply Quote 0
        • G Offline
          Gruff
          last edited by

          Proved out that VB.NET can talk to SU in the same manner provided you start with a (backwards compatible) COM Project.

          As I thought the generic object type may be substituted for the vb6 variant type.

          SU does not complain. πŸ˜„

          Attached is a simple VB.NET dll with a child form that builds a box through the SU API then returns a message to the SU script.

          Have fun!


          Zip containing testbed.rb and a VB.NET 2008 project

          Resistance is .... Character Forming. Grin

          1 Reply Last reply Reply Quote 0
          • G Offline
            Gruff
            last edited by

            Update:

            Found we can pass the main Sketchup object to the VB dll.
            (Had to create a variable to contain the Sketchup object first. Duh.)

            This opened up more possibilities. For instance you can load a Ruby script file from your VB program that does not existing in your plugin folder.

            
              Private Sub cmdRunRuby_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRunRuby.Click
                Dim status As Object
            
                With OpenFileDialog1
                  .InitialDirectory = "c;\"
                  .AddExtension = True
                  .DefaultExt = "rb"
                  .Filter = "Text files (*.rb)|*.rb"
                  .FileName = ""
                  .ShowDialog()
                  If .ShowDialog() = Windows.Forms.DialogResult.OK Then
                    status = g_oApp.load(.FileName.Replace("\", "\\"))
                    status = Nothing
                  End If
                End With
              End Sub
            
            

            Attached is a flow chart (Poorly made) that attempts to show the process used to drive SU from VB. Also attached is a snapshot of the vb.net testbed from the previous post running.

            Determined that the SketchUp API exposed to Windows is not the SketchUp API that is used internally by Ruby. This is somewhat disappointing as it means we cannot do SU API debugging nor do we have Intellisense for the SU objects.

            On the up side we have both of those features for data typed variable written in VB.


            Snapshot of the testbed app in the previous post


            Flow Chart

            Resistance is .... Character Forming. Grin

            1 Reply Last reply Reply Quote 0
            • T Offline
              theta_theta
              last edited by

              Gruff, thanks for posting. I'm trying to step through your VB.NET example using the files in testbed.zip but I get the following error when I start up StetchUp:

              "Error Loading File testbed.rb no such file to load win32ole"

              My guess is that the Ruby script in Sketchup cannot find the library win32ole.rb. I downloaded and installed Ruby 1.8 for windows (http://rubyinstaller.org/) because I suspect the win32ole.rb is somewhere in the Ruby installation. If I find win32ole.rb I will copy it to the Plugins folder (C:\Program Files\Google\Google SketchUp 8\Plugins)

              However I can't seem to find the required library. The most I can find is C:\Ruby187\lib\ruby\1.8\win32ole\property.rb.

              Do you know what files are required for the win32ole to work? Did you have any issues with this?

              1 Reply Last reply Reply Quote 0
              • Dan RathbunD Offline
                Dan Rathbun
                last edited by

                Dean ... you can get the win32ole.so file (it is a compiled "shared object" file, not a rb text script,) ...

                here: [Plugin Library] Win32API and Win32OLE so files

                And you normally do not just install any odd version of Ruby. SketchUp v8 uses 1.8.6-p287
                which you can get here: http://rubyforge.org/frs/download.php/47082/ruby186-27_rc2.exe

                I'm not here much anymore.

                1 Reply Last reply Reply Quote 0
                • M Offline
                  Marthmatica
                  last edited by

                  Just starting to connect VB to SkectchUp. As that is taking a little longer than I thought, I thought it mind be helpful for some to use Excel as the "go between" if you need to do something between VB or Acad and SkecthUp, as either of them can connect to Excel as easily as SkecthUp can.

                  So as an example I did a SkecthUp cafe creator, driven from Excel face point data per row.

                  Maybe someone will find this useful, or a better way to do it, or improve my Ruby, since I am just starting on the Ruby end.

                  
                  
                  #Reference standard API hooks.
                  require 'sketchup.rb'
                  require 'win32ole'
                  
                  
                  #Add a menu item to launch our plugin,
                  #in its SketchUp menu default name target,
                  #and the name we are giving our function in the "Tools" menu.
                  UI.menu("Tools").add_item("Get XLTiler") {
                    # UI.messagebox("Ye Excel! come up from hell!") 
                      get_xltiler
                  }
                  
                  
                  #define the function that is activated from that added menu item click
                  def get_xltiler
                  
                  #connect to an already open Excel application, use WIN320LE.new to start Excel
                  #.connect to connect to an already open Excel instance
                  application = WIN32OLE.connect('Excel.Application')
                  application.visible = TRUE
                  
                  #Instantiate tile matrix origin for Excel rows and columns reference
                  r = 0
                  c = 1
                  
                  #Set row and column count
                  #note cols is the face pts x1,y1,z1; x2,y2,z2... 1 through 4 xyz points; or 12 cols
                  #XL row 1= pt1; 1,	1,	0	pt2; 1,	2,	0	pt3; 2,	2,	0	pt4; 2,	1,	0
                  #XL row 2= pt1; 2,	1,	0	pt2; 2,	2,	0	pt3; 3,	2,	0	pt4; 3,	1,	0
                  #and so on...
                  
                  #Rows are face count to create
                  rows = 24
                  
                  #Columns have all 4 face points
                  cols = 12
                  
                  # rows is how many face tiles you are creating in SketchUp, 1 face tile, per each row
                  # Get handles to our model and the Entities collection it contains.
                  model = Sketchup.active_model
                  entities = model.entities
                  
                  
                  #THE MAIN FACE CREATING ROUTINE
                  #stepping through rows, as how many tiles you are creating is total rows,
                  #then stepping through cols to populate all 4 face pts per row
                  #step through all the XL rows
                  for step in 1..rows
                  r = r + 1
                  UI.messagebox(r)
                  c = 1
                  # and in every row populate the face pts from Excel cell values
                  for step in 1..cols
                  
                  pt1x = application.activesheet.cells(r,c).value
                  pt1y = application.activesheet.cells(r,c + 1).value
                  pt1z = application.activesheet.cells(r,c + 2).value
                  pt1 = pt1x, pt1y, pt1z
                  
                  pt2x = application.activesheet.cells(r,c + 3).value
                  pt2y = application.activesheet.cells(r,c + 4).value
                  pt2z = application.activesheet.cells(r,c + 5).value
                  pt2 = pt2x, pt2y, pt2z
                  
                  pt3x = application.activesheet.cells(r,c + 6).value
                  pt3y = application.activesheet.cells(r,c + 7).value
                  pt3z = application.activesheet.cells(r,c + 8).value
                  pt3 = pt3x, pt3y, pt3z
                  
                  pt4x = application.activesheet.cells(r,c + 9).value
                  pt4y = application.activesheet.cells(r,c + 10).value
                  pt4z = application.activesheet.cells(r,c + 11).value
                  pt4 = pt4x, pt4y, pt4z
                  #add new face per this row
                  new_face = entities.add_face pt1, pt2, pt3, pt4
                  end
                  #advance loop to next row
                  end
                  
                  end
                  
                  
                  
                  
                  1 Reply Last reply Reply Quote 0
                  • M Offline
                    Marthmatica
                    last edited by

                    Got an emergency to control SketchUp via a Visual Basic program for testing and design?

                    Open the SkecthUp console, give it focus manually.

                    Then just port some Ruby commands in, sending keys to the SU console title.

                    Private Sub Command5037_Click()
                    AppActivate ("Ruby Console")
                    Set WshShell = CreateObject("WScript.Shell")
                    WshShell.SendKeys "Testing" & vbCr 'etc, etc
                    End Sub

                    1 Reply Last reply Reply Quote 0
                    • Dan RathbunD Offline
                      Dan Rathbun
                      last edited by

                      @marthmatica said:

                      So as an example I did a SkecthUp cafe creator, driven from Excel face point data per row.

                      Maybe someone will find this useful, or a better way to do it, or improve my Ruby, since I am just starting on the Ruby end.

                      Ruby improved.

                      See new topic: [Code] Geometry Creation from Excel worksheet data

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • 1 / 1
                      • First post
                        Last post
                      Buy SketchPlus
                      Buy SUbD
                      Buy WrapR
                      Buy eBook
                      Buy Modelur
                      Buy Vertex Tools
                      Buy SketchCuisine
                      Buy FormFonts

                      Advertisement