@dan rathbun said:
Well it's not called a "compiler" is it?
No, but I doubt it interprets characaters by characters at run time, it would be too slow. It has to pre-compile or something.
@dan rathbun said:
Well it's not called a "compiler" is it?
No, but I doubt it interprets characaters by characters at run time, it would be too slow. It has to pre-compile or something.
I agree 100% with you.
BTW, when SKP runs your rb scripts, is the rb script first compiled by the Ruby interpreter, or is it interpreted like the old DOS Basic? Or compiled to P-Code?
I found the answer to my own problem! I was running the code inside my class
I don't know why it makes a difference!
@dan rathbun said:
Using "Untitled" as a substring only works in English editions.
True!
@dan rathbun said:
The Win32 Resource ID in the sketchup.exe String Table is 61443 (in case you like using a LoadString system call.)
Thanks.
But I don't think my approach or that of thomthom to get the SKP window works. If you use Process.pid and enum the windows until you find the right one, and use GetWindowText WinAPI to get the title of the SKP window, it works, but not always. I have a shortcut to SKP in one of my folder and it works to get the title, but if I use the Windows Start menu to run SKP, the title is blank, so it's not getting the proper window as expected. And since the return text is blank, we can't tell which window it is!
So try it using the following...
wnd = getAncestor.call(wnd, 3)
buf = "\0" * 260
getWindowText.call(wnd, buf, 256)
UI.messagebox(buf.strip)
or the complete code...
getTopWindow = Win32API.new('user32.dll', 'GetTopWindow', 'l', 'l')
getWindow = Win32API.new('user32.dll', 'GetWindow', 'li', 'l')
getWindowThreadProcessId = Win32API.new('user32.dll', 'GetWindowThreadProcessId', 'lp', 'l')
getWindowText = Win32API.new('user32', 'GetWindowText', 'LPI', 'I')
getAncestor = Win32API.new('user32', 'GetAncestor', 'LI', 'L')
tid = Process.pid
wnd = getTopWindow.call(0)
pid = 0.chr * 4
while wnd != 0
getWindowThreadProcessId.call(wnd, pid)
pidnum = pid.unpack('L').first
if pidnum == tid
wnd = getAncestor.call(wnd, 3)
buf = "\0" * 260
getWindowText.call(wnd, buf, 256)
UI.messagebox(buf.strip)
break
end
wnd = getWindow.call(wnd, 2)
end
@dan rathbun said:
From Ruby you can get process id, like:
$$
or
Process.pid
That worked I should have used GetCurrentProcessId instead of GetCurrentThreadId but your way is much simpler. Thanks!
@thomthom said:
You experienced crashes?
Yes, and it seems to have something to do with toolbars from 3rd party. When I have all of them visible (about 30 of them), your code runs for about 10 secs then SK unload from memory!
@thomthom said:
What if the user has multiple windows open with the same title? Multiple unsaved models etc?
I know, that's why I don't want to use it and want my first code to work!
@thomthom said:
Did you try using
GetAncestor.call(handle, GA_ROOTOWNER)
to ensure you get the root SketchUp window which is the owner of all SU's window? Your code might be getting a child window...
No I didn't, because my code never return a handle to begin with! It does iterate all windows, so it should pickup the pid, that's why I'm asking for help!
model_path = Sketchup.active_model.path
if (model_path.empty?)
model_name = "Untitled"
else
model_name = File.basename(model_path)
end
if (Sketchup.app_name == "Google SketchUp Pro")
sketchup_title = model_name + " - SketchUp Pro"
else
sketchup_title = model_name + " - SketchUp"
end
findWindow = Win32API.new("user32.dll", "FindWindow", ['P','P'], 'N')
window_id = findWindow.call(0, sketchup_title)
Here's another way that works, but it's based on the title. I'd rather have my first one working instead, or your's if SK doesn't crash.
Have you tried my first one see what you get? Do you see what's wrong with it?
Yes I did look at your post first, but I got mixed results, sometimes SK just unload from memory, and sometimes the handle was nil. So I wanted to created one without a callback, hence my code above. I'm just not sure what the bug is.
@dan rathbun said:
Well it's supplied with the mingGW compiled Windows Ruby one-click install packages. So I'm not responsible.
I know, but I should have figured it out myself
Yes indeed, I didn't know the other 2 were loaded into the one. That's a nice ref book! Thanks Dan.
Sweet! But only ruby18-core.chm works out of the 3! Or is it me?
I just posted http://forums.sketchucation.com/viewtopic.php?f=180&t=39119 another challange for you
getWindow = Win32API.new('user32.dll', 'GetWindow', 'li', 'l')
getTopWindow = Win32API.new('user32.dll', 'GetTopWindow', 'l', 'l')
getWindowThreadProcessId = Win32API.new('user32.dll', 'GetWindowThreadProcessId', 'lp', 'l')
getCurrentThreadId = Win32API.new("kernel32.dll", "GetCurrentThreadId", '', 'L')
tid = getCurrentThreadId.call
wnd = getTopWindow.call(0)
pid = 0.chr * 4
while wnd != 0
getWindowThreadProcessId.call(wnd, pid)
pidnum = pid.unpack('L').first
if pidnum == tid
UI.messagebox(wnd.to_s)
break
end
wnd = getWindow.call(wnd, 2)
end
I'm trying to get the Sketchup window handle, and my code above never gets to display the handle! Looks right to me, but I have no idea why it isn't working. Any ideas?
Dan, what is the Block expected in rb_funcall(menu, rb_intern('add_submenu')...
I keep getting the error "tried to create Proc object without a block" if I use 1 arg.
If I use 2 arg, I get "wrong number of arguments (2 for 1)" but even you said it needs 2!? Confusing
@dan rathbun said:
The API
add_item
method takes 2 args, aString
and aBlock
, ... not 1 arg.
Indeed! I figured it out, and the rb_intern('menu')
takes one, a str of the submenu name, like "Plugins" right?
When I do rb_intern('add_submenu')
with 1 arg of str "Testing", it adds only "T" to the Pluigns menu, the first letter only!?
If I don't use rb_str_new2 SK crash, Am I doing it right?
For the Block, do I have to use rb_something to pass the Block, or just the reference pointer?
Sorry to be a pain in the......
Thank Dan. So far, everything works great, I even got this to work...
modUI = rb_define_module('UI');
menu = rb_funcall(modUI, rb_intern('menu'), 0, nil);
but I'm stuck on this one...
rb_funcall(menu, rb_intern('add_item'), 1, rb_str_new2('File/Testing'));
It tells me "tried to create Proc object without a block"
Where do you learn all this? I can't find any docs on rb_intern or what to pass to it. I only guess!
Dan, one last question, can the dll be compiled in 64bit or does it have to be 32bit like SK?
Does the handle return by rb_define_module('Sketchup') correspond to the ISkpApplication interface?