win_gui 0.2.17 → 0.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY +4 -0
 - data/README.rdoc +11 -12
 - data/VERSION +1 -1
 - data/lib/win_gui/window.rb +44 -19
 - data/spec/win_gui/window_spec.rb +148 -114
 - metadata +4 -4
 
    
        data/HISTORY
    CHANGED
    
    
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -7,7 +7,8 @@ url:: http://github.com/arvicco/win_gui 
     | 
|
| 
       7 
7 
     | 
    
         
             
            WinGui is a module that provides higher-level abstractions/wrappers around GUI-related
         
     | 
| 
       8 
8 
     | 
    
         
             
            Win32 API functions. It uses Win gem as a basis, which in turn uses FFI.
         
     | 
| 
       9 
9 
     | 
    
         
             
            So (in theory) it should work for any Ruby implementation supporting FFI. In practice,
         
     | 
| 
       10 
     | 
    
         
            -
            it's only been tested under mingw and cygwin flavors of Ruby 1.9. 
     | 
| 
      
 10 
     | 
    
         
            +
            it's only been tested under mingw and cygwin flavors of Ruby 1.9. Porting to JRuby is
         
     | 
| 
      
 11 
     | 
    
         
            +
            under way, waiting for its 1.9 compatibility to mature.
         
     | 
| 
       11 
12 
     | 
    
         | 
| 
       12 
13 
     | 
    
         
             
            == SUMMARY:
         
     | 
| 
       13 
14 
     | 
    
         | 
| 
         @@ -32,26 +33,24 @@ For example, here is how you deal with typical GUI-related tasks using Win: 
     | 
|
| 
       32 
33 
     | 
    
         
             
              end
         
     | 
| 
       33 
34 
     | 
    
         
             
              close_window(window_handle)
         
     | 
| 
       34 
35 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
      
 36 
     | 
    
         
            +
            This works fine, but such functional style is does not feel like object-oriented Ruby.
         
     | 
| 
      
 37 
     | 
    
         
            +
            Ideally, there should be a thin wrapper class around window handle, and the code above
         
     | 
| 
      
 38 
     | 
    
         
            +
            should be more like this:
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
       36 
40 
     | 
    
         
             
              require 'win_gui'
         
     | 
| 
       37 
41 
     | 
    
         
             
              include WinGui
         
     | 
| 
       38 
42 
     | 
    
         | 
| 
       39 
     | 
    
         
            -
              window = Window.find(: 
     | 
| 
      
 43 
     | 
    
         
            +
              window = Window.find(:title => /PartTitle/)
         
     | 
| 
       40 
44 
     | 
    
         
             
              puts window.handle, window.title, window.thread, window.process
         
     | 
| 
       41 
     | 
    
         
            -
              window. 
     | 
| 
      
 45 
     | 
    
         
            +
              window.children.each {|child| puts child.handle, child.title, child.thread, child.process }
         
     | 
| 
       42 
46 
     | 
    
         
             
              window.close
         
     | 
| 
       43 
47 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
            Windows GUI-related code much more fun than it is right now.
         
     | 
| 
      
 48 
     | 
    
         
            +
            WinGui library strives to provide such wrappers and convenience methods that will make
         
     | 
| 
      
 49 
     | 
    
         
            +
            working with Windows GUI-related code much more fun than it is right now.
         
     | 
| 
       46 
50 
     | 
    
         | 
| 
       47 
51 
     | 
    
         
             
            == REQUIREMENTS:
         
     | 
| 
       48 
52 
     | 
    
         | 
| 
       49 
     | 
    
         
            -
            Only works with Ruby 1.9 
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
            == FEATURES/PROBLEMS:
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
            This project is quite new, so it may be not suitable for production-quality systems yet.
         
     | 
| 
       54 
     | 
    
         
            -
            Contributors always welcome!
         
     | 
| 
      
 53 
     | 
    
         
            +
            Only works with Ruby 1.9 compatible implementations since Win gem uses some of latest Ruby features.
         
     | 
| 
       55 
54 
     | 
    
         | 
| 
       56 
55 
     | 
    
         
             
            == INSTALL:
         
     | 
| 
       57 
56 
     | 
    
         | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0.2. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.2.18
         
     | 
    
        data/lib/win_gui/window.rb
    CHANGED
    
    | 
         @@ -14,7 +14,7 @@ module WinGui 
     | 
|
| 
       14 
14 
     | 
    
         
             
                  # Returns either Window instance (for a found handle) or nil if nothing found.
         
     | 
| 
       15 
15 
     | 
    
         
             
                  # Private method to dry up other window lookup methods
         
     | 
| 
       16 
16 
     | 
    
         
             
                  #
         
     | 
| 
       17 
     | 
    
         
            -
                  def lookup_window 
     | 
| 
      
 17 
     | 
    
         
            +
                  def lookup_window opts # :yields: index, position
         
     | 
| 
       18 
18 
     | 
    
         
             
                    # Need this to avoid handle considered local var in begin..end block
         
     | 
| 
       19 
19 
     | 
    
         
             
                    handle = yield
         
     | 
| 
       20 
20 
     | 
    
         
             
                    if opts[:timeout]
         
     | 
| 
         @@ -30,40 +30,63 @@ module WinGui 
     | 
|
| 
       30 
30 
     | 
    
         
             
                    Window.new(handle) if handle
         
     | 
| 
       31 
31 
     | 
    
         
             
                  end
         
     | 
| 
       32 
32 
     | 
    
         | 
| 
      
 33 
     | 
    
         
            +
                  def lookup_window_in_collection opts, &collection_proc
         
     | 
| 
      
 34 
     | 
    
         
            +
                    class_name   = opts[:class]
         
     | 
| 
      
 35 
     | 
    
         
            +
                    title        = opts[:title]
         
     | 
| 
      
 36 
     | 
    
         
            +
                    id           = opts[:id]
         
     | 
| 
      
 37 
     | 
    
         
            +
                    class_regexp = class_name.is_a? Regexp
         
     | 
| 
      
 38 
     | 
    
         
            +
                    title_regexp = title.is_a? Regexp
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    lookup_window(opts) do
         
     | 
| 
      
 41 
     | 
    
         
            +
                      collection_proc.call.each do |handle|
         
     | 
| 
      
 42 
     | 
    
         
            +
                        win         = Window.new handle
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                        id_match    = !id || win.id == id
         
     | 
| 
      
 45 
     | 
    
         
            +
                        title_match = !title || win.title == title ||
         
     | 
| 
      
 46 
     | 
    
         
            +
                            title_regexp && win.title =~ title
         
     | 
| 
      
 47 
     | 
    
         
            +
                        class_match = !class_name || win.class_name == class_name ||
         
     | 
| 
      
 48 
     | 
    
         
            +
                            class_regexp && win.class_name =~ class_name
         
     | 
| 
      
 49 
     | 
    
         
            +
                        return win if class_match && title_match && id_match
         
     | 
| 
      
 50 
     | 
    
         
            +
                      end
         
     | 
| 
      
 51 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       33 
55 
     | 
    
         
             
                  # Finds top level window by title/class, returns wrapped Window object or nil (raises exception if asked to).
         
     | 
| 
       34 
56 
     | 
    
         
             
                  # If timeout option given, waits for window to appear within timeout, returns nil if it didn't.
         
     | 
| 
       35 
57 
     | 
    
         
             
                  # Options:
         
     | 
| 
       36 
     | 
    
         
            -
                  # :title:: window title
         
     | 
| 
       37 
     | 
    
         
            -
                  # :class:: window class
         
     | 
| 
      
 58 
     | 
    
         
            +
                  # :title:: window title (String or Regexp)
         
     | 
| 
      
 59 
     | 
    
         
            +
                  # :class:: window class (String or Regexp)
         
     | 
| 
       38 
60 
     | 
    
         
             
                  # :timeout:: timeout (seconds)
         
     | 
| 
       39 
61 
     | 
    
         
             
                  # :raise:: raise this exception instead of returning nil if nothing found
         
     | 
| 
       40 
62 
     | 
    
         
             
                  #
         
     | 
| 
       41 
     | 
    
         
            -
                  def top_level 
     | 
| 
       42 
     | 
    
         
            -
                     
     | 
| 
      
 63 
     | 
    
         
            +
                  def top_level opts={}
         
     | 
| 
      
 64 
     | 
    
         
            +
                    if opts[:class].is_a?(Regexp) or opts[:title].is_a?(Regexp)
         
     | 
| 
      
 65 
     | 
    
         
            +
                      lookup_window_in_collection(opts) { WinGui.enum_windows }
         
     | 
| 
      
 66 
     | 
    
         
            +
                    else
         
     | 
| 
      
 67 
     | 
    
         
            +
                      lookup_window(opts) { WinGui.find_window opts[:class], opts[:title] }
         
     | 
| 
      
 68 
     | 
    
         
            +
                    end
         
     | 
| 
       43 
69 
     | 
    
         
             
                  end
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                  alias find top_level
         
     | 
| 
       45 
72 
     | 
    
         
             
                end
         
     | 
| 
       46 
73 
     | 
    
         | 
| 
       47 
74 
     | 
    
         
             
                # Finds child window (control) by either control ID or window class/title.
         
     | 
| 
       48 
75 
     | 
    
         
             
                # By default, only direct children are searched.
         
     | 
| 
       49 
76 
     | 
    
         
             
                # Options:
         
     | 
| 
       50 
77 
     | 
    
         
             
                # :id:: integer control id (such as IDOK, IDCANCEL, etc)
         
     | 
| 
       51 
     | 
    
         
            -
                # :title:: window title
         
     | 
| 
       52 
     | 
    
         
            -
                # :class:: window class
         
     | 
| 
      
 78 
     | 
    
         
            +
                # :title:: window title (String or Regexp)
         
     | 
| 
      
 79 
     | 
    
         
            +
                # :class:: window class (String or Regexp)
         
     | 
| 
       53 
80 
     | 
    
         
             
                # :indirect:: search all descendants, not only direct children
         
     | 
| 
       54 
81 
     | 
    
         
             
                # :timeout:: timeout (seconds)
         
     | 
| 
       55 
82 
     | 
    
         
             
                # :raise:: raise this exception instead of returning nil if nothing found
         
     | 
| 
       56 
     | 
    
         
            -
                # TODO: add the ability to nail indirect children as well
         
     | 
| 
       57 
83 
     | 
    
         
             
                #
         
     | 
| 
       58 
84 
     | 
    
         
             
                def child(opts={})
         
     | 
| 
       59 
85 
     | 
    
         
             
                  if opts[:indirect]
         
     | 
| 
       60 
     | 
    
         
            -
                    self.class. 
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                                (opts[:title] ? child.title == opts[:title] : true)
         
     | 
| 
       65 
     | 
    
         
            -
                      end
         
     | 
| 
       66 
     | 
    
         
            -
                      found.handle if found
         
     | 
| 
      
 86 
     | 
    
         
            +
                    self.class.lookup_window_in_collection(opts) { enum_child_windows }
         
     | 
| 
      
 87 
     | 
    
         
            +
                  elsif opts[:class].is_a?(Regexp) or opts[:title].is_a?(Regexp)
         
     | 
| 
      
 88 
     | 
    
         
            +
                    self.class.lookup_window_in_collection(opts) do
         
     | 
| 
      
 89 
     | 
    
         
            +
                      enum_child_windows.select { |handle| child? handle }
         
     | 
| 
       67 
90 
     | 
    
         
             
                    end
         
     | 
| 
       68 
91 
     | 
    
         
             
                  else
         
     | 
| 
       69 
92 
     | 
    
         
             
                    self.class.lookup_window opts do
         
     | 
| 
         @@ -106,9 +129,9 @@ module WinGui 
     | 
|
| 
       106 
129 
     | 
    
         
             
                    WinGui.set_cursor_pos *point
         
     | 
| 
       107 
130 
     | 
    
         | 
| 
       108 
131 
     | 
    
         
             
                    button = opts[:mouse_button] || opts[:mouse] || opts[:which]
         
     | 
| 
       109 
     | 
    
         
            -
                    down, up = 
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
      
 132 
     | 
    
         
            +
                    down, up = (button == :right) ?
         
     | 
| 
      
 133 
     | 
    
         
            +
                        [WinGui::MOUSEEVENTF_RIGHTDOWN, WinGui::MOUSEEVENTF_RIGHTUP] :
         
     | 
| 
      
 134 
     | 
    
         
            +
                        [WinGui::MOUSEEVENTF_LEFTDOWN, WinGui::MOUSEEVENTF_LEFTUP]
         
     | 
| 
       112 
135 
     | 
    
         | 
| 
       113 
136 
     | 
    
         
             
                    WinGui.mouse_event down, 0, 0, 0, 0
         
     | 
| 
       114 
137 
     | 
    
         
             
                    WinGui.mouse_event up, 0, 0, 0, 0
         
     | 
| 
         @@ -150,6 +173,8 @@ module WinGui 
     | 
|
| 
       150 
173 
     | 
    
         
             
                  get_window_thread_process_id.last
         
     | 
| 
       151 
174 
     | 
    
         
             
                end
         
     | 
| 
       152 
175 
     | 
    
         | 
| 
      
 176 
     | 
    
         
            +
                alias pid process
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
       153 
178 
     | 
    
         
             
                # Control ID associated with the window (only makes sense for controls)
         
     | 
| 
       154 
179 
     | 
    
         
             
                def id
         
     | 
| 
       155 
180 
     | 
    
         
             
                  get_dlg_ctrl_id
         
     | 
    
        data/spec/win_gui/window_spec.rb
    CHANGED
    
    | 
         @@ -1,5 +1,104 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "spec_helper.rb"
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            shared_examples_for 'normal window finder' do
         
     | 
| 
      
 4 
     | 
    
         
            +
              it 'finds top-level window by title and wraps it in a Window object' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                window = Window.top_level(:title => title, timeout: 1)
         
     | 
| 
      
 6 
     | 
    
         
            +
                window.handle.should == @win.handle
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              it 'finds top-level window by class and wraps it in a Window object' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                window = Window.top_level(:class => class_name, timeout: 1)
         
     | 
| 
      
 11 
     | 
    
         
            +
                window.handle.should == @win.handle
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              it 'finds top-level window by both class and title' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                window = Window.top_level(:class => class_name, :title => title)
         
     | 
| 
      
 16 
     | 
    
         
            +
                window.handle.should == @win.handle
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              it 'finds top-level window by both class and title' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                window = Window.top_level(:class => class_name, :title => title)
         
     | 
| 
      
 21 
     | 
    
         
            +
                window.handle.should == @win.handle
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              it 'returns nil if either window title or class do not match' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                Window.top_level(:class => class_name, :title => impossible).should == nil
         
     | 
| 
      
 26 
     | 
    
         
            +
                Window.top_level(:class => impossible, :title => title).should == nil
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              it 'returns nil immediately if top-level window not found' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                start = Time.now
         
     | 
| 
      
 31 
     | 
    
         
            +
                Window.top_level(:title => impossible).should == nil
         
     | 
| 
      
 32 
     | 
    
         
            +
                (Time.now - start).should be_within(0.05).of 0
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              it 'returns nil after timeout if top-level window not found' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                start = Time.now
         
     | 
| 
      
 37 
     | 
    
         
            +
                Window.top_level(:title => impossible, :timeout => 0.3).should == nil
         
     | 
| 
      
 38 
     | 
    
         
            +
                (Time.now - start).should be_within(0.05).of 0.3
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              it 'raises exception if asked to' do
         
     | 
| 
      
 42 
     | 
    
         
            +
                expect { Window.top_level(:title => impossible, :raise => "Horror!") }.to raise_error "Horror!"
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            shared_examples_for 'child window finder' do
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              it 'finds ANY child window without specific args' do
         
     | 
| 
      
 49 
     | 
    
         
            +
                use { @child = @win.child(opts) }
         
     | 
| 
      
 50 
     | 
    
         
            +
                @child.should_not == nil
         
     | 
| 
      
 51 
     | 
    
         
            +
                @win.child?(@child.handle).should == true
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              it 'returns nil immediately if specific child not found' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                start = Time.now
         
     | 
| 
      
 56 
     | 
    
         
            +
                @win.child(opts.merge(:title => impossible)).should == nil
         
     | 
| 
      
 57 
     | 
    
         
            +
                (Time.now - start).should be_within(0.05).of 0
         
     | 
| 
      
 58 
     | 
    
         
            +
              end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              it 'returns nil after timeout if specific child not found' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                start = Time.now
         
     | 
| 
      
 62 
     | 
    
         
            +
                @win.child(opts.merge(:title => impossible, :timeout => 0.5)).should == nil
         
     | 
| 
      
 63 
     | 
    
         
            +
                (Time.now - start).should be_within(0.05).of 0.5
         
     | 
| 
      
 64 
     | 
    
         
            +
              end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
              it 'finds child window by class and returns it as a Window object (no timeout)' do
         
     | 
| 
      
 67 
     | 
    
         
            +
                child = @win.child opts.merge(:class => class_name)
         
     | 
| 
      
 68 
     | 
    
         
            +
                child.should_not == nil
         
     | 
| 
      
 69 
     | 
    
         
            +
                @win.child?(child.handle).should == true
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
              it 'finds child window by class and returns it as a Window object (with timeout)' do
         
     | 
| 
      
 73 
     | 
    
         
            +
                child = @win.child opts.merge(:class => class_name, :timeout => 0.5)
         
     | 
| 
      
 74 
     | 
    
         
            +
                child.should_not == nil
         
     | 
| 
      
 75 
     | 
    
         
            +
                @win.child?(child.handle).should == true
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              it 'finds child with specific text and returns it as a Window object' do
         
     | 
| 
      
 79 
     | 
    
         
            +
                with_dialog(:save) do |dialog|
         
     | 
| 
      
 80 
     | 
    
         
            +
                  child = dialog.child opts.merge(:title => cancel)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  child.should_not == nil
         
     | 
| 
      
 82 
     | 
    
         
            +
                  dialog.child?(child.handle).should == true
         
     | 
| 
      
 83 
     | 
    
         
            +
                  child.get_dlg_ctrl_id.should == IDCANCEL
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  child = dialog.child opts.merge(:title => "&Save")
         
     | 
| 
      
 86 
     | 
    
         
            +
                  child.should_not == nil
         
     | 
| 
      
 87 
     | 
    
         
            +
                  dialog.child?(child.handle).should == true
         
     | 
| 
      
 88 
     | 
    
         
            +
                  child.get_dlg_ctrl_id.should == IDOK
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              it 'finds child control with a given ID and returns it as a Window object' do
         
     | 
| 
      
 93 
     | 
    
         
            +
                with_dialog(:save) do |dialog|
         
     | 
| 
      
 94 
     | 
    
         
            +
                  child = dialog.child opts.merge(:id => IDCANCEL)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  child.should_not == nil
         
     | 
| 
      
 96 
     | 
    
         
            +
                  dialog.child?(child.handle).should == true
         
     | 
| 
      
 97 
     | 
    
         
            +
                  child.text.should == "Cancel"
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
            end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
       3 
102 
     | 
    
         
             
            describe WinGui::Window do
         
     | 
| 
       4 
103 
     | 
    
         
             
              before(:each) { @win = launch_test_app.main_window }
         
     | 
| 
       5 
104 
     | 
    
         
             
              after(:each) { close_test_app }
         
     | 
| 
         @@ -51,18 +150,17 @@ describe WinGui::Window do 
     | 
|
| 
       51 
150 
     | 
    
         | 
| 
       52 
151 
     | 
    
         
             
                it 'has class_name and text/title properties (derived from WinGui function calls)' do
         
     | 
| 
       53 
152 
     | 
    
         
             
                  @win.class_name.should == WIN_CLASS
         
     | 
| 
       54 
     | 
    
         
            -
                  # text  
     | 
| 
      
 153 
     | 
    
         
            +
                  # text property accessed by sending WM_GETTEXT directly to window (convenience method in WinGui)
         
     | 
| 
       55 
154 
     | 
    
         
             
                  @win.text.should == WIN_TITLE
         
     | 
| 
       56 
     | 
    
         
            -
                  # window_text  
     | 
| 
      
 155 
     | 
    
         
            +
                  # window_text property accessed via GetWindowText
         
     | 
| 
       57 
156 
     | 
    
         
             
                  @win.window_text.should == WIN_TITLE
         
     | 
| 
       58 
157 
     | 
    
         
             
                  # title property is just an alias for window_text
         
     | 
| 
       59 
158 
     | 
    
         
             
                  @win.title.should == WIN_TITLE
         
     | 
| 
       60 
159 
     | 
    
         
             
                end
         
     | 
| 
       61 
160 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                it 'has thread and process properties derived from get_window_thread_process_id' do
         
     | 
| 
       63 
     | 
    
         
            -
                  thread 
     | 
| 
       64 
     | 
    
         
            -
                   
     | 
| 
       65 
     | 
    
         
            -
                  [thread, process].should == get_window_thread_process_id(@win.handle)
         
     | 
| 
      
 161 
     | 
    
         
            +
                it 'has thread and process(pid) properties derived from get_window_thread_process_id' do
         
     | 
| 
      
 162 
     | 
    
         
            +
                  [@win.thread, @win.process].should == get_window_thread_process_id(@win.handle)
         
     | 
| 
      
 163 
     | 
    
         
            +
                  @win.pid.should == @win.process
         
     | 
| 
       66 
164 
     | 
    
         
             
                end
         
     | 
| 
       67 
165 
     | 
    
         | 
| 
       68 
166 
     | 
    
         
             
                it 'has id property that only makes sense for controls' do
         
     | 
| 
         @@ -71,143 +169,79 @@ describe WinGui::Window do 
     | 
|
| 
       71 
169 
     | 
    
         
             
              end
         
     | 
| 
       72 
170 
     | 
    
         | 
| 
       73 
171 
     | 
    
         
             
              describe '::top_level' do
         
     | 
| 
       74 
     | 
    
         
            -
                it 'finds top-level window by title and wraps it in a Window object' do
         
     | 
| 
       75 
     | 
    
         
            -
                  window = Window.top_level(title: WIN_TITLE, timeout: 1)
         
     | 
| 
       76 
     | 
    
         
            -
                  window.handle.should == @win.handle
         
     | 
| 
       77 
     | 
    
         
            -
                end
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
     | 
    
         
            -
                it 'finds top-level window by class and wraps it in a Window object' do
         
     | 
| 
       80 
     | 
    
         
            -
                  window = Window.top_level(class: WIN_CLASS, timeout: 1)
         
     | 
| 
       81 
     | 
    
         
            -
                  window.handle.should == @win.handle
         
     | 
| 
       82 
     | 
    
         
            -
                end
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
172 
     | 
    
         
             
                it 'finds ANY top-level window without args and wraps it in a Window object' do
         
     | 
| 
       85 
173 
     | 
    
         
             
                  use { @window = Window.top_level() }
         
     | 
| 
       86 
174 
     | 
    
         
             
                  @window.should be_a Window
         
     | 
| 
       87 
175 
     | 
    
         
             
                end
         
     | 
| 
       88 
176 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
                 
     | 
| 
       90 
     | 
    
         
            -
                   
     | 
| 
       91 
     | 
    
         
            -
                   
     | 
| 
       92 
     | 
    
         
            -
                  ( 
     | 
| 
       93 
     | 
    
         
            -
                end
         
     | 
| 
      
 177 
     | 
    
         
            +
                context 'with String arguments' do
         
     | 
| 
      
 178 
     | 
    
         
            +
                  let(:title) { WIN_TITLE }
         
     | 
| 
      
 179 
     | 
    
         
            +
                  let(:class_name) { WIN_CLASS }
         
     | 
| 
      
 180 
     | 
    
         
            +
                  let(:impossible) { IMPOSSIBLE }
         
     | 
| 
       94 
181 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                  start = Time.now
         
     | 
| 
       97 
     | 
    
         
            -
                  Window.top_level(title: IMPOSSIBLE, timeout: 0.3).should == nil
         
     | 
| 
       98 
     | 
    
         
            -
                  (Time.now - start).should be_within(0.03).of 0.3
         
     | 
| 
      
 182 
     | 
    
         
            +
                  it_should_behave_like 'normal window finder'
         
     | 
| 
       99 
183 
     | 
    
         
             
                end
         
     | 
| 
       100 
184 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
                 
     | 
| 
       102 
     | 
    
         
            -
                   
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
      
 185 
     | 
    
         
            +
                context 'with Regexp arguments' do
         
     | 
| 
      
 186 
     | 
    
         
            +
                  let(:title) { Regexp.new WIN_TITLE[-6..-1] }
         
     | 
| 
      
 187 
     | 
    
         
            +
                  let(:class_name) { Regexp.new WIN_CLASS[-6..-1] }
         
     | 
| 
      
 188 
     | 
    
         
            +
                  let(:impossible) { Regexp.new IMPOSSIBLE }
         
     | 
| 
       104 
189 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
                  use { @window = Window.find() }
         
     | 
| 
       107 
     | 
    
         
            -
                  @window.should be_a Window
         
     | 
| 
      
 190 
     | 
    
         
            +
                  it_should_behave_like 'normal window finder'
         
     | 
| 
       108 
191 
     | 
    
         
             
                end
         
     | 
| 
       109 
     | 
    
         
            -
              end # describe .top_level
         
     | 
| 
       110 
192 
     | 
    
         | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
      
 193 
     | 
    
         
            +
                context 'with mixed arguments' do
         
     | 
| 
      
 194 
     | 
    
         
            +
                  let(:title) { Regexp.new WIN_TITLE[-6..-1] }
         
     | 
| 
      
 195 
     | 
    
         
            +
                  let(:class_name) { WIN_CLASS }
         
     | 
| 
      
 196 
     | 
    
         
            +
                  let(:impossible) { IMPOSSIBLE }
         
     | 
| 
       113 
197 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                  start = Time.now
         
     | 
| 
       116 
     | 
    
         
            -
                  @win.child(title: IMPOSSIBLE).should == nil
         
     | 
| 
       117 
     | 
    
         
            -
                  (Time.now - start).should be_within(0.03).of 0
         
     | 
| 
       118 
     | 
    
         
            -
                end
         
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
                it 'returns nil after timeout if specific child not found' do
         
     | 
| 
       121 
     | 
    
         
            -
                  start = Time.now
         
     | 
| 
       122 
     | 
    
         
            -
                  @win.child(title: IMPOSSIBLE, timeout: 0.5).should == nil
         
     | 
| 
       123 
     | 
    
         
            -
                  (Time.now - start).should be_within(0.03).of 0.5
         
     | 
| 
      
 198 
     | 
    
         
            +
                  it_should_behave_like 'normal window finder'
         
     | 
| 
       124 
199 
     | 
    
         
             
                end
         
     | 
| 
       125 
200 
     | 
    
         | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
                  use { @child = @win.child() }
         
     | 
| 
       128 
     | 
    
         
            -
                  @child.should_not == nil
         
     | 
| 
       129 
     | 
    
         
            -
                  @win.child?(@child.handle).should == true
         
     | 
| 
       130 
     | 
    
         
            -
                end
         
     | 
| 
      
 201 
     | 
    
         
            +
              end # describe .top_level
         
     | 
| 
       131 
202 
     | 
    
         | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
     | 
    
         
            -
                  child.should_not == nil
         
     | 
| 
       135 
     | 
    
         
            -
                  @win.child?(child.handle).should == true
         
     | 
| 
       136 
     | 
    
         
            -
                end
         
     | 
| 
      
 203 
     | 
    
         
            +
              describe '#child' do
         
     | 
| 
      
 204 
     | 
    
         
            +
                spec { use { @child = @win.child(title: "Title", class: "Class", id: 0) } }
         
     | 
| 
       137 
205 
     | 
    
         | 
| 
       138 
     | 
    
         
            -
                 
     | 
| 
       139 
     | 
    
         
            -
                   
     | 
| 
       140 
     | 
    
         
            -
                  child.should_not == nil
         
     | 
| 
      
 206 
     | 
    
         
            +
                context 'direct children only' do
         
     | 
| 
      
 207 
     | 
    
         
            +
                  let(:opts) { {} }
         
     | 
| 
       141 
208 
     | 
    
         | 
| 
       142 
     | 
    
         
            -
                   
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
             
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
                end
         
     | 
| 
      
 209 
     | 
    
         
            +
                  context 'with String arguments' do
         
     | 
| 
      
 210 
     | 
    
         
            +
                    let(:cancel) { 'Cancel' }
         
     | 
| 
      
 211 
     | 
    
         
            +
                    let(:class_name) { TEXTAREA_CLASS }
         
     | 
| 
      
 212 
     | 
    
         
            +
                    let(:impossible) { IMPOSSIBLE }
         
     | 
| 
       147 
213 
     | 
    
         | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
                  with_dialog(:save) do |dialog|
         
     | 
| 
       150 
     | 
    
         
            -
                    child = dialog.child(title: "Cancel")
         
     | 
| 
       151 
     | 
    
         
            -
                    child.should_not == nil
         
     | 
| 
       152 
     | 
    
         
            -
                    dialog.child?(child.handle).should == true
         
     | 
| 
       153 
     | 
    
         
            -
                    child.get_dlg_ctrl_id.should == IDCANCEL
         
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
                    child = dialog.child(title: "&Save")
         
     | 
| 
       156 
     | 
    
         
            -
                    child.should_not == nil
         
     | 
| 
       157 
     | 
    
         
            -
                    dialog.child?(child.handle).should == true
         
     | 
| 
       158 
     | 
    
         
            -
                    child.get_dlg_ctrl_id.should == IDOK
         
     | 
| 
      
 214 
     | 
    
         
            +
                    it_should_behave_like 'child window finder'
         
     | 
| 
       159 
215 
     | 
    
         
             
                  end
         
     | 
| 
       160 
     | 
    
         
            -
                end
         
     | 
| 
       161 
216 
     | 
    
         | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
                     
     | 
| 
       165 
     | 
    
         
            -
                     
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                    child 
     | 
| 
      
 217 
     | 
    
         
            +
                  context 'with Regexp arguments' do
         
     | 
| 
      
 218 
     | 
    
         
            +
                    let(:cancel) { /Cancel/ }
         
     | 
| 
      
 219 
     | 
    
         
            +
                    let(:class_name) { Regexp.new TEXTAREA_CLASS[-6..-1] }
         
     | 
| 
      
 220 
     | 
    
         
            +
                    let(:impossible) { Regexp.new IMPOSSIBLE }
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                    it_should_behave_like 'child window finder'
         
     | 
| 
       168 
223 
     | 
    
         
             
                  end
         
     | 
| 
       169 
224 
     | 
    
         
             
                end
         
     | 
| 
       170 
225 
     | 
    
         | 
| 
       171 
     | 
    
         
            -
                context 'indirect  
     | 
| 
       172 
     | 
    
         
            -
                   
     | 
| 
       173 
     | 
    
         
            -
                    @win.child(title: IMPOSSIBLE, indirect: true).should == nil
         
     | 
| 
       174 
     | 
    
         
            -
                  end
         
     | 
| 
      
 226 
     | 
    
         
            +
                context 'indirect children' do
         
     | 
| 
      
 227 
     | 
    
         
            +
                  let(:opts) { {:indirect => true} }
         
     | 
| 
       175 
228 
     | 
    
         | 
| 
       176 
     | 
    
         
            -
                   
     | 
| 
       177 
     | 
    
         
            -
                     
     | 
| 
       178 
     | 
    
         
            -
                     
     | 
| 
       179 
     | 
    
         
            -
                     
     | 
| 
       180 
     | 
    
         
            -
                  end
         
     | 
| 
      
 229 
     | 
    
         
            +
                  context 'with String arguments' do
         
     | 
| 
      
 230 
     | 
    
         
            +
                    let(:cancel) { 'Cancel' }
         
     | 
| 
      
 231 
     | 
    
         
            +
                    let(:class_name) { TEXTAREA_CLASS }
         
     | 
| 
      
 232 
     | 
    
         
            +
                    let(:impossible) { IMPOSSIBLE }
         
     | 
| 
       181 
233 
     | 
    
         | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
       183 
     | 
    
         
            -
                    child = @win.child(class: TEXTAREA_CLASS, indirect: true)
         
     | 
| 
       184 
     | 
    
         
            -
                    child.should_not == nil
         
     | 
| 
       185 
     | 
    
         
            -
                    @win.child?(child.handle).should == true
         
     | 
| 
      
 234 
     | 
    
         
            +
                    it_should_behave_like 'child window finder'
         
     | 
| 
       186 
235 
     | 
    
         
             
                  end
         
     | 
| 
       187 
236 
     | 
    
         | 
| 
       188 
     | 
    
         
            -
                   
     | 
| 
       189 
     | 
    
         
            -
                     
     | 
| 
       190 
     | 
    
         
            -
             
     | 
| 
       191 
     | 
    
         
            -
             
     | 
| 
       192 
     | 
    
         
            -
                      dialog.child?(child.handle).should == true
         
     | 
| 
       193 
     | 
    
         
            -
                      child.id.should == IDCANCEL
         
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
                      child = dialog.child(title: "&Save", indirect: true)
         
     | 
| 
       196 
     | 
    
         
            -
                      child.should_not == nil
         
     | 
| 
       197 
     | 
    
         
            -
                      dialog.child?(child.handle).should == true
         
     | 
| 
       198 
     | 
    
         
            -
                      child.id.should == IDOK
         
     | 
| 
       199 
     | 
    
         
            -
                    end
         
     | 
| 
       200 
     | 
    
         
            -
                  end
         
     | 
| 
      
 237 
     | 
    
         
            +
                  context 'with Regexp arguments' do
         
     | 
| 
      
 238 
     | 
    
         
            +
                    let(:cancel) { /Cancel/ }
         
     | 
| 
      
 239 
     | 
    
         
            +
                    let(:class_name) { Regexp.new TEXTAREA_CLASS[-6..-1] }
         
     | 
| 
      
 240 
     | 
    
         
            +
                    let(:impossible) { Regexp.new IMPOSSIBLE }
         
     | 
| 
       201 
241 
     | 
    
         | 
| 
       202 
     | 
    
         
            -
             
     | 
| 
       203 
     | 
    
         
            -
                    with_dialog(:save) do |dialog|
         
     | 
| 
       204 
     | 
    
         
            -
                      child = dialog.child(id: IDCANCEL, indirect: true)
         
     | 
| 
       205 
     | 
    
         
            -
                      child.should_not == nil
         
     | 
| 
       206 
     | 
    
         
            -
                      dialog.child?(child.handle).should == true
         
     | 
| 
       207 
     | 
    
         
            -
                      child.text.should == "Cancel"
         
     | 
| 
       208 
     | 
    
         
            -
                    end
         
     | 
| 
      
 242 
     | 
    
         
            +
                    it_should_behave_like 'child window finder'
         
     | 
| 
       209 
243 
     | 
    
         
             
                  end
         
     | 
| 
       210 
     | 
    
         
            -
                end 
     | 
| 
      
 244 
     | 
    
         
            +
                end
         
     | 
| 
       211 
245 
     | 
    
         
             
              end # describe child
         
     | 
| 
       212 
246 
     | 
    
         | 
| 
       213 
247 
     | 
    
         
             
              describe '#children' do
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -2,7 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         
             
            name: win_gui
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
       4 
4 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       5 
     | 
    
         
            -
              version: 0.2. 
     | 
| 
      
 5 
     | 
    
         
            +
              version: 0.2.18
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors: 
         
     | 
| 
       8 
8 
     | 
    
         
             
            - arvicco
         
     | 
| 
         @@ -10,7 +10,7 @@ autorequire: 
     | 
|
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
     | 
    
         
            -
            date: 2011-02- 
     | 
| 
      
 13 
     | 
    
         
            +
            date: 2011-02-17 00:00:00 +03:00
         
     | 
| 
       14 
14 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       15 
15 
     | 
    
         
             
            dependencies: 
         
     | 
| 
       16 
16 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
         @@ -46,7 +46,7 @@ dependencies: 
     | 
|
| 
       46 
46 
     | 
    
         
             
                    version: 0.3.1
         
     | 
| 
       47 
47 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       48 
48 
     | 
    
         
             
              version_requirements: *id003
         
     | 
| 
       49 
     | 
    
         
            -
            description: Abstractions/wrappers around GUI-related Win32 API functions
         
     | 
| 
      
 49 
     | 
    
         
            +
            description: Work with Windows GUI in an object-oriented way. Abstractions/wrappers around GUI-related Win32 API functions
         
     | 
| 
       50 
50 
     | 
    
         
             
            email: arvitallian@gmail.com
         
     | 
| 
       51 
51 
     | 
    
         
             
            executables: []
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
         @@ -115,7 +115,7 @@ rubyforge_project: 
     | 
|
| 
       115 
115 
     | 
    
         
             
            rubygems_version: 1.5.0
         
     | 
| 
       116 
116 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       117 
117 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       118 
     | 
    
         
            -
            summary:  
     | 
| 
      
 118 
     | 
    
         
            +
            summary: Work with Windows GUI in an object-oriented way
         
     | 
| 
       119 
119 
     | 
    
         
             
            test_files: 
         
     | 
| 
       120 
120 
     | 
    
         
             
            - spec/extension_spec.rb
         
     | 
| 
       121 
121 
     | 
    
         
             
            - spec/spec_helper.rb
         
     |