win_gui 0.1.0

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.
Files changed (164) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +43 -0
  5. data/Rakefile +58 -0
  6. data/VERSION +1 -0
  7. data/book_code/early_success/bundle.rb +34 -0
  8. data/book_code/early_success/english.txt +1 -0
  9. data/book_code/early_success/jruby_basics.rb +47 -0
  10. data/book_code/early_success/windows_basics.rb +97 -0
  11. data/book_code/guessing/locknote.rb +379 -0
  12. data/book_code/guessing/monkeyshines.rb +14 -0
  13. data/book_code/guessing/note.rb +120 -0
  14. data/book_code/guessing/note_spec.rb +175 -0
  15. data/book_code/guessing/replay.rb +21 -0
  16. data/book_code/guessing/seed.rb +9 -0
  17. data/book_code/guessing/spec_helper.rb +69 -0
  18. data/book_code/guessing/windows_gui.rb +247 -0
  19. data/book_code/home_stretch/junquenote.rb +151 -0
  20. data/book_code/home_stretch/locknote.rb +180 -0
  21. data/book_code/home_stretch/note.rb +144 -0
  22. data/book_code/home_stretch/note_spec.rb +191 -0
  23. data/book_code/home_stretch/spec_helper.rb +55 -0
  24. data/book_code/home_stretch/swing_gui.rb +50 -0
  25. data/book_code/home_stretch/windows_gui.rb +232 -0
  26. data/book_code/junquenote/exports.sh +10 -0
  27. data/book_code/junquenote/jruby_mac.sh +10 -0
  28. data/book_code/junquenote/junquenote_app.rb +262 -0
  29. data/book_code/novite/Rakefile +10 -0
  30. data/book_code/novite/app/controllers/application.rb +18 -0
  31. data/book_code/novite/app/controllers/guests_controller.rb +28 -0
  32. data/book_code/novite/app/controllers/parties_controller.rb +77 -0
  33. data/book_code/novite/app/helpers/application_helper.rb +11 -0
  34. data/book_code/novite/app/helpers/guests_helper.rb +10 -0
  35. data/book_code/novite/app/helpers/parties_helper.rb +10 -0
  36. data/book_code/novite/app/models/guest.rb +11 -0
  37. data/book_code/novite/app/models/party.rb +32 -0
  38. data/book_code/novite/app/models/party_mailer.rb +19 -0
  39. data/book_code/novite/app/views/layouts/application.rhtml +44 -0
  40. data/book_code/novite/app/views/parties/new.html.erb +42 -0
  41. data/book_code/novite/app/views/parties/show.html.erb +43 -0
  42. data/book_code/novite/app/views/party_mailer/invite.erb +17 -0
  43. data/book_code/novite/config/boot.rb +117 -0
  44. data/book_code/novite/config/database.yml +19 -0
  45. data/book_code/novite/config/environment.rb +67 -0
  46. data/book_code/novite/config/environments/development.rb +29 -0
  47. data/book_code/novite/config/environments/production.rb +27 -0
  48. data/book_code/novite/config/environments/test.rb +30 -0
  49. data/book_code/novite/config/initializers/inflections.rb +18 -0
  50. data/book_code/novite/config/initializers/mime_types.rb +13 -0
  51. data/book_code/novite/config/routes.rb +47 -0
  52. data/book_code/novite/db/migrate/001_create_parties.rb +26 -0
  53. data/book_code/novite/db/migrate/002_create_guests.rb +23 -0
  54. data/book_code/novite/db/schema.rb +41 -0
  55. data/book_code/novite/log/empty.txt +0 -0
  56. data/book_code/novite/public/.htaccess +40 -0
  57. data/book_code/novite/public/404.html +38 -0
  58. data/book_code/novite/public/422.html +38 -0
  59. data/book_code/novite/public/500.html +38 -0
  60. data/book_code/novite/public/dispatch.cgi +10 -0
  61. data/book_code/novite/public/dispatch.fcgi +24 -0
  62. data/book_code/novite/public/dispatch.rb +18 -0
  63. data/book_code/novite/public/favicon.ico +0 -0
  64. data/book_code/novite/public/images/rails.png +0 -0
  65. data/book_code/novite/public/index.html +285 -0
  66. data/book_code/novite/public/javascripts/application.js +10 -0
  67. data/book_code/novite/public/javascripts/controls.js +971 -0
  68. data/book_code/novite/public/javascripts/dragdrop.js +980 -0
  69. data/book_code/novite/public/javascripts/effects.js +1128 -0
  70. data/book_code/novite/public/javascripts/prototype.js +4233 -0
  71. data/book_code/novite/public/robots.txt +5 -0
  72. data/book_code/novite/script/about +3 -0
  73. data/book_code/novite/script/console +3 -0
  74. data/book_code/novite/script/destroy +3 -0
  75. data/book_code/novite/script/generate +3 -0
  76. data/book_code/novite/script/performance/benchmarker +3 -0
  77. data/book_code/novite/script/performance/profiler +3 -0
  78. data/book_code/novite/script/performance/request +3 -0
  79. data/book_code/novite/script/plugin +3 -0
  80. data/book_code/novite/script/process/inspector +3 -0
  81. data/book_code/novite/script/process/reaper +3 -0
  82. data/book_code/novite/script/process/spawner +3 -0
  83. data/book_code/novite/script/runner +3 -0
  84. data/book_code/novite/script/server +3 -0
  85. data/book_code/novite/test/test_helper.rb +46 -0
  86. data/book_code/one_more_thing/applescript.rb +68 -0
  87. data/book_code/one_more_thing/note_spec.rb +50 -0
  88. data/book_code/one_more_thing/spec_helper.rb +17 -0
  89. data/book_code/one_more_thing/textedit-pure.rb +28 -0
  90. data/book_code/one_more_thing/textedit.applescript +26 -0
  91. data/book_code/one_more_thing/textedit.rb +32 -0
  92. data/book_code/one_more_thing/textnote.rb +87 -0
  93. data/book_code/simplify/junquenote.rb +48 -0
  94. data/book_code/simplify/locknote.rb +46 -0
  95. data/book_code/simplify/note.rb +35 -0
  96. data/book_code/simplify/note_spec.rb +28 -0
  97. data/book_code/simplify/swing_gui.rb +45 -0
  98. data/book_code/simplify/windows_gui.rb +232 -0
  99. data/book_code/simplify/windows_gui_spec.rb +35 -0
  100. data/book_code/story/invite.story +19 -0
  101. data/book_code/story/journal.txt +29 -0
  102. data/book_code/story/novite_stories.rb +156 -0
  103. data/book_code/story/party.rb +149 -0
  104. data/book_code/story/password.rb +61 -0
  105. data/book_code/story/password.story +26 -0
  106. data/book_code/story/rsvp.story +29 -0
  107. data/book_code/tables/TestTime.html +93 -0
  108. data/book_code/tables/TestTimeSample.html +63 -0
  109. data/book_code/tables/calculate_time.rb +39 -0
  110. data/book_code/tables/calculator.rb +108 -0
  111. data/book_code/tables/calculator_actions.rb +27 -0
  112. data/book_code/tables/calculator_spec.rb +47 -0
  113. data/book_code/tables/fit.rb +32 -0
  114. data/book_code/tables/matrix.rb +109 -0
  115. data/book_code/tables/pseudocode.rb +17 -0
  116. data/book_code/tubes/book_selenium.rb +67 -0
  117. data/book_code/tubes/book_watir.rb +60 -0
  118. data/book_code/tubes/dragdrop.html +81 -0
  119. data/book_code/tubes/html_capture.rb +33 -0
  120. data/book_code/tubes/joke_list.rb +67 -0
  121. data/book_code/tubes/list_spec.rb +41 -0
  122. data/book_code/tubes/search_spec.rb +32 -0
  123. data/book_code/tubes/selenium_example.rb +66 -0
  124. data/book_code/tubes/selenium_link.rb +23 -0
  125. data/book_code/tubes/web_server.rb +14 -0
  126. data/book_code/windows/wgui.rb +29 -0
  127. data/book_code/windows/wobj.rb +25 -0
  128. data/book_code/windows/wsh.rb +25 -0
  129. data/book_code/with_rspec/empty_spec.rb +13 -0
  130. data/book_code/with_rspec/junquenote.rb +60 -0
  131. data/book_code/with_rspec/locknote.rb +129 -0
  132. data/book_code/with_rspec/note_spec.rb +32 -0
  133. data/book_code/with_rspec/should_examples.rb +18 -0
  134. data/exp/exp.rb +6 -0
  135. data/exp/exp_encodings.rb +40 -0
  136. data/exp/exp_enum_windows.rb +60 -0
  137. data/exp/exp_quik.rb +38 -0
  138. data/exp/exp_wsh.rb +115 -0
  139. data/exp/old/windows_basics.rb +80 -0
  140. data/exp/old/wnote.rb +80 -0
  141. data/exp/old/wnote_spec.rb +20 -0
  142. data/features/step_definitions/win_gui_steps.rb +0 -0
  143. data/features/support/env.rb +4 -0
  144. data/features/win_gui.feature +9 -0
  145. data/lib/note/java/jemmy.jar +0 -0
  146. data/lib/note/java/jnote.rb +48 -0
  147. data/lib/note/java/jruby_basics.rb +37 -0
  148. data/lib/note/java/junquenote_app.rb +262 -0
  149. data/lib/note/java/note_spec.rb +20 -0
  150. data/lib/note/win/locknote.rb +19 -0
  151. data/lib/note.rb +15 -0
  152. data/lib/win_gui/constants.rb +66 -0
  153. data/lib/win_gui/string_extensions.rb +24 -0
  154. data/lib/win_gui/win_gui.rb +274 -0
  155. data/lib/win_gui/window.rb +70 -0
  156. data/lib/win_gui.rb +3 -0
  157. data/spec/note/win/locknote_spec.rb +7 -0
  158. data/spec/spec.opts +2 -0
  159. data/spec/spec_helper.rb +100 -0
  160. data/spec/test_apps/locknote/LockNote.exe +0 -0
  161. data/spec/win_gui/string_extensions_spec.rb +61 -0
  162. data/spec/win_gui/win_gui_spec.rb +733 -0
  163. data/spec/win_gui/window_spec.rb +124 -0
  164. metadata +251 -0
@@ -0,0 +1,70 @@
1
+ module WinGui
2
+ class Window
3
+ include WinGui
4
+ extend WinGui
5
+
6
+ attr_reader :handle
7
+
8
+ # find top level window by title, return wrapped Window object
9
+ def self.top_level(title, seconds=3)
10
+ @handle = timeout(seconds) do
11
+ sleep WG_SLEEP_DELAY while (h = find_window nil, title) == nil; h
12
+ end
13
+ Window.new @handle
14
+ end
15
+
16
+ def initialize(handle)
17
+ @handle = handle
18
+ end
19
+
20
+ # find child window (control) by title, window class, or control ID:
21
+ def child(id)
22
+ result = case id
23
+ when String
24
+ by_title = find_window_ex @handle, 0, nil, id.gsub('_' , '&' )
25
+ by_class = find_window_ex @handle, 0, id, nil
26
+ by_title ? by_title : by_class
27
+ when Fixnum
28
+ get_dlg_item @handle, id
29
+ when nil
30
+ find_window_ex @handle, 0, nil, nil
31
+ else
32
+ nil
33
+ end
34
+ raise "Control '#{id}' not found" unless result
35
+ Window.new result
36
+ end
37
+
38
+ def children
39
+ enum_child_windows(@handle,'Msg').map{|child_handle| Window.new child_handle}
40
+ end
41
+
42
+ # emulate click of the control identified by id
43
+ def click(id)
44
+ h = child(id).handle
45
+ rectangle = [0, 0, 0, 0].pack 'LLLL'
46
+ get_window_rect h, rectangle
47
+ left, top, right, bottom = rectangle.unpack 'LLLL'
48
+ center = [(left + right) / 2, (top + bottom) / 2]
49
+ set_cursor_pos *center
50
+ mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
51
+ mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
52
+ end
53
+
54
+ def close
55
+ post_message @handle, WM_SYSCOMMAND, SC_CLOSE, 0
56
+ end
57
+
58
+ def wait_for_close
59
+ timeout(WG_CLOSE_TIMEOUT) do
60
+ sleep WG_SLEEP_DELAY while window_visible?(@handle)
61
+ end
62
+ end
63
+
64
+ def text
65
+ buffer = "\x0" * 2048
66
+ length = send_message @handle, WM_GETTEXT, buffer.length, buffer
67
+ length == 0 ? '' : buffer[0..length - 1]
68
+ end
69
+ end
70
+ end
data/lib/win_gui.rb ADDED
@@ -0,0 +1,3 @@
1
+ win_gui_dir = File.join(File.dirname(__FILE__),"win_gui" )
2
+ $LOAD_PATH.unshift win_gui_dir unless $LOAD_PATH.include?(win_gui_dir)
3
+ require 'win_gui'
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), ".." , ".." ,"spec_helper" )
2
+
3
+ module GuiTest
4
+ describe LockNote do
5
+
6
+ end
7
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format nested
@@ -0,0 +1,100 @@
1
+ lib_dir = File.join(File.dirname(__FILE__),".." ,"lib" )
2
+ $LOAD_PATH.unshift lib_dir unless $LOAD_PATH.include?(lib_dir)
3
+ require 'spec'
4
+ require 'win_gui'
5
+ require 'note'
6
+
7
+ # Customize RSpec with my own extensions
8
+ module SpecMacros
9
+
10
+ # wrapper for it method that extracts description from example source code, such as:
11
+ # spec { use{ function(arg1 = 4, arg2 = 'string') }}
12
+ def spec &block
13
+ it description_from(*block.source_location), &block
14
+ end
15
+
16
+ # reads description line from source file and drops external brackets (like its{}, use{}
17
+ def description_from(file, line)
18
+ File.open(file) do |f|
19
+ f.lines.to_a[line-1].gsub( /(spec.*?{)|(use.*?{)|}/, '' ).strip
20
+ end
21
+ end
22
+ end
23
+
24
+ Spec::Runner.configure { |config| config.extend(SpecMacros) }
25
+
26
+ module GuiTest
27
+ include WinGui
28
+
29
+ # Test related Constants:
30
+ TEST_TIMEOUT = 0.001
31
+ TEST_KEY_DELAY = 0.001
32
+ TEST_SLEEP_DELAY = 0.01
33
+ TEST_APP_PATH = File.join(File.dirname(__FILE__), "test_apps/locknote/LockNote.exe" )
34
+ TEST_APP_START = 'start "" "' + TEST_APP_PATH + '"'
35
+ TEST_WIN_TITLE = 'LockNote - Steganos LockNote'
36
+ TEST_WIN_CLASS = 'ATL:00434098'
37
+ TEST_WIN_RECT = [710, 400, 1210, 800]
38
+ TEST_MAX_RECT = [-4, -4, 1924, 1204] # on my 1920x1200 display
39
+ TEST_MIN_RECT = [-32000, -32000, -31840, -31976]
40
+ TEST_TEXTAREA_CLASS = 'ATL:00434310'
41
+ TEST_IMPOSSIBLE = 'Impossible'
42
+ TEST_ERROR_CONVERSION = /Can.t convert/
43
+
44
+ # Helper methods:
45
+ def use
46
+ lambda {yield}.should_not raise_error
47
+ end
48
+
49
+ def any_handle
50
+ find_window(nil, nil)
51
+ end
52
+
53
+ def any_block
54
+ lambda {|*args| args}
55
+ end
56
+
57
+ def hide_method(name) # hide original method if it is defined
58
+ WinGui.module_eval do
59
+ if method_defined? name.to_sym
60
+ alias_method "orig_#{name.to_s}".to_sym, name.to_sym
61
+ remove_method name.to_sym
62
+ end
63
+ end
64
+ end
65
+
66
+ def restore_method(name) # restore original method if it was hidden
67
+ WinGui.module_eval do
68
+ temp = "orig_#{name.to_s}".to_sym
69
+ if method_defined? temp
70
+ alias_method name.to_sym, temp
71
+ remove_method temp
72
+ end
73
+ end
74
+ end
75
+
76
+ def launch_test_app
77
+ system TEST_APP_START
78
+ sleep TEST_SLEEP_DELAY until (handle = find_window(nil, TEST_WIN_TITLE))
79
+ @launched_test_app = Window.new handle
80
+ end
81
+
82
+ def close_test_app(app = @launched_test_app)
83
+ while app and app.respond_to? :handle and find_window(nil, TEST_WIN_TITLE)
84
+ post_message(app.handle, WM_SYSCOMMAND, SC_CLOSE, 0)
85
+ sleep TEST_SLEEP_DELAY
86
+ end
87
+ @launched_test_app = nil
88
+ end
89
+
90
+ # Creates test app object and yields it back to the block
91
+ def test_app
92
+ app = launch_test_app
93
+ def app.textarea #define singleton method retrieving app's text area
94
+ Window.new find_window_ex(self.handle, 0, TEST_TEXTAREA_CLASS, nil)
95
+ end
96
+ yield app
97
+ close_test_app
98
+ end
99
+
100
+ end
@@ -0,0 +1,61 @@
1
+ require File.join(File.dirname(__FILE__), ".." , "spec_helper" )
2
+
3
+ module GuiTest
4
+
5
+ describe String do
6
+ context '#snake_case' do
7
+ it 'transforms CamelCase strings' do
8
+ 'GetCharWidth32'.snake_case.should == 'get_char_width_32'
9
+ end
10
+
11
+ it 'leaves snake_case strings intact' do
12
+ 'keybd_event'.snake_case.should == 'keybd_event'
13
+ end
14
+ end
15
+
16
+ context '#to_w' do
17
+ it 'transcodes string to utf-16LE' do
18
+ 'GetCharWidth32'.to_w.encoding.name.should == 'UTF-16LE'
19
+ end
20
+
21
+ it 'ensures that encoded string is null-terminated' do
22
+ 'GetCharWidth32'.to_w.bytes.to_a[-2..-1].should == [0, 0]
23
+ end
24
+ end
25
+
26
+ context '#to_vkeys' do
27
+ it 'transforms number char into [equivalent key code]' do
28
+ ('0'..'9').each {|char| char.to_vkeys.should == char.unpack('C')}
29
+ end
30
+
31
+ it 'transforms uppercase letters into [shift, equivalent key code]' do
32
+ ('A'..'Z').each {|char| char.to_vkeys.should == [VK_SHIFT, *char.unpack('C')]}
33
+ end
34
+
35
+ it 'transforms lowercase letters into [(upcase) key code]' do
36
+ ('a'..'z').each {|char| char.to_vkeys.should == char.upcase.unpack('C')}
37
+ end
38
+
39
+ it 'transforms space into [equivalent key code]' do
40
+ " ".to_vkeys.should == " ".unpack('C')
41
+ end
42
+
43
+ it 'raises error if char is not implemented punctuation' do
44
+ ('!'..'/').each {|char| lambda {char.to_vkeys}.should raise_error TEST_ERROR_CONVERSION }
45
+ (':'..'@').each {|char| lambda {char.to_vkeys}.should raise_error TEST_ERROR_CONVERSION }
46
+ ('['..'`').each {|char| lambda {char.to_vkeys}.should raise_error TEST_ERROR_CONVERSION }
47
+ ('{'..'~').each {|char| lambda {char.to_vkeys}.should raise_error TEST_ERROR_CONVERSION }
48
+ end
49
+
50
+ it 'raises error if char is non-printable or non-ascii' do
51
+ lambda {1.chr.to_vkeys}.should raise_error TEST_ERROR_CONVERSION
52
+ lambda {230.chr.to_vkeys}.should raise_error TEST_ERROR_CONVERSION
53
+ end
54
+
55
+ it 'raises error if string is multi-char' do
56
+ lambda {'hello'.to_vkeys}.should raise_error TEST_ERROR_CONVERSION
57
+ lambda {'23'.to_vkeys}.should raise_error TEST_ERROR_CONVERSION
58
+ end
59
+ end
60
+ end
61
+ end