• Login
sketchucation logo sketchucation
  • Login
πŸ”Œ Quick Selection | Try Didier Bur's reworked classic extension that supercharges selections in SketchUp Download

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.
  • D Offline
    dacastror
    last edited by 6 May 2015, 06:36

    Hello everyone, I have a question related to the coordinates of the corners of the viewport relative to the screen, my goal is to create a webdialog and place it in one of these corners. I'm not sure how to get these coordinates, in advance thank you very much for your attention.
    This picture illustrates what I want to get

    coords corner.png

    (I used google translator, sorry for errors)

    1 Reply Last reply Reply Quote 0
    • T Offline
      TIG Moderator
      last edited by 6 May 2015, 09:14

      Using 0,0 puts it at the top-left of the whole screen.
      You can't usefully get the viewing area's top-left corner.
      Docked toolbars at top and left will affect the actual viewable area...
      The screen resolution will also intervene !
      Just place it somewhere near the top-left and let the user relocate it as desired, its last location is remembered in the Registry across sessions [PC at least?]

      TIG

      1 Reply Last reply Reply Quote 0
      • D Offline
        driven
        last edited by 6 May 2015, 10:30

        if you 'really' want to and it's for v14/5 then you may be able to do something I do on a mac...

        for mac I use a bin tool, but there is a windows gem called 'auto-click', that has get/set mouse position methods.

        basic concept is from inside a tool you
        programmatically double-click at [vpwidth/2, vpheight/2] e.g. a = [600,400]
        retrieve the SU x,y with onLButtonDoubleClick(flags, x, y, view) e.g. b = [458,340]
        then offset = a-b i.e. top left corner of viewport...

        I've used it for automating 'user input' tests, mainly for the fun of it...
        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 6 May 2015, 16:59

          Hello dacastror.

          There is no SketchUp API function that will give you the upper left corner of the viewport area, relative to screen origin. However, one can use Windows API to get it, for the Windows OS only.

          FYI, I wrote a plugin, called SU windows settings, and it too creates a webdialog, hides all borders and places it in any corner user clips it to. You can see that plugin here: http://sketchucation.com/forums/viewtopic.php?t=42926

          When I get home, I'll provide some code snippet of getting screen coordinates to viewport origin.

          Anton

          1 Reply Last reply Reply Quote 0
          • D Offline
            dacastror
            last edited by 6 May 2015, 17:58

            thank you very much for your answers, I really want to do this, Driven interesting that behavior in Mac, I try to do something with it.
            Anton thank you very much, I was just beginning to explore your code is really awesome πŸ˜›, I can see that the coordinates of the viewport are obtained with this AMS::Sketchup::Viewport.rect returns an array like this [74, 120, 1678, 991] that corresponds to what I need πŸ˜›. Although I feel like killing a fly using an atomic bomb, it would be excessive to require the complete library, I'm trying to study their code to accomplish what I need through Win32API, but it is proving difficult. Nevertheless, I can contemplate the beauty and power of your code

            (google translator)

            1 Reply Last reply Reply Quote 0
            • D Offline
              driven
              last edited by 6 May 2015, 18:05

              what version of SU are you running?
              the gem I mentioned should work with Ruby 2 and can be installed in SU v14/v15 using

              Gem.install('auto_click')
              

              https://github.com/erinata/auto_click

              good luck
              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
              • D Offline
                dacastror
                last edited by 6 May 2015, 18:41

                Driven thanks, I'll look it looks interesting, I wonder if there will be a gem that allows some things like making Win32API so that they can perform on Mac

                Anton would perform similar to yours definitions, but using Win32API
                this is your original definition

                
                    def client_rect(hwnd, mode = 1)
                      return nil unless valid?(hwnd)
                      mode = mode.to_i
                      mode = 1 unless mode.between?(1,3)
                      lpRect = 0.chr*16
                      wins;;GetClientRect.call(hwnd, lpRect)
                      crect = lpRect.unpack('l*')
                      return crect if mode == 3
                      style = wins;;GetWindowLong.call(hwnd, -16)
                      exstyle = wins;;GetWindowLong.call(hwnd, -20)
                      wins;;AdjustWindowRectEx.call(lpRect, style, false, exstyle)
                      arect = lpRect.unpack('l*')
                      r = []
                      if mode == 1
                        wins;;GetWindowRect.call(hwnd, lpRect)
                        rect = lpRect.unpack('l*')
                        r[0] = rect[0] - arect[0]
                        r[1] = rect[1] - arect[1]
                        r[2] = r[0] + crect[2]
                        r[3] = r[1] + crect[3]
                      else
                        r[0] = -arect[0]
                        r[1] = -arect[1]
                        r[2] = r[0] + crect[2]
                        r[3] = r[1] + crect[3]
                      end
                      r
                    end
                
                

                and this is what I try to do, I do not know if it is correct

                require "Win32API"
                
                GetClientRect = Win32API.new( 'user32.dll','GetClientRect', 'LP', 'B')
                GetWindowLong = Win32API.new("user32.dll" , "GetWindowLong", "LI" , "L")
                AdjustWindowRectEx = Win32API.new('user32.dll','AdjustWindowRectEx', 'PLBL', 'B')
                GetWindowRect = Win32API.new('user32.dll','GetWindowRect', 'LP', 'B')
                
                def client_rect(hwnd, mode = 1)
                  mode = mode.to_i
                  mode = 1 unless mode.between?(1,3)
                  lpRect = 0.chr*16
                  GetClientRect.call(hwnd, lpRect)
                  crect = lpRect.unpack('l*')
                  return crect if mode == 3
                  style = GetWindowLong.call(hwnd, -16)
                  exstyle = GetWindowLong.call(hwnd, -20)
                  AdjustWindowRectEx.call(lpRect, style, exstyle)
                  arect = lpRect.unpack('l*')
                  r = []
                  if mode == 1
                    GetWindowRect.call(hwnd, lpRect)
                    rect = lpRect.unpack('l*')
                    r[0] = rect[0] - arect[0]
                    r[1] = rect[1] - arect[1]
                    r[2] = r[0] + crect[2]
                    r[3] = r[1] + crect[3]
                  else
                    r[0] = -arect[0]
                    r[1] = -arect[1]
                    r[2] = r[0] + crect[2]
                    r[3] = r[1] + crect[3]
                  end
                   r
                end
                

                at this time I do not know how to get "hwnd" for sketchup window

                (google translator)

                1 Reply Last reply Reply Quote 0
                • A Offline
                  Anton_S
                  last edited by 6 May 2015, 23:35

                  Decastor, there are several ways of getting SU window. My way, which is used in my C++ extension of AMS library, uses callbacks to iterate through all windows and find the one that matches SU window properties, like window class name and SU process id. Win32API doesn't support callbacks, so you'll need a simpler way of getting handle to SU window. A simple way of getting SU window is by calling GetActiveWindow when SU starts. It should that way, in most cases (probably in all), return handle to SU window. Then, you will also need a handle to the viewport child window. You're trying to acquire rectangle of viewport window after all. I will provide you a full proper working function in a day or so.

                  1 Reply Last reply Reply Quote 0
                  • D Offline
                    dacastror
                    last edited by 7 May 2015, 00:22

                    wow! thank you very much Anton, get this Handle seems more sophisticated than I expected

                    I'm anxious to see how to do πŸ˜„

                    1 Reply Last reply Reply Quote 0
                    • Dan RathbunD Offline
                      Dan Rathbun
                      last edited by 7 May 2015, 00:46

                      Just as a heads up, Win32API has been deprecated (for some time,) and in Ruby 1.9, was removed, and replaced with a "Win32API.rb" that is a wrapper making calls using the DL library.

                      So since then, you'd actually be using DL, when you made Win32API calls.

                      However DL has recently been deprecated, in favor of the Fiddle library.
                      In Ruby 2.0, there is a conditional loader that will attempt to wrap DL as calls into Fiddle.

                      Be warned that DL has already been removed from Ruby 2.2 !

                      Time to start learning Fiddle.

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • A Offline
                        Anton_S
                        last edited by 7 May 2015, 05:33

                        Well, in that deprecation purpose, I think the most convenient approach would be to write a c extension. But, meanwhile I will provide a Win32API reliant version, and then a C extension if decastror wishes.

                        1 Reply Last reply Reply Quote 0
                        • A Offline
                          Anton_S
                          last edited by 7 May 2015, 09:05

                          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 8 May 2015, 08:10

                            β˜€ 😍 🀒 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 8 May 2015, 08:20

                              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 8 May 2015, 18:13

                                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 8 May 2015, 19:21

                                  @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 8 May 2015, 20:06

                                    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 8 May 2015, 20:21

                                      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 8 May 2015, 20:31

                                        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 8 May 2015, 20:33

                                          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
                                          • 1
                                          • 2
                                          • 1 / 2
                                          1 / 2
                                          • First post
                                            5/31
                                            Last post
                                          Buy SketchPlus
                                          Buy SUbD
                                          Buy WrapR
                                          Buy eBook
                                          Buy Modelur
                                          Buy Vertex Tools
                                          Buy SketchCuisine
                                          Buy FormFonts

                                          Advertisement