[Code] Win32 - Get SketchUp Window Handle (WIP)

Re: [Code] Win32 - Get SketchUp Window Handle

Postby Dan Rathbun » Wed Dec 29, 2010 4:30 am

thomthom wrote:I think one can get lots of useful info if one can get the thread id of the SketchUp process. Any ideas of how one can do this.
How about?
Process.pid()
Thread.main.object_id
thomthom wrote:I've been scanning the Win32 API a bit today looking for relevant functions.

Well all the API functions for: Processes and Threads
0
    I'm not here much anymore. But a PM will fire email notifications.
    User avatar
    Dan Rathbun 
    PluginStore Author
    PluginStore Author
     

    Re: [Code] Win32 - Get SketchUp Window Handle

    Postby thomthom » Wed Dec 29, 2010 12:46 pm

    Ah - there we go, that might help.
    GetCurrentProcessId looks promising.
    0
    Thomas Thomassen — SketchUp Monkey & Coding addict
    List of my plugins and link to the CookieWare fund
    User avatar
    thomthom 
    PluginStore Author
    PluginStore Author
     

    Re: [Code] Win32 - Get SketchUp Window Handle

    Postby thomthom » Wed Dec 29, 2010 12:49 pm

    pid = GetCurrentProcessId.call
    4684
    Process.pid()
    4684

    It seem to return the same thing.
    0
    Thomas Thomassen — SketchUp Monkey & Coding addict
    List of my plugins and link to the CookieWare fund
    User avatar
    thomthom 
    PluginStore Author
    PluginStore Author
     

    Re: [Code] Win32 - Get SketchUp Window Handle

    Postby Dan Rathbun » Wed Dec 29, 2010 2:14 pm

    thomthom wrote:pid = GetCurrentProcessId.call
    4684
    Process.pid()
    4684

    It seem to return the same thing.

    Yes and it's the same as you'll see in the Task Manager, or using tlist.exe from the command line (for that Sketchup instance.)
    0
      I'm not here much anymore. But a PM will fire email notifications.
      User avatar
      Dan Rathbun 
      PluginStore Author
      PluginStore Author
       

      Re: [Code] Win32 - Get SketchUp Window Handle

      Postby Dan Rathbun » Wed Dec 29, 2010 2:34 pm

      Dan Rathbun wrote: It looks as though the DL library supports callbacks. Maybe we should use it ??

      My bad.. :oops:
      Callbacks were added in 1.9.x, both 1.8.6 and 1.8.7 DL libs don't have the callback.rb file.

      sorry Thom
      0
        I'm not here much anymore. But a PM will fire email notifications.
        User avatar
        Dan Rathbun 
        PluginStore Author
        PluginStore Author
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby thomthom » Wed Dec 29, 2010 2:56 pm

        GetCurrentThreadId I think this one is what we can use to get associated window handles. Just need to get callbacks working so we can use EnumThreadWindows to get the windows for the calling thread.
        0
        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund
        User avatar
        thomthom 
        PluginStore Author
        PluginStore Author
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby thomthom » Wed Dec 29, 2010 3:45 pm

        Jim wrote:
        thomthom wrote:Where is the win32-api found - the one that supports callbacks?

        http://win32utils.rubyforge.org/

        I'm not sure if this can co-exist with Win32API or not.

        require 'win32/api'
        win32.zip


        I just tried it, works fine with Win32API.

        Here's a bastardised proof of concept snippet where I found the SketchUp window regardless if it had focus or not.

        Code: Select all
        # http://stackoverflow.com/questions/3327666/win32s-findwindow-can-find-a-particular-window-with-the-exact-title-but-what
        EnumWindows       = Win32::API.new('EnumWindows', 'KP', 'L', 'user32')
        EnumThreadWindows = Win32::API.new('EnumThreadWindows', 'LKP', 'I', 'user32')
        GetCurrentThreadId = Win32API.new("kernel32.dll", "GetCurrentThreadId", '', 'L')

        # Detect the toolwindows even if Hide Dialogs is active.
        def enum_sketchup_windows
          threadId = GetCurrentThreadId.call
          enumWindowsProc = Win32::API::Callback.new('LP', 'I'){ |handle, param|
            #puts "EnumWindows - Callback"
            #puts "> handle: #{handle}"
            #puts "> param: #{param.inspect}"
            window_text = get_window_text(handle)
            window_text.strip! # Remove trailing NULL character
            p window_text unless window_text.empty?
            if !window_text.index(param).nil?
              puts "window was found: handle #{handle}"
              0 # FALSE - stop looking after we find it
              1 # TRUE
            else
              1 # TRUE
            end
          }
          EnumThreadWindows.call(threadId, enumWindowsProc, 'SketchUp')
        end

        # Takes the first enumerated window for the calling SketchUp thread and fetches
        # the root owner which should be the SketchUp window. (Not tested against wxSU)
        #
        # Is the enum required to get just one window? Any other function to get an
        # arbitrary window from the SketchUp thread?
        def find_sketchup_window
          threadId = GetCurrentThreadId.call
          hwnd = 0
          enumWindowsProc = Win32::API::Callback.new('LP', 'I'){ |handle, param|
            hwnd = GetAncestor.call(handle, GA_ROOTOWNER)
            0
          }
          EnumThreadWindows.call(threadId, enumWindowsProc, 'SketchUp')
          hwnd
        end


        Remaining issues:
        • Migrate Win32API to Win32::API for all function calls.
        • While testing I eventually got an exception that said there was too many callbacks initiated. Seems there might be a limit. I have not looked into this further, but I think once might have to make one callback proc, and then delegate to the appropriate handling method based on param.
        0
        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund
        User avatar
        thomthom 
        PluginStore Author
        PluginStore Author
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby thomthom » Wed Dec 29, 2010 3:56 pm

        = Documentation
        The source file contains inline RDoc documentation. If you installed
        this file as a gem, then you have the docs.

        Where do you get the source code?

        I tried to install the gem, but got this error:
        gemInstallError.png
        0
        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund
        User avatar
        thomthom 
        PluginStore Author
        PluginStore Author
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby Jim » Wed Dec 29, 2010 4:18 pm

        It is a c-language based extension, and apparently isn't available already compiled for your platform. So you would need to compile it.

        This is the advantage of using the mingw32 Ruby Installer with devkit - it automatically builds native libraries.

        http://rubyinstaller.org/downloads/
        0
        Hi

        Jim 
        Global Moderator
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby thomthom » Wed Dec 29, 2010 4:33 pm

        But where is the source code - since it's suppose to contain the documentation?
        0
        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund
        User avatar
        thomthom 
        PluginStore Author
        PluginStore Author
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby Jim » Wed Dec 29, 2010 4:36 pm

        For me, it is here:

        C:\Ruby186\lib\ruby\gems\1.8\gems\win32-api-1.4.7-x86-mingw32\ext\win32
        0
        Hi

        Jim 
        Global Moderator
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby thomthom » Wed Dec 29, 2010 5:05 pm

        hm... guess I have to look into that ming-thing...


        Anyway - I have produced a code which appear to return the handle for the SketchUp window of the calling thread. I created a EnumWindowsProc to delegate enumeration messages in order to avoid Error: #<Win32::API::Error: too many callbacks are defined.>. I really want to know what this limit is. This is the first draft, I expect there is a better way to deal with this.

        But, we do get a reliable window for the SketchUp window we want - as far as I have been able to test.
        0
        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund
        User avatar
        thomthom 
        PluginStore Author
        PluginStore Author
         

        Re: [Code] Win32 - Get SketchUp Window Handle

        Postby thomthom » Wed Dec 29, 2010 5:08 pm

        Maybe we can handle drag and drop by callbacks. Or intercept window messages so we can simulate the roll-up/down of toolwindows.

        Still, OSX users are out of luck here...
        0
        Thomas Thomassen — SketchUp Monkey & Coding addict
        List of my plugins and link to the CookieWare fund
        User avatar
        thomthom 
        PluginStore Author
        PluginStore Author
         

        Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

        Postby Dan Rathbun » Thu Dec 30, 2010 3:41 am

        Here's some interesting info:

        Code: Select all
        #
        #  some Sketchup window properties:
        #
        #  AutomationId  =  ""
        #
        #  CLASS   =  "Afx:00400000:b:00010011:00000006:00790557"
        #  *** the last octet changes each time Sketchup is run,
        #  examples:  "Afx:00400000:b:00010011:00000006:0012077F"
        #             "Afx:00400000:b:00010011:00000006:000E0699"
        #
        #  ControlType           =  "ControlType.Window"
        #  LocalizedControlType  =  "window"
        #

        The main application window is the only one with a classname like this, and also the only one with a LocalizedControlType that equals "window".

        ALL dialogs including WebDialogs, are:
        Code: Select all
        #
        #  ClassName             =  "#32770"
        #  ControlType           =  "ControlType.Window"
        #  LocalizedControlType  =  "Dialog"
        #
        0
          I'm not here much anymore. But a PM will fire email notifications.
          User avatar
          Dan Rathbun 
          PluginStore Author
          PluginStore Author
           

          Re: [Code] Win32 - Get SketchUp Window Handle

          Postby Dan Rathbun » Thu Dec 30, 2010 4:14 am

          thomthom wrote:I have produced a code which appear to return the handle for the SketchUp window of the calling thread.

          Are you planning on distibuting a pre-compiled win-api as part of TT_Lib2 ??

          I have a few issues with this.
          (1) It's not in the correct folder. What if a person already has it (and possibly a newer version,) installed ?

          require will not recognize the path string you have in that example, and would load the older version down under your TT_Lib2 folder. That would overwrite the newer classes that might be loaded, if they were loaded first.

          OR.. since "T" comes before "W" your version would get loaded first, and when a normal version gets loaded after... your code might get broken. (I say "might" as newer versions are usually better.)

          So? I like the idea of someone precompiling Berger's WinUtils, and zipping them for manual install by the community (and/or creating a one-click-installer for dummies.) But they should be in the proper folder ... and likely a path to them appended to the $LOAD_PATH array.

          How much of Berger's suite would the distro have? the bare bones min or the whole thing?
          0
            I'm not here much anymore. But a PM will fire email notifications.
            User avatar
            Dan Rathbun 
            PluginStore Author
            PluginStore Author
             

            Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

            Postby thomthom » Thu Dec 30, 2010 11:18 am

            Dan Rathbun wrote:Here's some interesting info:

            I get Afx:00A50000:b:00010005:00000006:0A7C0E3B during one session,
            and the next I get Afx:00ED0000:b:00010005:00000006:5CCC0D4F - seems to be more than just the last bit that changes...

            SU8 - Win7...

            I don't understand where that name is from - other apps, like Notepad++ has a fixed classname.
            0
            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund
            User avatar
            thomthom 
            PluginStore Author
            PluginStore Author
             

            Re: [Code] Win32 - Get SketchUp Window Handle

            Postby thomthom » Thu Dec 30, 2010 11:28 am

            Dan Rathbun wrote:Are you planning on distibuting a pre-compiled win-api as part of TT_Lib2 ??

            I'm looking into it. If license allows it.

            Dan Rathbun wrote:(1) It's not in the correct folder. What if a person already has it (and possibly a newer version,) installed ?

            That is a thing that was on my to-look-into list. What if I placed it into a folder, say: TT_Lib2/win32api/win32/api.so - and then added the TT_Lib2/win32api/ path to $LOAD_PATH so one load it as the examples says require 'win32/api'?

            Dan Rathbun wrote:OR.. since "T" comes before "W" your version would get loaded first, and when a normal version gets loaded after... your code might get broken. (I say "might" as newer versions are usually better.)

            We have that potential issue with Win32API already, though it often lies in the root of the plugins folder, you can't be sure what version was copied into there last.

            Dan Rathbun wrote:How much of Berger's suite would the distro have? the bare bones min or the whole thing?

            Atm I only have use of api.so - but there was some interesting stuff he had.
            0
            Thomas Thomassen — SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund
            User avatar
            thomthom 
            PluginStore Author
            PluginStore Author
             

            Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

            Postby Dan Rathbun » Thu Dec 30, 2010 1:33 pm

            thomthom wrote:
            Dan Rathbun wrote:Here's some interesting info:

            I get Afx:00A50000:b:00010005:00000006:0A7C0E3B during one session,
            and the next I get Afx:00ED0000:b:00010005:00000006:5CCC0D4F - seems to be more than just the last bit that changes...

            SU8 - Win7...

            I don't understand where that name is from - other apps, like Notepad++ has a fixed classname.


            Wikipedia on Microsoft Foundation Class Library wrote:One interesting quirk of MFC is the use of "Afx" as the prefix for many functions, macros and the standard precompiled header name "stdafx.h". During early development what became MFC was called "Application Framework Extensions" and abbreviated "Afx". The name Microsoft Foundation Classes (MFC) was adopted too late in the release cycle to change these references.


            A guy on Experts Exchange wrote:Just few words about AFX:XXXXX:XXX like windows..... Dont confuse with this type of class names, these are just class names and actually MFC generates class names for its windows this way. Some of those numbers are an HINSTANCE and a process ID (to make sure the class name is unique). I'm not sure what the others are - if you really want to know, you can probably find it in 'MFC source code. -MAHESH


            In the AutoHotKey Forum post 633, Chris, in his reply, wrote:Below are quotes from the only relevant link discovered on Google at:
            http://visualbasicforum.com/showthread.php?t=149804 (dead link) wrote:Those Afx window classes were custom classes distributed with early versions of MFC, before the "Common Controls" concept was introduced.

            Many people have tried to "read" text from them but you CAN'T, not with messages anyway!

            They're almost certainly owner-drawn - the text is not delivered by messages, it's "hand-drawn" into the window's DC

            ...


            Apparently legacy from the early days ... there are many things I see (about Sketchup UI objects,) poking about with MS Tools that don't look quite right.
            0
              I'm not here much anymore. But a PM will fire email notifications.
              User avatar
              Dan Rathbun 
              PluginStore Author
              PluginStore Author
               

              Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

              Postby thomthom » Thu Dec 30, 2010 1:45 pm

              So, many of what looks like system UI elemens is not drawn by the system - but emulated by the AFX/MFC framework?
              0
              Thomas Thomassen — SketchUp Monkey & Coding addict
              List of my plugins and link to the CookieWare fund
              User avatar
              thomthom 
              PluginStore Author
              PluginStore Author
               

              Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

              Postby Dan Rathbun » Thu Dec 30, 2010 1:51 pm

              There are several GUI frameworks a coder can choose to use ... WTL sounds very interesting.

              http://en.wikipedia.org/wiki/Windows_Template_Library
              0
                I'm not here much anymore. But a PM will fire email notifications.
                User avatar
                Dan Rathbun 
                PluginStore Author
                PluginStore Author
                 

                Re: [Code] Win32 - Get SketchUp Window Handle

                Postby Dan Rathbun » Tue Jan 04, 2011 10:41 am

                Dan Rathbun wrote: I've also read that the DL library is 'on the outs', and they are planning to deprecate it and replace it with something else.

                OK.. now I remember what the next generation (after DL,) was supposed to move to, (the Foriegn Function Interface):
                Wikipedia: libffi
                and the github site for Ruby FFI is:
                https://github.com/ffi/ffi

                It is not yet included with Ruby as of v1.9.1-p429
                0
                  I'm not here much anymore. But a PM will fire email notifications.
                  User avatar
                  Dan Rathbun 
                  PluginStore Author
                  PluginStore Author
                   

                  Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

                  Postby Anton_S » Fri Jun 22, 2012 8:13 pm

                  Here is my way to find sketchup window.
                  I used it in SU Window Settings plugin.

                  Parts of ClassName change After restarting SU
                  ~sample: "Afx:00400000:b:00010011:00000006:0574025D"
                  From my testing:
                  • On windows XP, the last set of values, separated by ":" change.
                    Afx:00400000:b:00010011:00000006:0574025D
                  • On windows 7, all even parts, separated by ":" change. The odd parts are always the same, including on both 32 and 64 -bit processors.
                    Afx:00400000:b:00010011:00000006:0574025D

                  So, the only parts of class that are reliable to locate main SU window are, Afx, b and 00000006. Plus to get the current sketchup window, you could add the Process.pid. The code below does all of that work :)

                  Code: Select all
                  @main_window = Hash.new
                  @find_main_window = Win32::API::Callback.new('IP', 'I'){|hwnd, lParam|
                    p = 0.chr*4
                    threadID = GetWindowThreadProcessId.call(hwnd, p)
                    pid = p.unpack('l')[0]
                    next true if (pid != Process.pid)
                    cname = 0.chr*50
                    GetClassName.call(hwnd, cname, cname.size)
                    cname = cname.strip
                    if (cname[0,3] == "Afx") and (cname[13,1] == "b") and (cname[24,8] == "00000006")
                      @threadID = threadID
                      @main_window["hwnd"] = hwnd
                      next false
                    end
                    true
                  }
                  EnumWindows.call(@find_main_window, nil)


                  Note, this example was only tested on Windows XP and On Win7.

                  What vous think?
                  0

                  Anton_S 
                  PluginStore Author
                  PluginStore Author
                   

                  Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

                  Postby Dan Rathbun » Fri Jun 22, 2012 10:49 pm

                  You neglect to show the require() staement that loads Dan Berger's win32-api extensions. (This example does not use the Win32API.so file, that comes "out-of-the-box" with Ruby.)
                  0
                    I'm not here much anymore. But a PM will fire email notifications.
                    User avatar
                    Dan Rathbun 
                    PluginStore Author
                    PluginStore Author
                     

                    Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

                    Postby Dan Rathbun » Fri Jun 22, 2012 10:54 pm

                    I find it much simplier.. to use a KNOWN child window (sometimes I use the Console window, sometimes I create a hidden child window with a caption that is unique, like perhaps I insert a time-stamp and the current Sketchup pid, returned with $$, into my child window caption.)

                    Then find the handle to that unique window, and get it's owner.
                    0
                      I'm not here much anymore. But a PM will fire email notifications.
                      User avatar
                      Dan Rathbun 
                      PluginStore Author
                      PluginStore Author
                       

                      Re: [Code] Win32 - Get SketchUp Window Handle (WIP)

                      Postby Anton_S » Sat Jun 23, 2012 1:54 am

                      Dan Rathbun wrote:You neglect to show the require() staement that loads Dan Berger's win32-api extensions. (This example does not use the Win32API.so file, that comes "out-of-the-box" with Ruby.)


                      Thanks for pointing that out. Yep, the code above requires win32-api
                      0

                      Anton_S 
                      PluginStore Author
                      PluginStore Author
                       

                      SketchUcation One-Liner Adverts

                      by Ad Machine » 5 minutes ago



                      Ad Machine 
                      Robot
                       

                      Next


                       

                      Return to Developers' Forum

                      Who is online

                      Users browsing this forum: Bing [Bot] and 12 guests

                      Visit our sponsors: