Hook Procedure (win32 api)
-
This is the start to method of monetering keyboard/mouse messages and making decisions for them to be either passed or removed.
Some of us like Mr.k wondered on getting mouse input using win32 api. Here is the link: http://forums.sketchucation.com/viewtopic.php?f=180&t=38651. We got the click input, but it wasn't enough. We wanted more!!! So the main topic is about mouse and keyboard input.
-
Why need that?
There are a lot of us including me who would want to make games or cool plugins in sketchup using mouse and keyboard, but so that shortcut keys won't interfere with sketchup tools. Of cource we could remove each shortcut, but that's an inoing pain of doing that. And yeah most of us use keyboard to select default tools, so they would want to set shortcuts back, but that also would take a long time. -
Solution
Before I went on doing something myself, I first decided to get some suggestions from Dad. He suggested to use the hook procedure. It took a long time though, before he had time to help me understand and explain about computer messages and inputs, but not refering to time I still got it. Anyways, the method of hook proccedure was to make a decision for a message. It could process or be removed.
Hooks reference: http://msdn.microsoft.com/en-us/library/ms632589(v=VS.85).aspx
Method:
Firt we create Win API constants:
SetWindowsHookEx=API.new('SetWindowsHookEx', 'IKII', 'I', 'User32') UnhookWindowsHookEx=API.new('UnhookWindowsHookEx', 'I', 'I', 'User32') CallNextHookEx=API.new('CallNextHookEx', 'IILL', 'I', 'User32') GetCurrentThreadId=API.new('GetCurrentThreadId', 'V', 'I', 'Kernel32') GetModuleHandle=API.new('GetModuleHandle', 'V', 'I', 'Kernel32')
Then Callback Function:
From my test and from thomthom's reference at http://forums.sketchucation.com/viewtopic.php?f=180&t=33756&start=15#p297228 it is better that callbacks would be set inside the class. Don't know why. Please tell me if you know or have some ideas about that.
A callback function to keyboardProc parameters@@keyboardProc=API::Callback.new('ILI', 'I'){|nCode, wParam, lParam| return(CallNextHookEx.call(0, nCode, wParam, lParam)) if nCode<0 puts "any keyboard input is activated" ####Script#### 0 #0 - process the message, 3 - or I think any other positive number will remove the message from input. #Removed input will depend on threadID or module handle }
Set Hook:
For instance we'll take KeyboardProc http://msdn.microsoft.com/en-us/library/ms644984(v=VS.85).aspx
setHook:
hhk=SetWindowsHookEx.call(2, @@keyboardProc, hMod, threadID)
http://msdn.microsoft.com/en-us/library/ms644990(v=VS.85).aspxThis will make the callback function to get info on keyboard messages. In that callback function
Unhook: HIGHLY RECOMMENDED!!! Stop callback function from being called.
UnhookWindowsHookEx.call(hhk)
http://msdn.microsoft.com/en-us/library/ms644993(v=VS.85).aspxThere is another function: callNextHookEx. I know that It should be called in the callback function, but rightnow I'm not to sure exactly when to call it ~ when nCode<0 or what? Here's it is: http://msdn.microsoft.com/en-us/library/ms644974(v=VS.85).aspx
Still everything works great in my script, but I would want some more explanation to that.In hooks you can hook two keyboard procedures: One is just "KeyboardProc" and other is "LowLevelKeyboardProc". KeyboardProc is mostly usefull to block messages to certain window or thread I think. LowLevelKeyBoardProc is to make decisions to messages of the whole module handle. Of cource "ctrl-alt-delete" message is passed, but i'll still give a little warning sign to that, since you wouldn't be able to send keyboard messages to other windows, while this message is active.
You can also hook two kinds of mouse procedures. MouseProc and LowLevelMouseProc to which I would give a huge warning. - If all mouseMove messages would be removed from LowLevelMouseProc, then you won't be able to move the cursor. So, if you wan't to use it then remove only certain messages or remove all, but, so that there would be a way to unblock it back.
Bug or script error on lParam input in callback functions:
For instance lets take LowLevelMouseProc http://msdn.microsoft.com/en-us/library/ms644986(v=VS.85).aspx It says lParam should return a pointer to MSLLHOOKSTRUCT http://msdn.microsoft.com/en-us/library/ms644970(v=VS.85).aspx. But in my tests it only return's the x-coordinate of that structure. Should it return the whole structure? Or Does it return the address of that pointer? If does then how could I get the whole pointer structure? This is really important questions to me that I ask you to please answer it. Anyways, in LowLevelMouseProc I want to get the lParam because its MouseData specifies the dirrection the mousewheel rotation.Usage: Toggle between menu items, simple as that.
-
-
Works and Tested in Sketchup 7 and 8.
Note: some script that crashes in sketchup 7:
def car return() end
"return()" with nothing in brackets will crash su7. So, to return nothing in su7, do not add brackets ("return"). Though you can add brackets in su8.
-
@anton_s said:
Note: some script that crashes in sketchup 7:
def car return() end
use:
return nil
..
return
is a Ruby keyword, not a method call. You may be confusing the old Ruby v1.8.0-p0 interpreter that is distro'd with SU7. The old interpreter may think you are trying to call a method named "return" with an empty parameter list.(You can confirm by renaming the DLL, and copying the newer v1.8.6-p287 DLL from the SU8 folder, into the SU7 folder.)
-
@dan rathbun said:
(You can confirm by renaming the DLL, and copying the newer v1.8.6-p287 DLL from the SU8 folder, into the SU7 folder.)
What is su8 mswin32 version?
Based on this link http://forums.sketchucation.com/viewtopic.php?f=180&t=10142&start=15#p276047is there ruby 1.9.2 mswin32.dll?
-
@anton_s said:
@dan rathbun said:
(You can confirm by renaming the DLL, and copying the newer v1.8.6-p287 DLL from the SU8 folder, into the SU7 folder.)
What is su8 mswin32 version?
I stated what the SU8 Ruby version was (above).
@anton_s said:
Based on this link http://forums.sketchucation.com/viewtopic.php?f=180&t=10142&start=15#p276047is there ruby 1.9.2 mswin32.dll?
That is MY post, and I do not mention ANY Ruby 1.9.x version, because Sketchup CANNOT load Ruby in that trunk. You must stay in the 1.8.x trunk.
-
, thanks Dan...
Have you tried downloading the "HookProc.zip", which is on my first post of this topic?
If you're willing to, can you please download it to plugins and test it if it works or not?Here is the reference:
Items
KeyboardProc - The stated script should write an active keyboard message to logLine or text and remove the message from being sent to current thread. Ex: Lets assume virtual keyboard message "p" is shortcut to pushpull. If you click key "p" while the KeyboardProc is not active, the shortcut should call the pushpull tool. If you click key "p" while the KeyboardProc is active then the pudspull tool won't be called. Keyboard messages will not be removed from other windows. It will just remove them from the stated window, which in this case would be the sketchup window.MouseProc - Should moniter/display mouse messages sent to the thread. Default script will not remove the messages. Ex: message 512 - mouse move, 522, mouse wheel rotate, 513 / 514 - mouse button clicks.
LowLevelKeyboardProc - Should moniter/display and remove keyboard messages from the module handle. Ex: Lets say I have two windows: Sketchup and notepad++. In Sketchup window I activate LowLevelMouseProc, move to notepad++, and begin to type. Trying to type I don't get anything. It's because LowLevelKeyboard Hook Procedure prevents most the keyboard messages from to be sent to the module handle. Well, the once that it can't remove are some keyboard combination shortcuts, like "ctrl-alt-delete", "alt-lshift-PtrScn" and more.
LowLevelMouseProc - Same as lowLevelKeyboardProc, but this time should display mouse messages sent to the module handle. Well you can state it to remove messages by changing "0" return value to "3", but by doing that your comp will act like the mouse is disconnected from the computer. If you'd want to remove only some mouse messages from module handle, then just write a block like "If wParam==512 then 0 else 3 end".
All of the hooks above can be toggle by being set or unhooked.
RemoveAll - Unhooks all hooks above.
ClearTextQueue - Not really important in that role. Just clears the text queue that is displayed. LogLine remove's lines from text queue automatically, though just added for fun.
Think this is all
Thanks...
Advertisement