Module: TT::Win32

Defined in:
TT_Lib2/win32.rb,
TT_Lib2/win32_shim.rb

Overview

Since:

  • 2.5.0

Defined Under Namespace

Modules: Shim Classes: API

Constant Summary

NULL =

C/C++ constants.

Since:

  • 2.5.0

0
MAX_PATH =

Windows constants.

Since:

  • 2.5.0

260
CP_ACP =

Since:

  • 2.5.0

0
CP_UTF8 =

Since:

  • 2.5.0

65001
SHGFP_TYPE_CURRENT =

SHGetFolderPath constants.

Since:

  • 2.5.0

0
SHGFP_TYPE_DEFAULT =

Since:

  • 2.5.0

1
CSIDL_LOCAL_APPDATA =

Since:

  • 2.5.0

0x001c
WS_CAPTION =

Since:

  • 2.5.0

0x00C00000
WS_SYSMENU =

Since:

  • 2.5.0

0x00080000
WS_MAXIMIZEBOX =

Since:

  • 2.5.0

0x10000
WS_MINIMIZEBOX =

Since:

  • 2.5.0

0x20000
WS_SIZEBOX =

Since:

  • 2.5.0

0x40000
WS_POPUP =

Since:

  • 2.5.0

0x80000000
WS_EX_TOOLWINDOW =

Since:

  • 2.5.0

0x00000080
WS_EX_NOACTIVATE =

Since:

  • 2.5.0

0x08000000
GWL_STYLE =

Since:

  • 2.5.0

-16
GWL_EXSTYLE =

Since:

  • 2.5.0

-20
SWP_NOSIZE =

Since:

  • 2.5.0

0x0001
SWP_NOMOVE =

Since:

  • 2.5.0

0x0002
SWP_NOACTIVATE =

Since:

  • 2.5.0

0x0010
SWP_DRAWFRAME =

Since:

  • 2.5.0

0x0020
SWP_FRAMECHANGED =

Since:

  • 2.5.0

0x0020
SWP_NOREPOSITION =

Since:

  • 2.5.0

0x0200
HWND_BOTTOM =

Since:

  • 2.5.0

1
HWND_TOP =

Since:

  • 2.5.0

0
HWND_TOPMOST =

Since:

  • 2.5.0

-1
HWND_NOTOPMOST =

Since:

  • 2.5.0

-2
GA_PARENT =

Since:

  • 2.5.0

1
GA_ROOT =

Since:

  • 2.5.0

2
GA_ROOTOWNER =

Since:

  • 2.5.0

3
PM_NOREMOVE =

PeekMessage() flags

Since:

  • 2.5.0

0x0000
PM_REMOVE =

Messages are not removed from the queue after processing by PeekMessage.

Since:

  • 2.5.0

0x0001
PM_NOYIELD =

Messages are removed from the queue after processing by PeekMessage.

Since:

  • 2.5.0

0x0002
GetAncestor =

Windows Functions L = Long (includes hwnd) I = Integer P = Pointer V = Void

Since:

  • 2.5.0

API.new('GetAncestor' , 'LI', 'L', 'user32')
GetActiveWindow =

msdn.microsoft.com/en-us/library/ms646292%28v=vs.85%29.aspx blogs.msdn.com/b/oldnewthing/archive/2008/10/06/8969399.aspx

The return value is the handle to the active window attached to the calling thread's message queue. Otherwise, the return value is NULL.

To get the handle to the foreground window, you can use GetForegroundWindow.

Since:

  • 2.5.0

API.new('GetActiveWindow', '', 'L', 'user32')
SetActiveWindow =

Since:

  • 2.5.0

API.new('SetActiveWindow', 'L', 'L', 'user32')
SetWindowPos =

Since:

  • 2.5.0

API.new('SetWindowPos' , 'LLIIIII', 'I', 'user32')
SetWindowLong =

Since:

  • 2.5.0

API.new('SetWindowLong', 'LIL', 'L', 'user32')
GetWindowLong =

Since:

  • 2.5.0

API.new('GetWindowLong', 'LI' , 'L', 'user32')
GetWindowText =

Since:

  • 2.5.0

API.new('GetWindowText', 'LPI', 'I', 'user32')
GetWindowTextLength =

Since:

  • 2.5.0

API.new('GetWindowTextLength', 'L', 'I', 'user32')
PeekMessage =

Since:

  • 2.5.0

API.new('PeekMessage' , 'PLIII', 'I', 'user32')
OutputDebugString =

Since:

  • 2.5.0

API.new('OutputDebugString', 'P', 'V', 'kernel32')
EnumThreadWindows =

Raises an error in Ruby 2.2 because it uses Fiddle directly while 2.0 used DL. It didn't work in 2.0, but it didn't raise an error.

Since:

  • 2.5.0

API.new('EnumThreadWindows', 'LKP', 'I', 'user32')
GetCurrentThreadId =

Process.pid returns the same value as GetCurrentProcessId. GetCurrentProcessId = API.new('GetCurrentProcessId' , '', 'L', 'kernel32')

Since:

  • 2.5.0

API.new('GetCurrentThreadId', '', 'L', 'kernel32')
SHGetFolderPath =

Shell functons.

Since:

  • 2.5.0

API.new('SHGetFolderPathW', 'LILLP', 'I', 'shell32')
GetShortPathName =

File functions.

Since:

  • 2.5.0

API.new('GetShortPathNameW', 'PPL', 'L', 'kernel32')
MultiByteToWideChar =

String encoding.

Since:

  • 2.5.0

API.new('MultiByteToWideChar', 'LLPIPI', 'I', 'kernel32')
WideCharToMultiByte =

Since:

  • 2.5.0

API.new('WideCharToMultiByte', 'LLPIPIPP', 'I', 'kernel32')

Class Method Summary collapse

Class Method Details

.activate_sketchup_windowBoolean

Returns:

  • (Boolean)

Since:

  • 2.6.0



252
253
254
255
256
# File 'TT_Lib2/win32.rb', line 252

def self.activate_sketchup_window
  hwnd = self.get_sketchup_window
  return false unless hwnd
  SetActiveWindow.call( hwnd )
end

.get_folder_path(csidl) ⇒ String|Nil

Examples:

TT::Win32.get_folder_path( TT::Win32::CSIDL_LOCAL_APPDATA )

Parameters:

  • csidl (Integer)

Returns:

  • (String|Nil)

Since:

  • 2.9.0



281
282
283
284
# File 'TT_Lib2/win32.rb', line 281

def self.get_folder_path( csidl )
  path = self.get_folder_path_utf16( csidl )
  self.utf16_to_utf8( path )
end

.get_folder_path_ansi(csidl) ⇒ String|Nil

Examples:

TT::Win32.get_folder_path_ansi( TT::Win32::CSIDL_LOCAL_APPDATA )

Parameters:

  • csidl (Integer)

Returns:

  • (String|Nil)

Since:

  • 2.9.0



293
294
295
296
# File 'TT_Lib2/win32.rb', line 293

def self.get_folder_path_ansi( csidl )
  path = self.get_folder_path_utf16( csidl )
  self.utf16_to_ansi( path )
end

.get_short_folder_path(csidl) ⇒ String|Nil

Examples:

TT::Win32.get_short_folder_path( TT::Win32::CSIDL_LOCAL_APPDATA )

Parameters:

  • csidl (Integer)

Returns:

  • (String|Nil)

Since:

  • 2.9.0



305
306
307
308
# File 'TT_Lib2/win32.rb', line 305

def self.get_short_folder_path( csidl )
  path = self.get_short_folder_path_utf16( csidl )
  self.utf16_to_utf8( path )
end

.get_short_folder_path_ansi(csidl) ⇒ String|Nil

Examples:

TT::Win32.get_short_folder_path_ansi( TT::Win32::CSIDL_LOCAL_APPDATA )

Parameters:

  • csidl (Integer)

Returns:

  • (String|Nil)

Since:

  • 2.9.0



317
318
319
320
# File 'TT_Lib2/win32.rb', line 317

def self.get_short_folder_path_ansi( csidl )
  path = self.get_short_folder_path_utf16( csidl )
  self.utf16_to_ansi( path )
end

.get_sketchup_windowObject

Since:

  • 2.5.0



232
233
234
235
236
237
238
239
240
241
242
# File 'TT_Lib2/win32.rb', line 232

def self.get_sketchup_window
  threadId = GetCurrentThreadId.call
  hwnd = 0
  param = 'SketchUpMainWindow'
  enumWindowsProc = EnumWindowsProc.new( param ) { |handle|
    hwnd = GetAncestor.call( handle, GA_ROOTOWNER )
    0
  }
  EnumThreadWindows.call( threadId, enumWindowsProc.callback, param )
  hwnd
end

.get_virtual_file(file) ⇒ String, Nil

Parameters:

  • file (String)

Returns:

  • (String, Nil)

Since:

  • 2.9.0



514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
# File 'TT_Lib2/win32.rb', line 514

def self.get_virtual_file( file )
  filename = File.basename( file )
  filepath = File.dirname( file )
  # Verify file exists.
  unless File.exist?( file )
    raise IOError, "The file '#{file}' does not exist."
  end
  if ENV['LOCALAPPDATA'].nil?
    return nil
  end
  virtualstore = File.join( ENV['LOCALAPPDATA'], 'VirtualStore' )
  path = filepath.split(':')[1]
  virtual_path = File.join( virtualstore, path, filename )
  File.expand_path( virtual_path )
end

.get_window_text(hwnd) ⇒ String|Nil

Parameters:

  • hwnd (Integer)

Returns:

  • (String|Nil)

Since:

  • 2.5.0



263
264
265
266
267
268
269
270
271
272
# File 'TT_Lib2/win32.rb', line 263

def self.get_window_text(hwnd)
  # Create a string buffer for the window text.
  buf_len = GetWindowTextLength.call(hwnd)
  return nil if buf_len == 0
  str = ' ' * (buf_len + 1)
  # Retreive the text.
  result = GetWindowText.call(hwnd, str, str.length)
  return nil if result == 0
  str.strip
end

.is_virtualized?(file) ⇒ String

Parameters:

  • file (String)

Returns:

  • (String)

Since:

  • 2.9.0



504
505
506
507
# File 'TT_Lib2/win32.rb', line 504

def self.is_virtualized?( file )
  virtualfile = self.get_virtual_path( file )
  !virtualfile.nil? && File.exist?( virtualfile )
end

.make_toolwindow_frame(window_title) ⇒ Nil

Call after webdialog.show to change the window into a toolwindow. Spesify the window title so the method can verify it changes the correct window.

Parameters:

  • window_title (String)

Returns:

  • (Nil)

Since:

  • 2.5.0



406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
# File 'TT_Lib2/win32.rb', line 406

def self.make_toolwindow_frame(window_title)
  # Retrieves the window handle to the active window attached to the calling
  # thread's message queue.
  hwnd = GetActiveWindow.call
  return nil if hwnd == 0

  # Verify window text as extra security to ensure it's the correct window.
  buf_len = GetWindowTextLength.call(hwnd)
  return nil if buf_len == 0

  str = ' ' * (buf_len + 1)
  result = GetWindowText.call(hwnd, str, str.length)
  return nil if result == 0

  return nil unless str.strip == window_title.strip

  # Set frame to Toolwindow
  style = GetWindowLong.call(hwnd, GWL_EXSTYLE)
  return nil if style == 0

  new_style = style | WS_EX_TOOLWINDOW
  result = SetWindowLong.call(hwnd, GWL_EXSTYLE, new_style)
  return nil if result == 0

  # Remove and disable minimze and maximize
  # http://support.microsoft.com/kb/137033
  style = GetWindowLong.call(hwnd, GWL_STYLE)
  return nil if style == 0

  style = style & ~WS_MINIMIZEBOX
  style = style & ~WS_MAXIMIZEBOX
  result = SetWindowLong.call(hwnd, GWL_STYLE,  style)
  return nil if result == 0

  # Refresh the window frame
  # (!) SWP_NOZORDER | SWP_NOOWNERZORDER
  flags = SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
  result = SetWindowPos.call(hwnd, 0, 0, 0, 0, 0, flags)
  result != 0
end

.refresh_sketchupBoolean

Allows the SketchUp process to process it's queued messages. Avoids whiteout.

Returns:

  • (Boolean)

Since:

  • 2.5.0



495
496
497
# File 'TT_Lib2/win32.rb', line 495

def self.refresh_sketchup
  PeekMessage.call( nil, nil, 0, 0, PM_NOREMOVE ) != 0
end

.utf16_to_ansi(utf16_string) ⇒ String|Nil

Parameters:

  • utf16_string (String)

Returns:

  • (String|Nil)

Since:

  • 2.9.0



369
370
371
# File 'TT_Lib2/win32.rb', line 369

def self.utf16_to_ansi( utf16_string )
  self.utf16_to_codepage( utf16_string, CP_ACP )
end

.utf16_to_utf8(utf16_string) ⇒ String|Nil

Parameters:

  • utf16_string (String)

Returns:

  • (String|Nil)

Since:

  • 2.9.0



378
379
380
# File 'TT_Lib2/win32.rb', line 378

def self.utf16_to_utf8( utf16_string )
  self.utf16_to_codepage( utf16_string, CP_UTF8 )
end

.utf8_to_utf16(utf8_string) ⇒ String|Nil

Parameters:

  • utf8_string (String)

Returns:

  • (String|Nil)

Since:

  • 2.9.0



355
356
357
358
359
360
361
362
# File 'TT_Lib2/win32.rb', line 355

def self.utf8_to_utf16( utf8_string )
  utf16_string_len = MultiByteToWideChar.call( CP_UTF8, 0,
    "#{utf8_string}\0", -1, nil, 0 )
  utf16_string = ' ' * ( utf16_string_len * 2 )
  MultiByteToWideChar.call( CP_UTF8, 0,
    "#{utf8_string}\0", -1, utf16_string, utf16_string_len )
  utf16_string
end

.window_no_resize(window_title) ⇒ Nil

Removes the Min and Max button.

Call after webdialog.show to change the window into a toolwindow. Spesify the window title so the method can verify it changes the correct window.

Parameters:

  • window_title (String)

Returns:

  • (Nil)

Since:

  • 2.6.0



457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'TT_Lib2/win32.rb', line 457

def self.window_no_resize( window_title )
  # Retrieves the window handle to the active window attached to the calling
  # thread's message queue.
  hwnd = GetActiveWindow.call
  return nil if hwnd == 0

  # Verify window text as extra security to ensure it's the correct window.
  buf_len = GetWindowTextLength.call(hwnd)
  return nil if buf_len == 0

  str = ' ' * (buf_len + 1)
  result = GetWindowText.call(hwnd, str, str.length)
  return nil if result == 0

  return nil unless str.strip == window_title.strip

  # Remove and disable minimze and maximize
  # http://support.microsoft.com/kb/137033
  style = GetWindowLong.call(hwnd, GWL_STYLE)
  return nil if style == 0

  style = style & ~WS_MINIMIZEBOX
  style = style & ~WS_MAXIMIZEBOX
  result = SetWindowLong.call(hwnd, GWL_STYLE,  style)
  return nil if result == 0

  # Refresh the window frame
  # (!) SWP_NOZORDER | SWP_NOOWNERZORDER
  flags = SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
  result = SetWindowPos.call(hwnd, 0, 0, 0, 0, 0, flags)
  result != 0
end