Class: WinWindow
- Inherits:
-
Object
- Object
- WinWindow
- Defined in:
- lib/winwindow.rb,
lib/winwindow/ext.rb
Overview
extensions to the language which are external to what the WinWindow library itself does
Defined Under Namespace
Modules: AttachLib, Waiter, WinGDI, WinKernel, WinUser Classes: Error, MatchError, NotExistsError, SystemError, WaiterError
Constant Summary collapse
- Enumerator =
:nodoc:
Object.const_defined?('Enumerator') ? ::Enumerator : Enumerable::Enumerator
- Types =
AttachLib::Types
- WM_CLOSE =
0x0010- WM_KEYDOWN =
0x0100- WM_KEYUP =
0x0101- WM_CHAR =
0x0102- BM_CLICK =
0x00F5- WM_COMMAND =
0x0111- WM_SETTEXT =
0x000C- WM_GETTEXT =
0x000D- WM_GETTEXTLENGTH =
0xE- GW_HWNDFIRST =
– GetWindows constants
0- GW_HWNDLAST =
1- GW_HWNDNEXT =
2- GW_HWNDPREV =
3- GW_OWNER =
4- GW_CHILD =
5- GW_ENABLEDPOPUP =
6- GW_MAX =
6- GA_PARENT =
– GetAncestor constants
1- GA_ROOT =
2- GA_ROOTOWNER =
3- SW_HIDE =
– ShowWindow constants - msdn.microsoft.com/en-us/library/ms633548(VS.85).aspx
0- SW_SHOWNORMAL =
Hides the window and activates another window.
1- SW_SHOWMINIMIZED =
Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
2- SW_SHOWMAXIMIZED =
Activates the window and displays it as a minimized window.
3- SW_MAXIMIZE =
Activates the window and displays it as a maximized window.
3- SW_SHOWNOACTIVATE =
Maximizes the specified window. – there seems to be no distinct SW_MAXIMIZE (but there is a distinct SW_MINIMIZE), just the same as SW_SHOWMAXIMIZED some references define SW_MAXIMIZE as 11, which seems to just be wrong; that is correctly SW_FORCEMINIMIZE
4- SW_SHOW =
Displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except the window is not actived.
5- SW_MINIMIZE =
Activates the window and displays it in its current size and position.
6- SW_SHOWMINNOACTIVE =
Minimizes the specified window and activates the next top-level window in the Z order.
7- SW_SHOWNA =
Displays the window as a minimized window. This value is similar to SW_SHOWMINIMIZED, except the window is not activated.
8- SW_RESTORE =
Displays the window in its current size and position. This value is similar to SW_SHOW, except the window is not activated.
9- SW_SHOWDEFAULT =
Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when restoring a minimized window.
10- SW_FORCEMINIMIZE =
Sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application.
11- WIN_TRUE =
Windows 2000/XP: Minimizes a window, even if the thread that owns the window is not responding. This flag should only be used when minimizing windows from a different thread.
-1
- WIN_FALSE =
0- LSFW_LOCK =
:stopdoc:
1- LSFW_UNLOCK =
2- VK_MENU =
:stopdoc:
0x12- KEYEVENTF_KEYDOWN =
0x0- KEYEVENTF_KEYUP =
0x2- SRCCOPY =
:stopdoc:
0xCC0020- DIB_RGB_COLORS =
0x0- GMEM_FIXED =
0x0- All =
Enumerable object that iterates over every available window
May raise a WinWindow::SystemError from WinWindow.each_window
Enumerator.new(WinWindow, :each_window)
Instance Attribute Summary collapse
-
#hwnd ⇒ Object
readonly
handle to the window - a positive integer.
Class Method Summary collapse
-
.desktop_window ⇒ Object
Returns a WinWindow representing the desktop window.
-
.each_window ⇒ Object
Iterates over every window yielding a WinWindow object.
-
.find_all_by_text(text) ⇒ Object
returns all WinWindow objects found whose text matches what is given.
-
.find_first_by_text(text) ⇒ Object
returns the first window found whose text matches what is given.
-
.find_only_by_text(text) ⇒ Object
returns the only window matching the given text.
-
.foreground_window ⇒ Object
Returns a WinWindow representing the current foreground window (the window with which the user is currently working).
-
.handle_options(given_options, default_options, other_allowed_keys = []) ⇒ Object
takes given options and default options, and optionally a list of additional allowed keys not specified in default options (this is useful when you want to pass options along to another function but don’t want to specify a default that will clobber that function’s default) raises ArgumentError if the given options have an invalid key (defined as one not specified in default options or other_allowed_keys), and sets default values in given options where nothing is set.
-
.lock_set_foreground_window ⇒ Object
The foreground process can call the #lock_set_foreground_window function to disable calls to the #set_foreground! function.
-
.unlock_set_foreground_window ⇒ Object
The foreground process can call the #lock_set_foreground_window function to disable calls to the #set_foreground! function.
Instance Method Summary collapse
-
#ancestor_parent ⇒ Object
Retrieves the parent window.
-
#ancestor_root ⇒ Object
Retrieves the root window by walking the chain of parent windows.
-
#ancestor_root_owner ⇒ Object
Retrieves the owned root window by walking the chain of parent and owner windows returned by GetParent.
-
#bring_to_top! ⇒ Object
brings the window to the top of the Z order.
-
#capture_to_bmp_blob(options = {}) ⇒ Object
captures this window to a bitmap image (a screenshot).
-
#capture_to_bmp_file(filename, options = {}) ⇒ Object
captures this window to a bitmap image (a screenshot).
-
#capture_to_bmp_structs(options = {}) ⇒ Object
Creates a bitmap image of this window (a screenshot).
-
#child_button(button_text) ⇒ Object
returns a WinWindow that is a child of this that matches the given button_text (Regexp or #to_s-able) or nil if no such child exists.
-
#child_control_with_preceding_label(preceding_label_text, options = {}) ⇒ Object
Finds a child of this window which follows a label with the given text.
-
#child_of?(parent) ⇒ Boolean
tests whether a window is a child window or descendant window of a specified parent window.
-
#children ⇒ Object
returns an Enumerable object that can iterate over each child of this window, yielding a WinWindow object .
-
#children_recursive(options = {}) ⇒ Object
returns an Enumerable object that can iterate over each child of this window recursively, yielding a WinWindow object for each child.
-
#class_name ⇒ Object
retrieves the name of the class to which this window belongs.
-
#click! ⇒ Object
tries to click on this Window (using PostMessage sending BM_CLICK message).
-
#click_child_button_try_for!(button_text, time, options = {}) ⇒ Object
Give the name of a button, or a Regexp to match it (see #child_button).
-
#client_rect ⇒ Object
Returns a Rect struct with members left, top, right, and bottom indicating the coordinates of a window’s client area.
-
#close! ⇒ Object
minimizes this window (but does not destroy it) (why is it called close? I don’t know).
-
#destroy! ⇒ Object
destroy! destroys the window.
-
#each_child ⇒ Object
iterates over each child, yielding a WinWindow object.
-
#enabled_popup ⇒ Object
The retrieved handle identifies the enabled popup window owned by the specified window (the search uses the first such window found using GW_HWNDNEXT); otherwise, if there are no enabled popup windows, nil is returned.
-
#end_task!(force = false) ⇒ Object
called to forcibly close the window.
-
#eql?(oth) ⇒ Boolean
(also: #==)
true if comparing an object of the same class with the same hwnd (integer).
-
#exists? ⇒ Boolean
determines whether the specified window handle identifies an existing window.
-
#force_minimize! ⇒ Object
Windows 2000/XP: Minimizes the window, even if the thread that owns the window is not responding.
-
#foreground? ⇒ Boolean
returns true if this is the same Window that is returned from WinWindow.foreground_window.
-
#handle_options(*args) ⇒ Object
:nodoc:.
-
#hash ⇒ Object
:nodoc:.
-
#hide! ⇒ Object
Hides the window and activates another window.
-
#hung_app? ⇒ Boolean
determine if Microsoft Windows considers that a specified application is not responding.
-
#iconic? ⇒ Boolean
(also: #minimized?)
whether the window is minimized (iconic).
-
#initialize(hwnd) ⇒ WinWindow
constructor
creates a WinWindow from a given hWnd handle (integer) .
- #inspect ⇒ Object
-
#last_active_popup ⇒ Object
determines which pop-up window owned by this window was most recently active.
-
#maximize! ⇒ Object
Maximizes this window.
-
#minimize! ⇒ Object
Minimizes this window and activates the next top-level window in the Z order.
-
#owner ⇒ Object
The retrieved handle identifies the specified window’s owner window, if any.
-
#parent ⇒ Object
retrieves a handle to this window’s parent or owner.
- #pretty_print(pp) ⇒ Object
-
#process_id ⇒ Object
returns the process identifier that created this window.
-
#real_class_name ⇒ Object
retrieves a string that specifies the window type.
-
#really_set_foreground!(options = {}) ⇒ Object
really sets this to be the foreground window.
-
#recurse_each_child(options = {}) ⇒ Object
iterates over each child recursively, yielding a WinWindow object for each child.
-
#restore! ⇒ Object
Activates and displays the window.
-
#retrieve_text ⇒ Object
This is similar to #text that one is GetWindowText(hwnd) this one is SendMessage(hwnd, WM_GETTEXT) differences are documented here: msdn.microsoft.com/en-us/magazine/cc301438.aspx and here: blogs.msdn.com/oldnewthing/archive/2003/08/21/54675.aspx.
-
#retrieve_text_length ⇒ Object
similar to #text_length; differences between that and this are the same as between #text and #retrieve_text.
-
#send_close! ⇒ Object
sends notification that the window should close.
-
#send_set_text!(text) ⇒ Object
sets text by sending WM_SETTEXT message.
-
#set_foreground! ⇒ Object
puts the thread that created the specified window into the foreground and activates the window.
-
#set_parent!(parent) ⇒ Object
changes the parent window of this child window.
-
#set_text!(text) ⇒ Object
changes the text of the specified window’s title bar (if it has one).
-
#show! ⇒ Object
Activates the window and displays it in its current size and position.
-
#show_default! ⇒ Object
Sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application.
-
#show_maximized! ⇒ Object
Activates the window and displays it as a maximized window.
-
#show_min_no_active! ⇒ Object
Displays the window as a minimized window.
-
#show_minimized! ⇒ Object
Activates the window and displays it as a minimized window.
-
#show_na! ⇒ Object
Displays the window in its current size and position.
-
#show_no_activate! ⇒ Object
Displays the window in its most recent size and position.
-
#show_normal! ⇒ Object
Activates and displays a window.
-
#switch_to!(alt_tab = false) ⇒ Object
switch focus and bring to the foreground.
-
#text ⇒ Object
retrieves the text of this window’s title bar (if it has one).
-
#text_length ⇒ Object
length of the window text, see #text.
-
#thread_id ⇒ Object
returns the identifier of the thread that created the window.
-
#top_window ⇒ Object
examines the Z order of the child windows associated with self and retrieves a handle to the child window at the top of the Z order.
-
#visible? ⇒ Boolean
visibility state of the specified window.
-
#window_rect ⇒ Object
Returns a Rect struct with members left, top, right, and bottom indicating the dimensions of the bounding rectangle of the specified window.
Constructor Details
#initialize(hwnd) ⇒ WinWindow
creates a WinWindow from a given hWnd handle (integer)
raises ArgumentError if the hWnd is not an Integer greater than 0
397 398 399 400 |
# File 'lib/winwindow.rb', line 397 def initialize(hwnd) raise ArgumentError, "hwnd must be an integer greater than 0; got #{hwnd.inspect} (#{hwnd.class})" unless hwnd.is_a?(Integer) && hwnd > 0 @hwnd=hwnd end |
Instance Attribute Details
#hwnd ⇒ Object (readonly)
handle to the window - a positive integer. (properly, this is a pointer, but we deal with it as a number.)
392 393 394 |
# File 'lib/winwindow.rb', line 392 def hwnd @hwnd end |
Class Method Details
.desktop_window ⇒ Object
Returns a WinWindow representing the desktop window. The desktop window covers the entire screen. The desktop window is the area on top of which other windows are painted.
1356 1357 1358 1359 1360 1361 1362 1363 |
# File 'lib/winwindow.rb', line 1356 def self.desktop_window hwnd=WinUser.GetDesktopWindow if hwnd == 0 nil else self.new(hwnd) end end |
.each_window ⇒ Object
Iterates over every window yielding a WinWindow object.
use WinWindow::All if you want an Enumerable object.
Raises a WinWindow::SystemError if a System Error occurs.
msdn.microsoft.com/en-us/library/ms633497.aspx
For System Error Codes see msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 |
# File 'lib/winwindow.rb', line 1253 def self.each_window # :yields: win_window enum_windows_callback= WinUser.window_enum_callback do |hwnd,lparam| yield WinWindow.new(hwnd) WIN_TRUE end begin ret=WinUser.EnumWindows(enum_windows_callback, nil) ensure WinUser.remove_window_enum_callback(enum_windows_callback) end if ret==WIN_FALSE system_error "EnumWindows" end nil end |
.find_all_by_text(text) ⇒ Object
returns all WinWindow objects found whose text matches what is given
May raise a WinWindow::SystemError from WinWindow.each_window
1286 1287 1288 1289 1290 |
# File 'lib/winwindow.rb', line 1286 def self.find_all_by_text(text) WinWindow::All.select do |window| text===window.text # use triple-equals so regexps try to match, strings see if equal end end |
.find_first_by_text(text) ⇒ Object
returns the first window found whose text matches what is given
May raise a WinWindow::SystemError from WinWindow.each_window
1277 1278 1279 1280 1281 |
# File 'lib/winwindow.rb', line 1277 def self.find_first_by_text(text) WinWindow::All.detect do |window| text===window.text # use triple-equals so regexps try to match, strings see if equal end end |
.find_only_by_text(text) ⇒ Object
returns the only window matching the given text. raises a WinWindow::MatchError if more than one window matching given text is found, so that you can be sure you are returned the right one (because it’s the only one)
behavior is slightly more complex than that - if multiple windows match the given text, but are all in one heirarchy (all parents/children of each other), then this returns the highest one in the heirarchy.
if there are multiple windows with titles that match which are all in a parent/child relationship with each other, this will not error and will return the innermost child whose text matches.
May also raise a WinWindow::SystemError from WinWindow.each_window
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 |
# File 'lib/winwindow.rb', line 1305 def self.find_only_by_text(text) matched=WinWindow::All.select do |window| text===window.text end # matched.reject! do |win| # reject win where # matched.any? do |other_win| # exists any other_win # parent=other_win.parent # win_is_parent=false # while parent && !win_is_parent # win_is_parent ||= win==parent # parent=parent.parent # end # win_is_parent # such that win is parent of other_win # end # end matched.reject! do |win| # reject any win where matched.any? do |other_win| # any other_win parent=win.parent other_is_parent=false while parent && !other_is_parent other_is_parent ||= other_win==parent parent=parent.parent end other_is_parent # is its parent end end if matched.size != 1 raise MatchError, "Found #{matched.size} windows matching #{text.inspect}; there should be one" else return matched.first end end |
.foreground_window ⇒ Object
Returns a WinWindow representing the current foreground window (the window with which the user is currently working).
1343 1344 1345 1346 1347 1348 1349 1350 |
# File 'lib/winwindow.rb', line 1343 def self.foreground_window hwnd=WinUser.GetForegroundWindow if hwnd == 0 nil else self.new(hwnd) end end |
.handle_options(given_options, default_options, other_allowed_keys = []) ⇒ Object
takes given options and default options, and optionally a list of additional allowed keys not specified in default options (this is useful when you want to pass options along to another function but don’t want to specify a default that will clobber that function’s default) raises ArgumentError if the given options have an invalid key (defined as one not specified in default options or other_allowed_keys), and sets default values in given options where nothing is set.
10 11 12 13 14 15 16 17 18 19 |
# File 'lib/winwindow/ext.rb', line 10 def self.(, , other_allowed_keys=[]) # :nodoc: =.dup unless (unknown_keys=(.keys-.keys-other_allowed_keys)).empty? raise ArgumentError, "Unknown options: #{(.keys-.keys).map(&:inspect).join(', ')}. Known options are #{(.keys+other_allowed_keys).map(&:inspect).join(', ')}" end (.keys-.keys).each do |key| [key]=[key] end end |
.lock_set_foreground_window ⇒ Object
The foreground process can call the #lock_set_foreground_window function to disable calls to the #set_foreground! function.
Disables calls to #set_foreground!
675 676 677 678 |
# File 'lib/winwindow.rb', line 675 def self.lock_set_foreground_window ret= WinUser.LockSetForegroundWindow(LSFW_LOCK) ret != WIN_FALSE # todo: raise system error? end |
.unlock_set_foreground_window ⇒ Object
The foreground process can call the #lock_set_foreground_window function to disable calls to the #set_foreground! function.
Enables calls to #set_foreground!
685 686 687 688 |
# File 'lib/winwindow.rb', line 685 def self.unlock_set_foreground_window ret= WinUser.LockSetForegroundWindow(LSFW_UNLOCK) ret != WIN_FALSE # todo: raise system error? end |
Instance Method Details
#ancestor_parent ⇒ Object
Retrieves the parent window. This does not include the owner, as it does with #parent
494 495 496 497 |
# File 'lib/winwindow.rb', line 494 def ancestor_parent ret_hwnd=WinUser.GetAncestor(hwnd, GA_PARENT) @ancestor_parent= ret_hwnd > 0 ? self.class.new(ret_hwnd) : nil end |
#ancestor_root ⇒ Object
Retrieves the root window by walking the chain of parent windows.
502 503 504 505 |
# File 'lib/winwindow.rb', line 502 def ancestor_root ret_hwnd=WinUser.GetAncestor(hwnd, GA_ROOT) @ancestor_root= ret_hwnd > 0 ? self.class.new(ret_hwnd) : nil end |
#ancestor_root_owner ⇒ Object
Retrieves the owned root window by walking the chain of parent and owner windows returned by GetParent.
511 512 513 514 |
# File 'lib/winwindow.rb', line 511 def ancestor_root_owner ret_hwnd=WinUser.GetAncestor(hwnd, GA_ROOTOWNER) @ancestor_root_owner= ret_hwnd > 0 ? self.class.new(ret_hwnd) : nil end |
#bring_to_top! ⇒ Object
brings the window to the top of the Z order. If the window is a top-level window, it is activated. If the window is a child window, the top-level parent window associated with the child window is activated.
738 739 740 741 |
# File 'lib/winwindow.rb', line 738 def bring_to_top! ret=WinUser.BringWindowToTop(hwnd) ret != WIN_FALSE end |
#capture_to_bmp_blob(options = {}) ⇒ Object
captures this window to a bitmap image (a screenshot).
Returns the bitmap as represented by a blob (a string) of bitmap data, including the BITMAPFILEHEADER, BITMAPINFOHEADER, and data. This can be written directly to a file (though if you want that, #capture_to_bmp_file is probably what you want), or passed to ImageMagick, or whatever you like.
takes an options hash. see the documentation on #capture_to_bmp_structs for what options are accepted.
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 |
# File 'lib/winwindow.rb', line 1058 def capture_to_bmp_blob(={}) capture_to_bmp_structs().map do |struct| if struct.is_a?(FFI::Pointer) ptr=struct size=ptr.size else ptr=struct.to_ptr size=struct.class.real_size end ptr.get_bytes(0, size) end.join("") end |
#capture_to_bmp_file(filename, options = {}) ⇒ Object
captures this window to a bitmap image (a screenshot).
stores the bitmap to a filename specified in the first argument.
takes an options hash. see the documentation on #capture_to_bmp_structs for what options are accepted.
1077 1078 1079 1080 1081 |
# File 'lib/winwindow.rb', line 1077 def capture_to_bmp_file(filename, ={}) File.open(filename, 'wb') do |file| file.write(capture_to_bmp_blob()) end end |
#capture_to_bmp_structs(options = {}) ⇒ Object
Creates a bitmap image of this window (a screenshot).
Returns the bitmap as represented by three FFI objects: a BITMAPFILEHEADER, a BITMAPINFOHEADER, and a pointer to actual bitmap data.
See also #capture_to_bmp_blob and #capture_to_bmp_file - probably more useful to the user than this method.
takes an options hash:
-
:dc => what device context to use
-
:client - captures the client area, which excludes window trimmings like title bar, resize bars, etc.
-
:window (default) - capturse the window area, including window trimmings.
-
-
:set_foreground => whether to try to set this to be the foreground
-
true - calls to #set_foreground!
-
false - doesn’t call to any functions to set this to be the foreground
-
:really (default) - calls to #really_set_foreground!. this is the default because really being in the foreground is rather important when taking a screenshot.
-
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 |
# File 'lib/winwindow.rb', line 968 def capture_to_bmp_structs(={}) =(, :dc => :window, :set_foreground => :really) case [:set_foreground] when :really really_set_foreground! when true set_foreground! when false,nil else raise ArgumentError, ":set_foreground option is invalid. expected values are :really, true, or false/nil. received #{[:set_foreground]} (#{[:set_foreground].class})" end if [:set_foreground] # if setting foreground, sleep a tick - sometimes it still hasn't show up even when it is # the foreground window; sometimes it's still only partway-drawn sleep 0.2 end case [:dc] when :client rect=self.client_rect dc=WinUser.GetDC(hwnd) || system_error("GetDC") when :window rect=self.window_rect dc=WinUser.GetWindowDC(hwnd) || system_error("GetWindowDC") else raise ArgumentError, ":dc option is invalid. expected values are :client or :window; received #{[:dc]} (#{[:dc].class})" end width=rect[:right]-rect[:left] height=rect[:bottom]-rect[:top] begin dc_mem = WinGDI.CreateCompatibleDC(dc) || system_error("CreateCompatibleDC") begin bmp = WinGDI.CreateCompatibleBitmap(dc, width, height) || system_error("CreateCompatibleBitmap") begin WinGDI.SelectObject(dc_mem, bmp) || system_error("SelectObject") WinGDI.BitBlt(dc_mem, 0, 0, width, height, dc, 0, 0, SRCCOPY) || system_error("BitBlt") bytes_per_pixel=3 bmp_info=WinGDI::BITMAPINFOHEADER.new { :Size => WinGDI::BITMAPINFOHEADER.real_size, # 40 :Width => width, :Height => height, :Planes => 1, :BitCount => bytes_per_pixel*8, :Compression => 0, :SizeImage => 0, :XPelsPerMeter => 0, :YPelsPerMeter => 0, :ClrUsed => 0, :ClrImportant => 0, }.each_pair do |key,val| bmp_info[key]=val end bmp_row_size=width*bytes_per_pixel bmp_row_size+=bmp_row_size%4 # row size must be a multiple of 4 (size of a dword) bmp_size=bmp_row_size*height bits=FFI::MemoryPointer.new(1, bmp_size) WinGDI.GetDIBits(dc_mem, bmp, 0, height, bits, bmp_info, DIB_RGB_COLORS) || system_error("GetDIBits") bmp_file_header=WinGDI::BITMAPFILEHEADER.new { :Type => 'BM'.unpack('S').first, # must be 'BM' :Size => WinGDI::BITMAPFILEHEADER.real_size + WinGDI::BITMAPINFOHEADER.real_size + bmp_size, :Reserved1 => 0, :Reserved2 => 0, :OffBits => WinGDI::BITMAPFILEHEADER.real_size + WinGDI::BITMAPINFOHEADER.real_size }.each_pair do |key,val| bmp_file_header[key]=val end return [bmp_file_header, bmp_info, bits] ensure WinGDI.DeleteObject(bmp) end ensure WinGDI.DeleteDC(dc_mem) end ensure WinUser.ReleaseDC(hwnd, dc) end end |
#child_button(button_text) ⇒ Object
returns a WinWindow that is a child of this that matches the given button_text (Regexp or #to_s-able) or nil if no such child exists.
“&” is stripped when matching so don’t include it. String comparison is case-insensitive.
May raise a WinWindow::SystemError from #each_child
1216 1217 1218 1219 1220 |
# File 'lib/winwindow.rb', line 1216 def () children.detect do |child| child.class_name=='Button' && .is_a?(Regexp) ? child.text.tr('&', '') =~ : child.text.tr('&', '').downcase==.to_s.tr('&', '').downcase end end |
#child_control_with_preceding_label(preceding_label_text, options = {}) ⇒ Object
Finds a child of this window which follows a label with the given text.
Options:
-
:control_class_name is the class name of the control you are looking for. Defaults to nil, which accepts any class name.
-
:label_class_name is the class name of the label preceding the control you are looking for. Defaults to ‘Static’
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 |
# File 'lib/winwindow.rb', line 1229 def child_control_with_preceding_label(preceding_label_text, ={}) =(, :control_class_name => nil, :label_class_name => "Static") prev_was_label=false control=self.children.detect do |child| ret=prev_was_label && (![:control_class_name] || child.class_name==[:control_class_name]) prev_was_label= child.class_name==[:label_class_name] && preceding_label_text===child.text ret end end |
#child_of?(parent) ⇒ Boolean
tests whether a window is a child window or descendant window of a specified parent window. A child window is the direct descendant of a specified parent window if that parent window is in the chain of parent windows; the chain of parent windows leads from the original overlapped or pop-up window to the child window.
556 557 558 559 560 |
# File 'lib/winwindow.rb', line 556 def child_of?(parent) parent_hwnd= parent.is_a?(self.class) ? parent.hwnd : parent child=WinUser.IsChild(parent_hwnd, hwnd) child!=WIN_FALSE end |
#children ⇒ Object
returns an Enumerable object that can iterate over each child of this window, yielding a WinWindow object
may raise a WinWindow::SystemError from #each_child
1135 1136 1137 |
# File 'lib/winwindow.rb', line 1135 def children Enumerator.new(self, :each_child) end |
#children_recursive(options = {}) ⇒ Object
returns an Enumerable object that can iterate over each child of this window recursively, yielding a WinWindow object for each child.
1162 1163 1164 |
# File 'lib/winwindow.rb', line 1162 def children_recursive(={}) Enumerator.new(self, :recurse_each_child, ) end |
#class_name ⇒ Object
retrieves the name of the class to which this window belongs
576 577 578 579 580 581 |
# File 'lib/winwindow.rb', line 576 def class_name buff_size=256 buff=" "*buff_size len=WinUser.GetClassNameA(hwnd, buff, buff_size) @class_name=buff.to_s[0...len] end |
#click! ⇒ Object
tries to click on this Window (using PostMessage sending BM_CLICK message).
Clicking might not always work! Especially if the window is not focused (frontmost application). The BM_CLICK message might just be ignored, or maybe it will just focus the hwnd but not really click.
910 911 912 |
# File 'lib/winwindow.rb', line 910 def click! WinUser.PostMessageA(hwnd, BM_CLICK, 0, nil) end |
#click_child_button_try_for!(button_text, time, options = {}) ⇒ Object
Give the name of a button, or a Regexp to match it (see #child_button). keeps clicking the button until the button no longer exists, or until the given block is true (ie, not false or nil)
Options:
-
:interval is the length of time in seconds between each attempt (default 0.05)
-
:set_foreground is whether the window should be activated first, since button-clicking is much more likely to fail if the window isn’t focused (default true)
-
:exception is the exception class or instance that will be raised if we can’t click the button (default nil, no exception is raised, the return value indicates success/failure)
Raises ArgumentError if invalid options are given. Raises a WinWindow::NotExistsError if the button doesn’t exist, or if this window doesn’t exist, or a WinWindow::SystemError if a System Error occurs (from #each_child)
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 |
# File 'lib/winwindow.rb', line 1194 def (, time, ={}) =(, {:set_foreground => true, :exception => nil, :interval => 0.05}) =() || (raise WinWindow::NotExistsError, "Button #{.inspect} not found") ={} [:condition]=proc{!.exists? || (block_given? && yield)} .merge!(.reject{|k,v| ![:exception, :interval].include?(k)}) Waiter.try_for(time, ) do if [:set_foreground] show_normal! really_set_foreground! end .click! end return [:condition].call end |
#client_rect ⇒ Object
Returns a Rect struct with members left, top, right, and bottom indicating the coordinates of a window’s client area. The client coordinates specify the upper-left and lower-right corners of the client area. Because client coordinates are relative to the upper-left corner of a window’s client area, the coordinates of the upper-left corner are (0,0).
934 935 936 937 938 939 940 941 942 |
# File 'lib/winwindow.rb', line 934 def client_rect rect=WinUser::Rect.new ret=WinUser.GetClientRect(hwnd, rect) if ret==WIN_FALSE self.class.system_error "GetClientRect" else rect end end |
#close! ⇒ Object
minimizes this window (but does not destroy it) (why is it called close? I don’t know)
747 748 749 750 |
# File 'lib/winwindow.rb', line 747 def close! ret=WinUser.CloseWindow(hwnd) ret != WIN_FALSE end |
#destroy! ⇒ Object
destroy! destroys the window. #destroy! sends WM_DESTROY and WM_NCDESTROY messages to the window to deactivate it and remove the keyboard focus from it. #destroy! also destroys the window’s menu, flushes the thread message queue, destroys timers, removes clipboard ownership, and breaks the clipboard viewer chain (if the window is at the top of the viewer chain).
If the specified window is a parent or owner window, #destroy! automatically destroys the associated child or owned windows when it destroys the parent or owner window. #destroy! first destroys child or owned windows, and then it destroys the parent or owner window. #destroy! also destroys modeless dialog boxes.
876 877 878 879 |
# File 'lib/winwindow.rb', line 876 def destroy! ret=WinUser.DestroyWindow(hwnd) ret != WIN_FALSE end |
#each_child ⇒ Object
iterates over each child, yielding a WinWindow object.
raises a WinWindow::NotExistsError if the window does not exist, or a WinWindow::SystemError if a System Error errors.
use #children to get an Enumerable object.
msdn.microsoft.com/en-us/library/ms633494(VS.85).aspx
For System Error Codes see msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 |
# File 'lib/winwindow.rb', line 1111 def each_child raise WinWindow::NotExistsError, "Window does not exist! Cannot enumerate children." unless exists? enum_child_windows_callback= WinUser.window_enum_callback do |chwnd, lparam| yield WinWindow.new(chwnd) WIN_TRUE end begin ret=WinUser.EnumChildWindows(hwnd, enum_child_windows_callback, nil) ensure WinUser.remove_window_enum_callback(enum_child_windows_callback) end if ret==0 self.class.system_error("EnumChildWindows") # actually, EnumChildWindows doesn't say anything about return value indicating error encountered. # Although EnumWindows does, so it seems sort of safe to assume that would apply here too. # but, maybe not - so, should we raise an error here? end nil end |
#enabled_popup ⇒ Object
The retrieved handle identifies the enabled popup window owned by the specified window (the search uses the first such window found using GW_HWNDNEXT); otherwise, if there are no enabled popup windows, nil is returned.
478 479 480 481 |
# File 'lib/winwindow.rb', line 478 def enabled_popup popup_hwnd=WinUser.GetWindow(hwnd, GW_ENABLEDPOPUP) @enabled_popup= popup_hwnd > 0 && popup_hwnd != self.hwnd ? self.class.new(popup_hwnd) : nil end |
#end_task!(force = false) ⇒ Object
called to forcibly close the window.
the argument force, if true, will force the destruction of the window if an initial attempt fails to gently close the window using WM_CLOSE.
if false, only the close with WM_CLOSE is attempted
889 890 891 892 |
# File 'lib/winwindow.rb', line 889 def end_task!(force=false) ret=WinUser.EndTask(hwnd, 0, force ? WIN_TRUE : WIN_FALSE) ret != WIN_FALSE end |
#eql?(oth) ⇒ Boolean Also known as: ==
true if comparing an object of the same class with the same hwnd (integer)
1167 1168 1169 |
# File 'lib/winwindow.rb', line 1167 def eql?(oth) oth.class==self.class && oth.hwnd==self.hwnd end |
#exists? ⇒ Boolean
determines whether the specified window handle identifies an existing window
612 613 614 615 |
# File 'lib/winwindow.rb', line 612 def exists? ret=WinUser.IsWindow(hwnd) ret != WIN_FALSE end |
#force_minimize! ⇒ Object
Windows 2000/XP: Minimizes the window, even if the thread that owns the window is not responding. This should only be used when minimizing windows from a different thread.
860 861 862 863 |
# File 'lib/winwindow.rb', line 860 def force_minimize! ret=WinUser.ShowWindow(hwnd, SW_FORCEMINIMIZE) ret != WIN_FALSE end |
#foreground? ⇒ Boolean
returns true if this is the same Window that is returned from WinWindow.foreground_window
660 661 662 |
# File 'lib/winwindow.rb', line 660 def foreground? self==self.class.foreground_window end |
#handle_options(*args) ⇒ Object
:nodoc:
21 22 23 |
# File 'lib/winwindow/ext.rb', line 21 def (*args) # :nodoc: self.class.(*args) end |
#hash ⇒ Object
:nodoc:
1172 1173 1174 |
# File 'lib/winwindow.rb', line 1172 def hash # :nodoc: [self.class, self.hwnd].hash end |
#hide! ⇒ Object
Hides the window and activates another window.
755 756 757 758 |
# File 'lib/winwindow.rb', line 755 def hide! ret=WinUser.ShowWindow(hwnd, SW_HIDE) ret != WIN_FALSE end |
#hung_app? ⇒ Boolean
determine if Microsoft Windows considers that a specified application is not responding. An application is considered to be not responding if it is not waiting for input, is not in startup processing, and has not called PeekMessage within the internal timeout period of 5 seconds.
568 569 570 571 |
# File 'lib/winwindow.rb', line 568 def hung_app? hung=WinUser.IsHungAppWindow(hwnd) hung != WIN_FALSE end |
#iconic? ⇒ Boolean Also known as: minimized?
whether the window is minimized (iconic).
628 629 630 631 |
# File 'lib/winwindow.rb', line 628 def iconic? ret=WinUser.IsIconic(hwnd) ret != WIN_FALSE end |
#inspect ⇒ Object
402 403 404 405 406 |
# File 'lib/winwindow.rb', line 402 def inspect retrieve_text class_name Object.instance_method(:inspect).bind(self).call end |
#last_active_popup ⇒ Object
determines which pop-up window owned by this window was most recently active
519 520 521 522 |
# File 'lib/winwindow.rb', line 519 def last_active_popup ret_hwnd=WinUser.GetLastActivePopup(hwnd) @last_active_popup= ret_hwnd > 0 ? self.class.new(ret_hwnd) : nil end |
#maximize! ⇒ Object
Maximizes this window. (note: exact same as show_maximized!)
789 790 791 792 |
# File 'lib/winwindow.rb', line 789 def maximize! ret=WinUser.ShowWindow(hwnd, SW_MAXIMIZE) ret != WIN_FALSE end |
#minimize! ⇒ Object
Minimizes this window and activates the next top-level window in the Z order.
814 815 816 817 |
# File 'lib/winwindow.rb', line 814 def minimize! ret=WinUser.ShowWindow(hwnd, SW_MINIMIZE) ret != WIN_FALSE end |
#owner ⇒ Object
The retrieved handle identifies the specified window’s owner window, if any.
486 487 488 489 |
# File 'lib/winwindow.rb', line 486 def owner owner_hwnd=WinUser.GetWindow(hwnd, GW_OWNER) @owner= owner_hwnd > 0 ? self.class.new(owner_hwnd) : nil end |
#parent ⇒ Object
retrieves a handle to this window’s parent or owner
536 537 538 539 |
# File 'lib/winwindow.rb', line 536 def parent parent_hwnd=WinUser.GetParent(hwnd) @parent= parent_hwnd > 0 ? self.class.new(parent_hwnd) : nil end |
#pretty_print(pp) ⇒ Object
408 409 410 411 412 |
# File 'lib/winwindow.rb', line 408 def pretty_print(pp) retrieve_text class_name pp.pp_object(self) end |
#process_id ⇒ Object
returns the process identifier that created this window
603 604 605 606 607 |
# File 'lib/winwindow.rb', line 603 def process_id lpdwProcessId=FFI::MemoryPointer.new(Types[:LPDWORD]) WinUser.GetWindowThreadProcessId(hwnd, lpdwProcessId) lpdwProcessId.get_ulong(0) end |
#real_class_name ⇒ Object
retrieves a string that specifies the window type
586 587 588 589 590 591 |
# File 'lib/winwindow.rb', line 586 def real_class_name buff_size=256 buff=" "*buff_size len=WinUser.RealGetWindowClassA(hwnd, buff, buff_size) @real_class_name=buff.to_s[0...len] end |
#really_set_foreground!(options = {}) ⇒ Object
really sets this to be the foreground window.
-
restores the window if it’s iconic.
-
attempts to circumvent a lock disabling calls made by set_foreground!
-
then calls set_foreground!, which should then work with that lock disabled. tries this for a few seconds, checking if it was successful.
if you want it to raise an exception if it can’t set the foreground window, pass :error => true (default is false)
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 |
# File 'lib/winwindow.rb', line 705 def really_set_foreground!(={}) =(, :error => false) try_harder=false =WinUser.MapVirtualKeyA(VK_MENU, 0) Waiter.try_for(2, :exception => ([:error] && WinWindow::Error.new("Failed to set foreground window"))) do if iconic? restore! end if try_harder # Simulate two single ALT keystrokes in order to deactivate lock on SetForeGroundWindow before we call it. # See LockSetForegroundWindow, http://msdn.microsoft.com/en-us/library/ms633532(VS.85).aspx # also keybd_event, see http://msdn.microsoft.com/en-us/library/ms646304(VS.85).aspx # # this idea is taken from AutoIt's setforegroundwinex.cpp in SetForegroundWinEx::Activate(HWND hWnd) # keybd_event((BYTE)VK_MENU, MapVirtualKey(VK_MENU, 0), 0, 0); # keybd_event((BYTE)VK_MENU, MapVirtualKey(VK_MENU, 0), KEYEVENTF_KEYUP, 0); 2.times do ret=WinUser.keybd_event(VK_MENU, , KEYEVENTF_KEYDOWN, nil) ret=WinUser.keybd_event(VK_MENU, , KEYEVENTF_KEYUP, nil) end else try_harder=true end set_foreground! foreground? end end |
#recurse_each_child(options = {}) ⇒ Object
iterates over each child recursively, yielding a WinWindow object for each child.
raises a WinWindow::NotExistsError if the window does not exist, or a WinWindow::SystemError if a System Error errors.
use #children_recursive to get an Enumerable object.
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 |
# File 'lib/winwindow.rb', line 1145 def recurse_each_child(={}) =(, :rescue_enum_child_windows => true) ycomb do |recurse| proc do |win_window| yield win_window begin win_window.each_child do |child_window| recurse.call child_window end rescue SystemError raise unless [:rescue_enum_child_windows] && $!.function=='EnumChildWindows' end end end.call(self) end |
#restore! ⇒ Object
Activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should use this when restoring a minimized window.
842 843 844 845 |
# File 'lib/winwindow.rb', line 842 def restore! ret=WinUser.ShowWindow(hwnd, SW_RESTORE) ret != WIN_FALSE end |
#retrieve_text ⇒ Object
This is similar to #text that one is GetWindowText(hwnd) this one is SendMessage(hwnd, WM_GETTEXT) differences are documented here: msdn.microsoft.com/en-us/magazine/cc301438.aspx and here: blogs.msdn.com/oldnewthing/archive/2003/08/21/54675.aspx
442 443 444 445 446 447 |
# File 'lib/winwindow.rb', line 442 def retrieve_text buff_size=retrieve_text_length+1 buff=" "*buff_size len= WinUser.SendMessageA(hwnd, WM_GETTEXT, buff_size, buff) @text=buff[0...len] end |
#retrieve_text_length ⇒ Object
similar to #text_length; differences between that and this are the same as between #text and #retrieve_text
451 452 453 454 |
# File 'lib/winwindow.rb', line 451 def retrieve_text_length len= WinUser.SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, nil) len end |
#send_close! ⇒ Object
sends notification that the window should close. returns nil (we get no indication of success or failure).
898 899 900 901 902 903 |
# File 'lib/winwindow.rb', line 898 def send_close! buff_size=0 buff="" len=WinUser.SendMessageA(hwnd, WM_CLOSE, buff_size, buff) nil end |
#send_set_text!(text) ⇒ Object
sets text by sending WM_SETTEXT message. this different than #set_text! in the same way that #retrieve_text is different than #text
468 469 470 471 |
# File 'lib/winwindow.rb', line 468 def send_set_text!(text) ret=WinUser.SendMessageA(hwnd, WM_SETTEXT, 0, text.dup) nil end |
#set_foreground! ⇒ Object
puts the thread that created the specified window into the foreground and activates the window. Keyboard input is directed to the window, and various visual cues are changed for the user. The system assigns a slightly higher priority to the thread that created the foreground window than it does to other threads.
If the window was brought to the foreground, the return value is true.
If the window was not brought to the foreground, the return value is false.
654 655 656 657 |
# File 'lib/winwindow.rb', line 654 def set_foreground! ret= WinUser.SetForegroundWindow(hwnd) ret != WIN_FALSE end |
#set_parent!(parent) ⇒ Object
changes the parent window of this child window
544 545 546 547 548 |
# File 'lib/winwindow.rb', line 544 def set_parent!(parent) parent_hwnd= parent.is_a?(self.class) ? parent.hwnd : parent new_parent=WinUser.SetParent(hwnd, parent_hwnd) new_parent > 0 ? self.class.new(new_parent) : nil end |
#set_text!(text) ⇒ Object
changes the text of the specified window’s title bar (if it has one). If the specified window is a control, the text of the control is changed. However, #set_text! cannot change the text of a control in another application (see #send_set_text!)
461 462 463 464 |
# File 'lib/winwindow.rb', line 461 def set_text!(text) set=WinUser.SetWindowTextA(hwnd, text) set != WIN_FALSE end |
#show! ⇒ Object
Activates the window and displays it in its current size and position.
806 807 808 809 |
# File 'lib/winwindow.rb', line 806 def show! ret=WinUser.ShowWindow(hwnd, SW_SHOW) ret != WIN_FALSE end |
#show_default! ⇒ Object
Sets the show state based on the SW_ value specified in the STARTUPINFO structure passed to the CreateProcess function by the program that started the application.
851 852 853 854 |
# File 'lib/winwindow.rb', line 851 def show_default! ret=WinUser.ShowWindow(hwnd, SW_SHOWDEFAULT) ret != WIN_FALSE end |
#show_maximized! ⇒ Object
Activates the window and displays it as a maximized window. (note: exact same as maximize!)
781 782 783 784 |
# File 'lib/winwindow.rb', line 781 def show_maximized! ret=WinUser.ShowWindow(hwnd, SW_SHOWMAXIMIZED) ret != WIN_FALSE end |
#show_min_no_active! ⇒ Object
Displays the window as a minimized window. This is similar to show_minimized!, except the window is not activated.
823 824 825 826 |
# File 'lib/winwindow.rb', line 823 def show_min_no_active! ret=WinUser.ShowWindow(hwnd, SW_SHOWMINNOACTIVE) ret != WIN_FALSE end |
#show_minimized! ⇒ Object
Activates the window and displays it as a minimized window.
773 774 775 776 |
# File 'lib/winwindow.rb', line 773 def show_minimized! ret=WinUser.ShowWindow(hwnd, SW_SHOWMINIMIZED) ret != WIN_FALSE end |
#show_na! ⇒ Object
Displays the window in its current size and position. This is similar to show!, except the window is not activated.
832 833 834 835 |
# File 'lib/winwindow.rb', line 832 def show_na! ret=WinUser.ShowWindow(hwnd, SW_SHOWNA) ret != WIN_FALSE end |
#show_no_activate! ⇒ Object
Displays the window in its most recent size and position. This is similar to show_normal!, except the window is not actived.
798 799 800 801 |
# File 'lib/winwindow.rb', line 798 def show_no_activate! ret=WinUser.ShowWindow(hwnd, SW_SHOWNOACTIVATE) ret != WIN_FALSE end |
#show_normal! ⇒ Object
Activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag when displaying the window for the first time.
765 766 767 768 |
# File 'lib/winwindow.rb', line 765 def show_normal! ret=WinUser.ShowWindow(hwnd, SW_SHOWNORMAL) ret != WIN_FALSE end |
#switch_to!(alt_tab = false) ⇒ Object
switch focus and bring to the foreground
the argument alt_tab, if true, indicates that the window is being switched to using the Alt/Ctl+Tab key sequence. This argument should be false otherwise.
640 641 642 |
# File 'lib/winwindow.rb', line 640 def switch_to!(alt_tab=false) WinUser.SwitchToThisWindow(hwnd, alt_tab ? WIN_TRUE : WIN_FALSE) end |
#text ⇒ Object
retrieves the text of this window’s title bar (if it has one). If this is a control, the text of the control is retrieved. However, #text cannot retrieve the text of a control in another application (see #retrieve_text)
419 420 421 422 423 424 |
# File 'lib/winwindow.rb', line 419 def text buff_size=text_length+1 buff="\001"*buff_size len= WinUser.GetWindowTextA(hwnd, buff, buff_size) @text=buff[0...len] end |
#text_length ⇒ Object
length of the window text, see #text
similar to #text, cannot retrieve the text of a control in another application - see #retrieve_text, #retrieve_text_length
432 433 434 435 |
# File 'lib/winwindow.rb', line 432 def text_length len= WinUser.GetWindowTextLengthA(hwnd) len end |
#thread_id ⇒ Object
returns the identifier of the thread that created the window
596 597 598 |
# File 'lib/winwindow.rb', line 596 def thread_id WinUser.GetWindowThreadProcessId(hwnd, nil) end |
#top_window ⇒ Object
examines the Z order of the child windows associated with self and retrieves a handle to the child window at the top of the Z order
528 529 530 531 |
# File 'lib/winwindow.rb', line 528 def top_window ret_hwnd= WinUser.GetTopWindow(hwnd) @top_window= ret_hwnd > 0 ? self.class.new(ret_hwnd) : nil end |
#visible? ⇒ Boolean
visibility state of the specified window
620 621 622 623 |
# File 'lib/winwindow.rb', line 620 def visible? ret=WinUser.IsWindowVisible(hwnd) ret != WIN_FALSE end |
#window_rect ⇒ Object
Returns a Rect struct with members left, top, right, and bottom indicating the dimensions of the bounding rectangle of the specified window. The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen.
919 920 921 922 923 924 925 926 927 |
# File 'lib/winwindow.rb', line 919 def window_rect rect=WinUser::Rect.new ret=WinUser.GetWindowRect(hwnd, rect) if ret==WIN_FALSE self.class.system_error "GetWindowRect" else rect end end |