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

    Get the coordinates of the corners of the viewport

    Scheduled Pinned Locked Moved Developers' Forum
    31 Posts 6 Posters 2.3k Views 6 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.
    • A Offline
      Anton_S
      last edited by

      Here it is decastror!

      
      # Load Win32API
      dir = File.dirname(__FILE__)
      if RUBY_VERSION =~ /2.0/
        # Standard libraries included in SU 2014+.
        require 'Win32API'
      else
        # Bundled with plugin for SU 2013 and prior.
        require File.join(dir, 'Win32API')
      end
      
      # Top level namespace just for convinience.
      module Decastror; end
      
      # Sub namespace for particular plugin.
      # It can also go directly into your top level namespace.
      module Decastror;;MyTool
      
        # Import some Windows API functions
        GetActiveWindow       = Win32API.new('User32', 'GetActiveWindow', '', 'L')
        GetWindow             = Win32API.new('User32', 'GetWindow', 'LL', 'L')
        GetWindowRect         = Win32API.new('User32', 'GetWindowRect', 'LP', 'I')
        GetClientRect         = Win32API.new('User32', 'GetClientRect', 'LP', 'I')
        FindWindowEx          = Win32API.new('User32', 'FindWindowEx', 'LLPP', 'L')
        GetWindowLong         = Win32API.new('User32', 'GetWindowLong', 'LI', 'L')
        AdjustWindowRectEx    = Win32API.new('User32', 'AdjustWindowRectEx', 'PLIL', 'I')
      
        # This simple technique works in most cases if not all.
        active = GetActiveWindow.call()
        owner = GetWindow.call(active, 4)
        MAIN_HWND = owner == 0 ? active ; owner
      
        class << self
      
          # Get handle to viewport window.
          # The reason we need this function, rather than constant is because viewport
          # handle is not constant. Viewport handle changes as view preferences
          # change.
          # @return [Fixnum]
          def get_viewport_handle
            # View class name is different among different SU versions.
            # SU6 uses AfxFrameOrView70u
            # SU7 and SU8 use AfxFrameOrView80u
            # SU2013 through SU2015 use AfxFrameOrView100u
            cname = case Sketchup.version.to_i
              when 6
                'AfxFrameOrView70u'
              when 7,8
                'AfxFrameOrView80u'
              else
                'AfxFrameOrView100u'
            end
            return FindWindowEx.call(MAIN_HWND, 0, cname, nil)
          end
      
          # Get screen coordinates to the upper-left and lower-right corners of the
          # viewport window.
          # @return [Array<Fixnum>] [x1,y1, x2,y2]
          def get_viewport_rect
            viewport = get_viewport_handle()
      
            style = GetWindowLong.call(viewport, -16)
            ex_style = GetWindowLong.call(viewport, -20)
      
            wrect = [0,0,0,0].pack('l*')
            crect = [0,0,0,0].pack('l*')
            arect = [0,0,0,0].pack('l*')
      
            GetWindowRect.call(viewport, wrect)
            GetClientRect.call(viewport, crect)
            GetClientRect.call(viewport, arect)
            AdjustWindowRectEx.call(arect, style, 0, ex_style)
      
            wrect = wrect.unpack('l*')
            crect = crect.unpack('l*')
            arect = arect.unpack('l*')
      
            return [
              wrect[0] - arect[0],
              wrect[1] - arect[1],
              wrect[0] - arect[0] + crect[2],
              wrect[1] - arect[1] + crect[3]
            ]
          end
      
        end # proxy class
      end # module Decastror;;MyTool
      
      unless file_loaded?(__FILE__)
        # This field is added just in case file is loaded more than once.
        # Add some menus and stuff that should be instantiated only once.
      
        file_loaded(__FILE__)
      end
      
      

      To get viewport rect:
      r = Decastror::MyTool.get_viewport_rect
      And this will give you viewport origin:
      origin = [r[0], r[1]]
      This will get viewport size:
      size = [r[2]-r[0], r[3]-r[1]]

      I created a sample tool. You can customize it to your taste and work your extension from there.


      decastror_tool.zip

      1 Reply Last reply Reply Quote 0
      • D Offline
        dacastror
        last edited by

        ☀ 😍 🤢 It works perfectly, Anton am very grateful that you've taken the time to write this, it's very good.
        I'm studying your code to see how does its magic, I have a question about owner = GetWindow.call (active, 4) I do not quite know who does this
        Other than that, I only see a bug in the code, you wrote D ecastror instead of Dacastror
        😆 I'm kidding of course.

        @unknownuser said:

        meanwhile I will provide a Win32API reliant version, and then a C extension if decastror wishes

        Build my first extension in C would be wonderful, it would be a good opportunity to dust off my little knowledge of C and most interestingly, could look to the development of faster plugins,
        once, I tried perform the "hello world" with a guide published on GitHub, but I got lost on the way, I do not remember why, I would very much accomplish, Anton that would be awesome.

        thank you very much for the advice Dan. I'll read about that library.

        (translated with google translator)

        1 Reply Last reply Reply Quote 0
        • D Offline
          dacastror
          last edited by

          I'm realizing I have to create a kind of observer of the size and position of the viewport, so that my webdialog is maintained in the corner when the user changes the size or position of the window Sketchup, for now the only option I see is do something with UI.start_timer and UI.stop_timer

          1 Reply Last reply Reply Quote 0
          • D Offline
            driven
            last edited by

            simple question,...
            what do you want to 'put' in the webdialog?
            adding observers has a cost to performance and can be very hard to debug when they go wrong...

            just curious...
            john

            learn from the mistakes of others, you may not live long enough to make them all yourself...

            1 Reply Last reply Reply Quote 0
            • A Offline
              Anton_S
              last edited by

              @dacastror said:

              I have a question about owner = GetWindow.call (active, 4) I do not quite know who does this

              The code has two parts to it:
              active = GetActiveWindow.call() owner = GetWindow.call(active, 4) MAIN_HWND = owner == 0 ? active : owner
              When SU starts, we get active window. The active window could return a handle to SU window or a handle to a webdialog belonging to SU window. To make sure that we get SU window, and not a webdialog, we use the GetWindow with a GW_OWNER command.

              @dacastror said:

              I'm realizing I have to create a kind of observer of the size and position of the viewport, so that my webdialog is maintained in the corner when the user changes the size or position of the window Sketchup, for now the only option I see is do something with UI.start_timer and UI.stop_timer

              Yes, a timer would be an easy way to go. However, my AMS Library, has such observers (EDIT: But, they don't rely on timer. They rely on actual messages coming from SU window procedure). You can see documentation here, in case you are interested: AMS::SketchupObserver.#swo_on_size_move

              1 Reply Last reply Reply Quote 0
              • D Offline
                dacastror
                last edited by

                Anton thank you very much for your explanation and links.

                you have many observers available it is awesome, I have two versions of your library,1.0.9 and 2.2.0, I'm trying to understand how you manage to observe changes in the windows but I can not understand how you do, What is the basis of your observers? Is it a timer that question every so often? or does it work differently? Anton sorry for asking so much, It is that I am interested in the mechanisms behind the clock.

                I want to keep as a surprise, when I finish you will understand why I needed this, however I will seriously consider your points.

                1 Reply Last reply Reply Quote 0
                • D Offline
                  dacastror
                  last edited by

                  I want to keep as a surprise, When I finish you will understand why I needed this, however I will seriously Consider Your points.

                  it seems that is no longer available the info in this link

                  @unknownuser said:

                  We're sorry, the page you requested cannot be found.

                  you could give me another clue to study this?

                  1 Reply Last reply Reply Quote 0
                  • A Offline
                    Anton_S
                    last edited by

                    Here is window procedure I'm using to monitor window events: [Window Procedure](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v)
                    Here is more info about window procedures and how to use them: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632593(v=vs.85).aspx

                    1 Reply Last reply Reply Quote 0
                    • A Offline
                      Anton_S
                      last edited by

                      My observers work by intersecting into SU window procedure and monitoring its messages. That is, too, possible with Windows API. No timers are needed. I have it all integrated in my C++ extension of AMS Library. You can read here about window procedure: https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx

                      1 Reply Last reply Reply Quote 0
                      • D Offline
                        dacastror
                        last edited by

                        Anton thank you very much, I'll get to study this 🤓

                        1 Reply Last reply Reply Quote 0
                        • A Offline
                          Anton_S
                          last edited by

                          Your welcome, dacastror. Window Procedure is a callback function. Win32API has no feature to create callbacks. You could use Ruby Fiddle (available as standard lib in SU2014+) or Win32-API (A more advanced win32 API by Daniel J Berger), but they could endup very performance consuming if you try to monitor SU WindowProc through Ruby. You might want to consider writing a C/C++ extension.

                          Hey, I will make a little C++ extension for you as you mentioned your not very familiar with C and how to use it in SU. All you'll need is Visual Studio (VS2010 preferred).

                          1 Reply Last reply Reply Quote 0
                          • D Offline
                            dacastror
                            last edited by

                            Anton you're great, I will be attentive to what you show me to make a extension.

                            1 Reply Last reply Reply Quote 0
                            • A Offline
                              Anton_S
                              last edited by

                              Okay, I finished it!

                              Extract dacastror.zip into your plugins folder, run SU, and see what happens.

                              This dacastror extension works under Ruby version 1.8.6 and up, which means it will work in SU8 and up. To make it work in SU6 and SU7, you'll need to update SU Ruby interpreter. Do that by copying msvcrt-ruby18.dll from SU8 or SU2013 path and pasting it in SU6/7 path (overwriting outdated ruby interpreter). Something else can be done with the C++ extension itself, to make it work under SU6/7, but I don't find it necessary as old SU versions are "deprecated" anyway.

                              The C++ extension works with visual studio (2010 preferred). I omitted several unused mac libraries and removed Swig, from original Github download, and just left the necessary parts. This reduced size significantly. Do the following to compile and use your c++ extension:

                              1. Extract SketchUp Ruby C++ Extensions.zip
                              2. Run SketchUp Ruby C++ Extensions/SketchUp Ruby C++ Extensions.sln
                              3. Select Solution Configurations box to preferred Ruby version, Release (2.0) is there by default.
                              4. Select Solution Platforms box to preferred platform, x64 is there by default.
                              5. Open Solution Explorer, right-click on dacastror project, and select Build.
                              6. Navigate to SketchUp Ruby C++ Extensions/Release x.y/... and get your .so library from there.
                              7. For you plugin, you will need 3 builds: Release 1.8 Win32, Release 2.0 Win32, and Release 2.0 x64.
                              8. Copy/Move dacastror.so to it desired folder in Plugins/dacastror/win[32/64]/[1.8/2.0]/

                              Your dacastror plugin already has all compiled so libraries. I added this as a guide so you could use it whenever you want to modify your C++ extension.

                              Oh and by the way, your dacastror.so contains the following functions:
                              `

                              • Dacastror::Windows.get_main_handle
                              • Dacastror::Windows.get_viewport_handle
                              • Dacastror::Windows.get_viewport_rect
                              • Dacastror::Windows.add_observer(object)
                              • Dacastror::Windows.remove_observer(object)`
                                See Plugins/dacastror/main.rb for more info.
                                You can also generate documentation of your C++ extension. Read more about it in SketchUp Ruby C++ Extensions/Dacastror/src/How To Generate Doc.txt

                              Dacastror sample plugin. Place in plugins folder.


                              Dacastror C++ extension. You'll need visual studio to use it.

                              1 Reply Last reply Reply Quote 0
                              • D Offline
                                dacastror
                                last edited by

                                ☀ 😍 Anton thank you very much, this is great, Christmas had never come so early for me, I am very happy. I am examining every part of this and I'm downloading "visual studio 2010," I'm trying to absorb all this.

                                1 Reply Last reply Reply Quote 0
                                • D Offline
                                  dacastror
                                  last edited by

                                  I just installed extesion and open sketchup, works great !!
                                  these observers are perfectly suited to my need 😄

                                  1 Reply Last reply Reply Quote 0
                                  • A Offline
                                    Anton_S
                                    last edited by

                                    Gurait! That c++ extension you have is my latest masterpiece. I'm pretty sure I'll have to improve my old AMS Library 😄.

                                    1 Reply Last reply Reply Quote 0
                                    • D Offline
                                      dacastror
                                      last edited by

                                      where you learn to do these wonderful things?

                                      1 Reply Last reply Reply Quote 0
                                      • A Offline
                                        Anton_S
                                        last edited by

                                        By examining other extensions and stuff I learned how to use C++. Now, I take CS162 at college and C++ becomes an easy language to use. My knowledge of Windows API is all from my long experience using it. It took some effort developing useful methods and optimizing them over time. It was all worth it though 😎.

                                        1 Reply Last reply Reply Quote 0
                                        • tt_suT Offline
                                          tt_su
                                          last edited by

                                          @anton_s said:

                                          By examining other extensions and stuff I learned how to use C++. Now, I take CS162 at college and C++ becomes an easy language to use. My knowledge of Windows API is all from my long experience using it. It took some effort developing useful methods and optimizing them over time. It was all worth it though 😎.

                                          C++11 yum yum!

                                          1 Reply Last reply Reply Quote 0
                                          • A Offline
                                            Anton_S
                                            last edited by

                                            I'm not sure if I used any C++ 11 syntax in that C++ extension, but Ruby C++ extensions as a whole give so much opportunities to writing great plugins in SU. I'm amazed that SU team chose Ruby over all available programming languages. Back then, when SU was first released, Ruby wasn't even popular, but SU team bypassed popularity and chose Ruby because Ruby was both simple and powerful due to a feature in supporting C extensions. Today, Ruby is becoming popular and is improving in performance and in features. Something tells me that SU had and still has really great minds behind it because choosing Ruby was the best path SU team could ever take. Imagine if they chose python or any other high level, limited programming language. SU would have been a totally different story from what it is today. Huge thanks goes to SU team for making SU a very great software for writing powerful plugins.

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

                                            Advertisement