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

    Need help with structures in callbacks

    Scheduled Pinned Locked Moved Developers' Forum
    8 Posts 3 Posters 4.9k Views 3 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

      Can win32 api callback function return structures?
      In my script it only return's pointer to the structure, but not the whole structure.
      Script:

      require "Sketchup.rb"
      require "win32/api.rb" #version 1.4.8 for ruby 1.8.x or 1.9.x
      include Win32
      
      SetWindowsHookEx=API.new('SetWindowsHookEx', 'IKII', 'I', 'User32') #http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx
      UnhookWindowsHookEx=API.new('UnhookWindowsHookEx', 'I', 'I', 'User32') #http://msdn.microsoft.com/en-us/library/ms644993(v=VS.85).aspx
      GetCurrentThreadId=API.new('GetCurrentThreadId', 'V', 'I', 'Kernel32') #http://msdn.microsoft.com/en-us/library/ms683183(VS.85).aspx
      GetModuleHandle=API.new('GetModuleHandle', 'V', 'I', 'Kernel32') #http://msdn.microsoft.com/en-us/library/ms683199(v=VS.85).aspx
      
      $inputText=[nil, [], 0]
      
      def logLine(str, lines=40)
       $inputText[0]=Sketchup.active_model.add_note("Sketchup Hook Procedure", 0.01, 0.2) if ($inputText[0]==nil or $inputText[0].deleted?)
       $inputText[1].push(str)
       $inputText[1][0,($inputText[1].length-lines)]=nil if $inputText[1].length>lines
       $inputText[0].text=$inputText[1].join("\n")
      end
      
      class LowLevelMouseHookProc
       @@hhk=nil
       @@lowLevelMouseProc=API;;Callback.new("ILP", 'I'){|nCode, wParam, p| #http://msdn.microsoft.com/en-us/library/ms644986(v=VS.85).aspx
        param=[p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]]
        #MSLLHOOKSTRUCT; http://msdn.microsoft.com/en-us/library/ms644970(v=VS.85).aspx
        x=p[0].to_i + (p[1].to_i<<8) + (p[2].to_i<<16) + (p[3].to_i<<24)
        y=p[4].to_i + (p[5].to_i<<8) + (p[6].to_i<<16) + (p[7].to_i<<24)
        mouseData=p[8].to_i + (p[9].to_i<<8) + (p[10].to_i<<16) + (p[11].to_i<<24)
        $inputText[2]+=1
        logLine("#{$inputText[2]} code; #{nCode} wParam; #{wParam} lParam; #{param.inspect} x; #{x} y; #{y} mouseData; #{mouseData}")
        nCode #proccess the message as it states to proccess
       }
       def setHook(hMod=0, threadID=0)
        UnhookWindowsHookEx.call(@@hhk) if @@hhk #First, if exists then unhook the hook before setting it again.
        @@hhk=SetWindowsHookEx.call(14, @@lowLevelMouseProc, hMod, threadID)
       end
       def unhook()
        UnhookWindowsHookEx.call(@@hhk) if @@hhk
        @@hhk=nil
       end
      end
      
      class MyAPPObserver < Sketchup;;AppObserver #Need to use that because it's highly recommended to unhook the procedure.
       def onQuit() #Will unhook it when sketchup will be closed
        $lowLevelMouseProc.unhook
       end
      end
      
      Sketchup.add_observer(MyAPPObserver.new)
      $lowLevelMouseProc=LowLevelMouseHookProc.new
      threadID=GetCurrentThreadId.call
      hMod=GetModuleHandle.call
      
      file_name=File.basename(__FILE__)
      unless file_loaded?(file_name)
       $procState=0
       submenu=UI.menu("Plugins")
       item=submenu.add_item("LowLevelMouseHookProc"){
        if $procState==0
         $procState=1
         $lowLevelMouseProc.setHook(hMod) #Since 'lowLevel' stands for global or module handle then it will work only on mudule handle.
        else
         $procState=0
         $lowLevelMouseProc.unhook
         $inputText[0].erase! unless ($inputText[0]==nil or $inputText[0].deleted?)
         $inputText=[nil, [], 0]
        end
       }
       submenu.set_validation_proc(item){if $procState==0 then MF_UNCHECKED else MF_CHECKED end}
       file_loaded(file_name)
      end
      

      Here's some result of what I get:

      22 code; 0 msg; 522 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      23 code; 0 msg; 513 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      24 code; 0 msg; 514 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      25 code; 0 msg; 513 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      26 code; 0 msg; 514 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      27 code; 0 msg; 516 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      28 code; 0 msg; 517 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      29 code; 0 msg; 513 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      30 code; 0 msg; 514 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      31 code; 0 msg; 516 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      32 code; 0 msg; 517 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      33 code; 0 msg; 512 lParam; [31, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 287 y; 0 mouseData; 0
      34 code; 0 msg; 512 lParam; [34, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 290 y; 0 mouseData; 0
      35 code; 0 msg; 512 lParam; [39, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 295 y; 0 mouseData; 0
      36 code; 0 msg; 512 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      37 code; 0 msg; 512 lParam; [53, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 309 y; 0 mouseData; 0
      38 code; 0 msg; 512 lParam; [55, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 311 y; 0 mouseData; 0
      39 code; 0 msg; 512 lParam; [55, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 311 y; 0 mouseData; 0
      40 code; 0 msg; 512 lParam; [55, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 311 y; 0 mouseData; 0
      41 code; 0 msg; 512 lParam; [55, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 311 y; 0 mouseData; 0
      42 code; 0 msg; 512 lParam; [52, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 308 y; 0 mouseData; 0
      43 code; 0 msg; 512 lParam; [47, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 303 y; 0 mouseData; 0
      44 code; 0 msg; 512 lParam; [45, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 301 y; 0 mouseData; 0
      45 code; 0 msg; 513 lParam; [45, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 301 y; 0 mouseData; 0
      46 code; 0 msg; 512 lParam; [42, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 298 y; 0 mouseData; 0
      47 code; 0 msg; 512 lParam; [41, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 297 y; 0 mouseData; 0
      48 code; 0 msg; 512 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      49 code; 0 msg; 512 lParam; [47, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 303 y; 0 mouseData; 0
      50 code; 0 msg; 512 lParam; [48, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 304 y; 0 mouseData; 0
      51 code; 0 msg; 512 lParam; [49, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 305 y; 0 mouseData; 0
      52 code; 0 msg; 512 lParam; [49, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 305 y; 0 mouseData; 0
      53 code; 0 msg; 514 lParam; [49, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 305 y; 0 mouseData; 0
      54 code; 0 msg; 512 lParam; [47, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 303 y; 0 mouseData; 0
      55 code; 0 msg; 512 lParam; [47, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 303 y; 0 mouseData; 0
      56 code; 0 msg; 512 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      57 code; 0 msg; 512 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      58 code; 0 msg; 512 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      59 code; 0 msg; 512 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      60 code; 0 msg; 512 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      61 code; 0 msg; 513 lParam; [46, 1, nil, nil, nil, nil, nil, nil, nil, nil] x; 302 y; 0 mouseData; 0
      

      But Should the lParam struct give the whole structure?

      • From that structure I can only get the x-coordinate and sometimes the y-coordinate when cursor x-pos is 0. But I cannnot get the rest of the info. Like when I spin the mouse wheel wParam returns the message 522, but doesn't return the whole pointer to MSLLHOOKSTRUCT. I tested it on Borland Delphi 6 and it does returns the whole structure, but on ruby it doesn't. By many observations I came-up with an evidence:

      if some part of the pointer in ruby is nil then ruby assumes that the rest of the strucure is also nil and states it to the end of the pointer. It does that because if some part is nil then it would have to raise an error that it can't set nil value.
      Example:

      a=0.chr*16 a[4]=2 #Works! a[4]=nil #Raises an Error

      So, is there a way to get the whole structure without writing a dll?

      All references to urls are in my script.

      Plugin(unzip it to plugins and test):


      Low Level Mouse Procedure

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

        For some reasons I don't get replies πŸ˜• , does this topic makes sense>?

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

          Well.. I have not had time to test it.

          And it's Windows only. We really need a solution that works on both platforms (Mac and Windows,) and that means it needs to be built into the Sketchup API by Google.

          I'm not here much anymore.

          1 Reply Last reply Reply Quote 0
          • thomthomT Offline
            thomthom
            last edited by

            @anton_s said:

            For some reasons I don't get replies πŸ˜• , does this topic makes sense>?

            I think it's more of a matter of people now knowing the answer.

            Thomas Thomassen β€” SketchUp Monkey & Coding addict
            List of my plugins and link to the CookieWare fund

            1 Reply Last reply Reply Quote 0
            • thomthomT Offline
              thomthom
              last edited by

              @dan rathbun said:

              And it's Windows only. We really need a solution that works on both platforms (Mac and Windows,) and that means it needs to be built into the Sketchup API by Google.

              That depends if he is aiming to support both platforms...

              Thomas Thomassen β€” SketchUp Monkey & Coding addict
              List of my plugins and link to the CookieWare fund

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

                Just a few things I can see wrong.

                Including a library file ( Win32,) in the global ObjectSpace is a big no no. Your code needs to be wrapped within a module.

                Once module wrapped... all those global vars can become module @@vars, or local module vars, or module constants.

                I'm not here much anymore.

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

                  If you look at some of the pure Ruby source in Dan Berger's windows-pr package, you'll come across examples of accessing C structures from Ruby using Array.pack and String.unpack

                  I'm not here much anymore.

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

                    @thomthom said:

                    @dan rathbun said:

                    And it's Windows only. We really need a solution that works on both platforms (Mac and Windows,) and that means it needs to be built into the Sketchup API by Google.

                    That depends if he is aiming to support both platforms...

                    Well, yes, I do want to support those for both platforms, but its just a starting test for platform that I'm using. And its not I'm the only one who want's that, I know there is much more people that would also want that ability in their plugins. So, yes after a solution to this topic, the code will be extended into more abilities of using on other platforms.

                    @dan rathbun said:

                    Including a library file (Win32,) in the global ObjectSpace is a big no no. Your code needs to be wrapped within a module.
                    BIG Thanks Dan πŸ˜„ This thing was bugging me all the time I've need to wtite a code. This was a thing I needed to be sure of.

                    @dan rathbun said:

                    If you look at some of the pure Ruby source in Dan Berger's windows-pr package, you'll come across examples of accessing C structures from Ruby using Array.pack and String.unpack
                    πŸ‘ πŸ‘ πŸ‘
                    Thanks πŸ˜„, think this is a solution. I no doubt, WILL examine the pakage!!!

                    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