rdp-win32screenshot 0.0.6

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ coverage
2
+ rdoc
3
+ pkg
4
+ .idea
5
+ spec/tmp
data/History.rdoc ADDED
@@ -0,0 +1,40 @@
1
+ = 0.0.6 2010-XX-XX
2
+ * Trying to bring window to the foreground more aggressively (Roger Pack)
3
+
4
+ = 0.0.5 2010-07-07
5
+ * Added method window_area for capturing specified area of the window instead of full window (Jarmo Pertman)
6
+ Usage: Win32::Screenshot.window_area(title, x1, y1, x2, y2) {|width, height, bmp|}
7
+ * Added method foreground_area for capturing area of the foreground (Jarmo Pertman)
8
+ Usage: Win32::Screenshot.foreground_area(x1, y1, x2, y2) {|width, height, bmp|}
9
+ * Added method desktop_area for capturing area of the visible view (Jarmo Pertman)
10
+ Usage: Win32::Screenshot.desktop_area(x1, y1, x2, y2) {|width, height, bmp|}
11
+ * Added method hwnd_area for capturing area of the window with specified handle (Jarmo Pertman)
12
+ Usage: Win32::Screenshot.hwnd_area(hwnd, x1, y1, x2, y2) {|width, height, bmp|}
13
+
14
+ == Internal changes
15
+ * Removed usage of ShowWindow with parameter SW_SHOW when trying to bring window to front due it's behaviour of resizing window if it was maximized (Jarmo Pertman)
16
+ * Using FFI::Struct when searching window handle (Roger Pack)
17
+
18
+ = 0.0.4 2010-05-27 - A Complete Overhaul
19
+ * Fixed a bug where taking of screenshots failed on some sizes of windows (thanks for the tip from Tony Popiel)
20
+ * Blocks should be used when taking screenshots for cleaning up resources after usage (Aslak Hellesøy)
21
+ * Changed library structure - it is now needed to require 'win32/screenshot' (Aslak Hellesøy)
22
+ * Replaced Ruby::DL with Ruby-FFI for better VM support and less segfaults (Jarmo Pertman)
23
+ * Added Ruby 1.9.1 support (Jarmo Pertman)
24
+ * Win32::Screenshot.window restores window if it's minimized before taking screenshots and brings it to the foreground (Jarmo Pertman)
25
+ * Changed some internal method names (Jarmo Pertman)
26
+ * Replaced Test::Unit with RSpec and made specs more robust (Jarmo Pertman)
27
+
28
+ PS! This version is not backwards compatible due to different method names and usage, but upgrading should be relatively easy nevertheless.
29
+
30
+ = 0.0.3 2007-01-18
31
+ * Fixed bug with too many callbacks
32
+ * Added get_hwnd(Regexp)
33
+
34
+ = 0.0.2 2006-12-02
35
+ * Added desktop method (patch from Ryan Schuft)
36
+ * Added HTTP server example (patch from Ryan Schuft)
37
+ * Added window(regexp) method
38
+
39
+ = 0.0.1 2006-11-29
40
+ * First release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Jarmo Pertman, Aslak Hellesøy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,76 @@
1
+ = Win32::Screenshot (old name win32screenshot)
2
+
3
+ * http://github.com/jarmo/win32screenshot
4
+
5
+ == DESCRIPTION
6
+
7
+ Capture Screenshots on Windows with Ruby. This library captures
8
+ screenshots in bmp format, but you may use RMagick to convert these to some
9
+ other formats like png.
10
+
11
+ == SYNOPSIS
12
+
13
+ require 'win32/screenshot'
14
+
15
+ # take a screenshot of the foreground window
16
+ Win32::Screenshot.foreground do |width, height, bmp|
17
+ File.open("picture1.bmp", "wb") {|file| file.puts bmp}
18
+ end
19
+
20
+ # take a screenshot of the area of the foreground where upper left x and y
21
+ # coordinates are 0 and 10, width is 100 and height is 200
22
+ Win32::Screenshot.foreground_area(0, 10, 100, 200) do |width, height, bmp|
23
+ File.open("picture2.bmp", "wb") {|file| file.puts bmp}
24
+ end
25
+
26
+ # take a screenshot of the screen
27
+ Win32::Screenshot.desktop do |width, height, bmp|
28
+ File.open("picture3.bmp", "wb") {|file| file.puts bmp}
29
+ end
30
+
31
+ # take a screenshot of the area of the desktop where upper left x and y
32
+ # coordinates are 0 and 10, width is 100 and height is 200
33
+ Win32::Screenshot.desktop_area(0, 10, 100, 200) do |width, height, bmp|
34
+ File.open("picture4.bmp", "wb") {|file| file.puts bmp}
35
+ end
36
+
37
+ # take a screenshot of the window, which has a text part of it's title
38
+ Win32::Screenshot.window("Internet Explorer") do |width, height, bmp|
39
+ File.open("picture5.bmp", "wb") {|file| file.puts bmp}
40
+ end
41
+
42
+ # take a screenshot of the window, which matches regexp against it's title
43
+ Win32::Screenshot.window(/Internet Explorer/) do |width, height, bmp|
44
+ File.open("picture6.bmp", "wb") {|file| file.puts bmp}
45
+ end
46
+
47
+ # take a screenshot of the area of the window where upper left x and y
48
+ # coordinates are 0 and 10, width is 100 and height is 200
49
+ Win32::Screenshot.window_area("Internet Explorer", 0, 10, 100, 200) do |width, height, bmp|
50
+ File.open("picture7.bmp", "wb") {|file| file.puts bmp}
51
+ end
52
+
53
+ # take a screenshot of the window with specified window handle
54
+ Win32::Screenshot.hwnd(window_handle) do |width, height, bmp|
55
+ File.open("picture8.bmp", "wb") {|file| file.puts bmp}
56
+ end
57
+
58
+ # take a screenshot of the area of the window with a window handle
59
+ # where upper left x and y
60
+ # coordinates are 0 and 10, width is 100 and height is 200
61
+ Win32::Screenshot.hwnd_area(window_handle, 0, 10, 100, 200) do |width, height, bmp|
62
+ File.open("picture9.bmp", "wb") {|file| file.puts bmp}
63
+ end
64
+
65
+ # convert a screenshot to the png format with RMagick
66
+ require 'rmagick'
67
+
68
+ Win32::Screenshot.hwnd(window_handle) do |width, height, bmp|
69
+ img = Magick::Image.from_blob(bmp)
70
+ png = img[0].to_blob {self.format = 'PNG'}
71
+ File.open("picture10.png", "wb") {|file| file.puts png}
72
+ end
73
+
74
+ == Copyright
75
+
76
+ Copyright (c) 2010 Jarmo Pertman, Aslak Hellesøy. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,63 @@
1
+ # coding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'os'
6
+
7
+ begin
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gem|
10
+ gem.name = "rdp-win32screenshot"
11
+ gem.summary = %Q{Capture Screenshots on Windows with Ruby}
12
+ gem.description = %Q{Capture Screenshots on Windows with Ruby}
13
+ gem.email = ["jarmo.p@gmail.com", "aslak.hellesoy@gmail.com"]
14
+ gem.homepage = "http://github.com/jarmo/win32screenshot"
15
+ gem.authors = ["Jarmo Pertman", "Aslak Hellesøy"]
16
+
17
+ gem.rdoc_options = ["--main", "README.rdoc"]
18
+
19
+ gem.add_dependency "ffi"
20
+
21
+ gem.add_development_dependency "rspec", ">= 1.2.9"
22
+ gem.add_development_dependency 'os'
23
+ if OS.java?
24
+ gem.add_development_dependency "rmagick4j"
25
+ else
26
+ gem.add_development_dependency "rmagick"
27
+ end
28
+ end
29
+ Jeweler::GemcutterTasks.new
30
+ rescue LoadError
31
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
32
+ end
33
+
34
+ require 'spec/rake/spectask'
35
+ Spec::Rake::SpecTask.new(:spec) do |spec|
36
+ spec.libs << 'lib' << 'spec'
37
+ spec.spec_files = FileList['spec/**/*_spec.rb']
38
+ end
39
+
40
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
41
+ spec.libs << 'lib' << 'spec'
42
+ spec.pattern = 'spec/**/*_spec.rb'
43
+ spec.rcov = true
44
+ end
45
+
46
+ task :spec => :check_dependencies
47
+
48
+ task :default => :spec
49
+
50
+ require 'rake/rdoctask'
51
+ Rake::RDocTask.new do |rdoc|
52
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "Win32::Screenshot #{version}"
56
+ rdoc.rdoc_files.include('README*')
57
+ rdoc.rdoc_files.include('lib/**/*.rb')
58
+ end
59
+
60
+ desc "Remove all temporary files"
61
+ task :clobber => [:clobber_rdoc, :clobber_rcov] do
62
+ rm_r "spec/tmp"
63
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.6
@@ -0,0 +1,100 @@
1
+ require 'win32/screenshot/bitmap_maker'
2
+
3
+ module Win32
4
+ # Captures screenshots with Ruby on Windows
5
+ class Screenshot
6
+ class << self
7
+
8
+ # captures foreground
9
+ def foreground(&proc)
10
+ hwnd = BitmapMaker.foreground_window
11
+ BitmapMaker.capture_all(hwnd, &proc)
12
+ end
13
+
14
+ # captures area of the foreground
15
+ # where *x1* and *y1* are 0 in the upper left corner and
16
+ # *x2* specifies the width and *y2* the height of the area to be captured
17
+ def foreground_area(x1, y1, x2, y2, &proc)
18
+ hwnd = BitmapMaker.foreground_window
19
+ validate_coordinates(hwnd, x1, y1, x2, y2)
20
+ BitmapMaker.capture_area(hwnd, x1, y1, x2, y2, &proc)
21
+ end
22
+
23
+ # captures visible view of the screen
24
+ #
25
+ # to make screenshot of the real desktop, all
26
+ # windows must be minimized before
27
+ def desktop(&proc)
28
+ hwnd = BitmapMaker.desktop_window
29
+ BitmapMaker.capture_all(hwnd, &proc)
30
+ end
31
+
32
+ # captures area of the visible view of the screen
33
+ # where *x1* and *y1* are 0 in the upper left corner and
34
+ # *x2* specifies the width and *y2* the height of the area to be captured
35
+ #
36
+ # to make screenshot of the real desktop, all
37
+ # windows must be minimized before
38
+ def desktop_area(x1, y1, x2, y2, &proc)
39
+ hwnd = BitmapMaker.desktop_window
40
+ validate_coordinates(hwnd, x1, y1, x2, y2)
41
+ BitmapMaker.capture_area(hwnd, x1, y1, x2, y2, &proc)
42
+ end
43
+
44
+ # captures window with a *title_query* and waits *pause* (by default is 0.5)
45
+ # seconds after trying to set window to the foreground
46
+ def window(title_query, pause=0.5, &proc)
47
+ hwnd = window_hwnd(title_query)
48
+ hwnd(hwnd, pause, &proc)
49
+ end
50
+
51
+ # captures area of the window with a *title_query*
52
+ # where *x1* and *y1* are 0 in the upper left corner and
53
+ # *x2* specifies the width and *y2* the height of the area to be captured
54
+ def window_area(title_query, x1, y1, x2, y2, pause=0.5, &proc)
55
+ hwnd = window_hwnd(title_query)
56
+ hwnd_area(hwnd, x1, y1, x2, y2, pause, &proc)
57
+ end
58
+
59
+ # captures by window handle
60
+ def hwnd(hwnd, pause=0.5, &proc)
61
+ BitmapMaker.prepare_window(hwnd, pause)
62
+ BitmapMaker.capture_all(hwnd, &proc)
63
+ end
64
+
65
+ # captures area of the window with a handle of *hwnd*
66
+ # where *x1* and *y1* are 0 in the upper left corner and
67
+ # *x2* specifies the width and *y2* the height of the area to be captured
68
+ def hwnd_area(hwnd, x1, y1, x2, y2, pause=0.5, &proc)
69
+ validate_coordinates(hwnd, x1, y1, x2, y2)
70
+ BitmapMaker.prepare_window(hwnd, pause)
71
+ BitmapMaker.capture_area(hwnd, x1, y1, x2, y2, &proc)
72
+ end
73
+
74
+ private
75
+
76
+ def window_hwnd(title_query)
77
+ hwnd = BitmapMaker.hwnd(title_query)
78
+ raise "window with title '#{title_query}' was not found!" unless hwnd
79
+ hwnd
80
+ end
81
+
82
+ def validate_coordinates(hwnd, *coords)
83
+ specified_coordinates = coords.join(', ')
84
+ if coords.any? {|c| c < 0}
85
+ raise "specified coordinates (#{specified_coordinates}) are invalid! cannot have any less than zero"
86
+ end
87
+ x1, y1, x2, y2 = *coords
88
+ if x1 >= x2 || y1 >= y2
89
+ raise "specified coordinates (#{specified_coordinates}) are invalid! cannot have x1 > x2 or y1 > y2"
90
+ end
91
+
92
+ x1_always_zero, y1_always_zero, max_x2, max_y2 = BitmapMaker.dimensions_for(hwnd)
93
+ if x2 > max_x2 || y2 > max_y2
94
+ raise "specified coordinates (#{specified_coordinates}) are invalid! max is #{max_x2},#{max_y2}"
95
+ end
96
+ end
97
+ end
98
+
99
+ end
100
+ end
@@ -0,0 +1,172 @@
1
+ require 'ffi'
2
+
3
+ module Win32
4
+ class Screenshot
5
+ # internal methods
6
+ module BitmapMaker #:nodoc:all
7
+ extend FFI::Library
8
+
9
+ ffi_lib 'user32', 'gdi32'
10
+ ffi_convention :stdcall
11
+
12
+ callback :enum_callback, [:long, :pointer], :bool
13
+
14
+ # user32.dll
15
+ attach_function :enum_windows, :EnumWindows,
16
+ [:enum_callback, :pointer], :long
17
+ attach_function :window_text, :GetWindowTextA,
18
+ [:long, :pointer, :int], :int
19
+ attach_function :window_text_length, :GetWindowTextLengthA,
20
+ [:long], :int
21
+ attach_function :window_visible, :IsWindowVisible,
22
+ [:long], :bool
23
+ attach_function :dc, :GetDC,
24
+ [:long], :long
25
+ attach_function :client_rect, :GetClientRect,
26
+ [:long, :pointer], :bool
27
+ attach_function :minimized, :IsIconic,
28
+ [:long], :bool
29
+ attach_function :show_window, :ShowWindow,
30
+ [:long, :int], :bool
31
+ attach_function :foreground_window, :GetForegroundWindow,
32
+ [], :long
33
+ attach_function :desktop_window, :GetDesktopWindow,
34
+ [], :long
35
+ attach_function :window_thread_process_id, :GetWindowThreadProcessId,
36
+ [:long, :pointer], :long
37
+ attach_function :attach_thread_input, :AttachThreadInput,
38
+ [:long, :long, :bool], :bool
39
+ attach_function :set_foreground_window, :SetForegroundWindow,
40
+ [:long], :bool
41
+ attach_function :bring_window_to_top, :BringWindowToTop,
42
+ [:long], :bool
43
+ attach_function :set_active_window, :SetActiveWindow,
44
+ [:long], :long
45
+
46
+
47
+ # gdi32.dll
48
+ attach_function :create_compatible_dc, :CreateCompatibleDC,
49
+ [:long], :long
50
+ attach_function :create_compatible_bitmap, :CreateCompatibleBitmap,
51
+ [:long, :int, :int], :long
52
+ attach_function :select_object, :SelectObject,
53
+ [:long, :long], :long
54
+ attach_function :bit_blt, :BitBlt,
55
+ [:long, :int, :int, :int, :int, :long, :int, :int, :long], :bool
56
+ attach_function :di_bits, :GetDIBits,
57
+ [:long, :long, :int, :int, :pointer, :pointer, :int], :int
58
+ attach_function :delete_object, :DeleteObject,
59
+ [:long], :bool
60
+ attach_function :delete_dc, :DeleteDC,
61
+ [:long], :bool
62
+ attach_function :release_dc, :ReleaseDC,
63
+ [:long, :long], :int
64
+
65
+
66
+ EnumWindowCallback = Proc.new do |hwnd, param|
67
+ searched_window = WindowStruct.new param
68
+ title_length = window_text_length(hwnd) + 1
69
+ title = FFI::MemoryPointer.new :char, title_length
70
+ window_text(hwnd, title, title_length)
71
+ title = title.read_string
72
+ if title =~ Regexp.new(searched_window[:title].read_string) && window_visible(hwnd)
73
+ searched_window[:hwnd] = hwnd
74
+ false
75
+ else
76
+ true
77
+ end
78
+ end
79
+
80
+ module_function
81
+
82
+ class WindowStruct < FFI::Struct
83
+ layout :title, :pointer,
84
+ :hwnd, :long
85
+ end
86
+
87
+ def hwnd(window_title)
88
+ window = WindowStruct.new
89
+ window_title = FFI::MemoryPointer.from_string(window_title.to_s)
90
+ window[:title] = window_title
91
+ enum_windows(EnumWindowCallback, window.to_ptr)
92
+ window[:hwnd] == 0 ? nil : window[:hwnd]
93
+ end
94
+
95
+ def prepare_window(hwnd, pause)
96
+ restore(hwnd) if minimized(hwnd)
97
+ set_foreground(hwnd)
98
+ sleep pause
99
+ end
100
+
101
+ SW_RESTORE = 9
102
+
103
+ def restore(hwnd)
104
+ show_window(hwnd, SW_RESTORE)
105
+ end
106
+
107
+ def set_foreground(hwnd)
108
+ if foreground_window != hwnd
109
+ set_foreground_window(hwnd)
110
+ set_active_window(hwnd)
111
+ bring_window_to_top(hwnd)
112
+ # and just in case...
113
+ foreground_thread = window_thread_process_id(foreground_window, nil)
114
+ other_thread = window_thread_process_id(hwnd, nil)
115
+ attach_thread_input(foreground_thread, other_thread, true) unless other_thread == foreground_thread
116
+ set_foreground_window(hwnd)
117
+ set_active_window(hwnd)
118
+ bring_window_to_top(hwnd)
119
+ attach_thread_input(foreground_thread, other_thread, false) unless other_thread == foreground_thread
120
+ end
121
+ end
122
+
123
+ def dimensions_for(hwnd)
124
+ rect = [0, 0, 0, 0].pack('L4')
125
+ client_rect(hwnd, rect)
126
+ x1, y1, x2, y2 = rect.unpack('L4')
127
+ end
128
+
129
+ def capture_all(hwnd, &proc)
130
+ x1, y1, x2, y2 = dimensions_for(hwnd)
131
+ capture_area(hwnd, x1, y1, x2, y2, &proc)
132
+ end
133
+
134
+ SRCCOPY = 0x00CC0020
135
+ DIB_RGB_COLORS = 0
136
+
137
+ def capture_area(hwnd, x1, y1, x2, y2, &proc)
138
+ hScreenDC = dc(hwnd)
139
+ w = x2-x1
140
+ h = y2-y1
141
+
142
+ hmemDC = create_compatible_dc(hScreenDC)
143
+ hmemBM = create_compatible_bitmap(hScreenDC, w, h)
144
+ select_object(hmemDC, hmemBM)
145
+ bit_blt(hmemDC, 0, 0, w, h, hScreenDC, x1, y1, SRCCOPY)
146
+ bitmap_size = w * h * 3 + w % 4 * h
147
+ lpvpxldata = FFI::MemoryPointer.new(bitmap_size)
148
+
149
+ # Bitmap header
150
+ # http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html
151
+ bmInfo = [40, w, h, 1, 24, 0, 0, 0, 0, 0, 0, 0].pack('L3S2L6')
152
+ di_bits(hmemDC, hmemBM, 0, h, lpvpxldata, bmInfo, DIB_RGB_COLORS)
153
+
154
+ bmFileHeader = [
155
+ 19778,
156
+ bitmap_size + 40 + 14,
157
+ 0,
158
+ 0,
159
+ 54
160
+ ].pack('SLSSL')
161
+
162
+ bmp_data = bmFileHeader + bmInfo + lpvpxldata.read_string(bitmap_size)
163
+ proc.call(w, h, bmp_data)
164
+ ensure
165
+ lpvpxldata.free
166
+ delete_object(hmemBM)
167
+ delete_dc(hmemDC)
168
+ release_dc(0, hScreenDC)
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
2
+ Kernel.warn %q(DEPRECATION: use "require 'win32/screenshot'" instead of "require 'win32screenshot'")
3
+ require "win32/screenshot"
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,76 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'win32/screenshot'
4
+ require 'rubygems'
5
+ require 'spec'
6
+ require 'spec/autorun'
7
+ require 'RMagick'
8
+ require 'fileutils'
9
+
10
+ module SpecHelper
11
+ SW_MAXIMIZE = 3
12
+ SW_MINIMIZE = 6
13
+ HWND_TOPMOST = -1
14
+ HWND_NOTOPMOST = -2
15
+ SWP_NOSIZE = 1
16
+ SWP_NOMOVE = 2
17
+ SWP_SHOWWINDOW = 40
18
+
19
+ extend FFI::Library
20
+ ffi_lib 'user32'
21
+ ffi_convention :stdcall
22
+
23
+ # user32.dll
24
+ attach_function :set_window_pos, :SetWindowPos,
25
+ [:long, :long, :int, :int, :int, :int, :int], :bool
26
+
27
+ def cleanup
28
+ FileUtils.rm Dir.glob(File.join(File.dirname(__FILE__), "tmp/*"))
29
+ end
30
+
31
+ def check_image(bmp, file=nil)
32
+ temp_dir = File.join(File.dirname(__FILE__), 'tmp')
33
+ FileUtils.mkdir temp_dir unless File.exists?(temp_dir)
34
+ File.open(File.join(temp_dir, "#{file}.bmp"), "wb") {|io| io.write(bmp)} unless file.nil?
35
+ bmp[0..1].should == 'BM'
36
+ img = Magick::Image.from_blob(bmp)
37
+ png = img[0].to_blob {self.format = 'PNG'}
38
+ png[0..3].should == "\211PNG"
39
+ File.open(File.join(temp_dir, "#{file}.png"), "wb") {|io| io.puts(png)} unless file.nil?
40
+ end
41
+
42
+ def wait_for_programs_to_open
43
+ until Win32::Screenshot::BitmapMaker.hwnd(/Internet Explorer/) &&
44
+ Win32::Screenshot::BitmapMaker.hwnd(/Notepad/) &&
45
+ Win32::Screenshot::BitmapMaker.hwnd(/Calculator/)
46
+ sleep 0.1
47
+ end
48
+ # just in case of slow PC
49
+ sleep 10
50
+ end
51
+
52
+ def maximize title
53
+ Win32::Screenshot::BitmapMaker.show_window(Win32::Screenshot::BitmapMaker.hwnd(title),
54
+ SW_MAXIMIZE)
55
+ sleep 1
56
+ end
57
+
58
+ def minimize title
59
+ Win32::Screenshot::BitmapMaker.show_window(Win32::Screenshot::BitmapMaker.hwnd(title),
60
+ SW_MINIMIZE)
61
+ sleep 1
62
+ end
63
+
64
+ def resize title
65
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(title)
66
+ set_window_pos(hwnd,
67
+ HWND_TOPMOST,
68
+ 0, 0, 150, 238,
69
+ SWP_NOMOVE)
70
+ set_window_pos(hwnd,
71
+ HWND_NOTOPMOST,
72
+ 0, 0, 0, 0,
73
+ SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE)
74
+ sleep 1
75
+ end
76
+ end
@@ -0,0 +1,184 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "win32-screenshot" do
4
+ include SpecHelper
5
+
6
+ before :all do
7
+ cleanup
8
+ PROGRAM_FILES = "c:/program files/"
9
+ @notepad = IO.popen("notepad").pid
10
+ @iexplore = IO.popen(File.join(PROGRAM_FILES, "Internet Explorer", "iexplore about:blank")).pid
11
+ @calc = IO.popen("calc").pid
12
+ wait_for_programs_to_open
13
+ end
14
+
15
+ it "captures foreground" do
16
+ Win32::Screenshot.foreground do |width, height, bmp|
17
+ check_image(bmp, 'foreground')
18
+ hwnd = Win32::Screenshot::BitmapMaker.foreground_window
19
+ dimensions = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
20
+ width.should == dimensions[2]
21
+ height.should == dimensions[3]
22
+ end
23
+ end
24
+
25
+ it "captures area of the foreground" do
26
+ Win32::Screenshot.foreground_area(30, 30, 100, 150) do |width, height, bmp|
27
+ check_image(bmp, 'foreground_area')
28
+ width.should == 70
29
+ height.should == 120
30
+ end
31
+ end
32
+
33
+ it "doesn't allow to capture area of the foreground with invalid coordinates" do
34
+ lambda {Win32::Screenshot.foreground_area(0, 0, -1, 100) {|width, height, bmp| check_image('foreground2')}}.
35
+ should raise_exception("specified coordinates (0, 0, -1, 100) are invalid! cannot have any less than zero")
36
+ end
37
+
38
+ it "captures desktop" do
39
+ Win32::Screenshot.desktop do |width, height, bmp|
40
+ check_image(bmp, 'desktop')
41
+ hwnd = Win32::Screenshot::BitmapMaker.desktop_window
42
+ dimensions = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
43
+ width.should == dimensions[2]
44
+ height.should == dimensions[3]
45
+ end
46
+ end
47
+
48
+ it "captures area of the desktop" do
49
+ Win32::Screenshot.desktop_area(30, 30, 100, 150) do |width, height, bmp|
50
+ check_image(bmp, 'desktop_area')
51
+ width.should == 70
52
+ height.should == 120
53
+ end
54
+ end
55
+
56
+ it "doesn't allow to capture area of the desktop with invalid coordinates" do
57
+ lambda {Win32::Screenshot.desktop_area(0, 0, -1, 100) {|width, height, bmp| check_image('desktop2')}}.
58
+ should raise_exception("specified coordinates (0, 0, -1, 100) are invalid! cannot have any less than zero")
59
+ end
60
+
61
+ it "captures maximized window by window title" do
62
+ title = "Internet Explorer"
63
+ maximize(title)
64
+ Win32::Screenshot.window(title) do |width, height, bmp|
65
+ check_image(bmp, 'iexplore')
66
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(title)
67
+ dimensions = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
68
+ width.should == dimensions[2]
69
+ height.should == dimensions[3]
70
+ end
71
+ end
72
+
73
+ it "captures minimized window by window title as a regexp" do
74
+ title = /calculator/i
75
+ minimize(title)
76
+ Win32::Screenshot.window(title) do |width, height, bmp|
77
+ check_image(bmp, 'calc')
78
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(title)
79
+ dimensions = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
80
+ width.should == dimensions[2]
81
+ height.should == dimensions[3]
82
+ end
83
+ end
84
+
85
+ it "captures small windows" do
86
+ title = /Notepad/
87
+ resize(title)
88
+ Win32::Screenshot.window(title) do |width, height, bmp|
89
+ check_image(bmp, 'notepad')
90
+ # we should get the size of the picture because
91
+ # screenshot doesn't include titlebar and the size
92
+ # varies between different themes and Windows versions
93
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(title)
94
+ dimensions = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
95
+ width.should == dimensions[2]
96
+ height.should == dimensions[3]
97
+ end
98
+ end
99
+
100
+ it "captures area of the window" do
101
+ title = /calculator/i
102
+ Win32::Screenshot.window_area(title, 30, 30, 100, 150) do |width, height, bmp|
103
+ check_image(bmp, 'calc_area')
104
+ width.should == 70
105
+ height.should == 120
106
+ end
107
+ end
108
+
109
+ it "captures whole window if window size is specified as coordinates" do
110
+ title = /calculator/i
111
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(title)
112
+ dimensions = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
113
+ Win32::Screenshot.window_area(title, 0, 0, dimensions[2], dimensions[3]) do |width, height, bmp|
114
+ check_image(bmp, 'calc_area_full_window')
115
+ width.should == dimensions[2]
116
+ height.should == dimensions[3]
117
+ end
118
+ end
119
+
120
+ it "doesn't allow to capture area of the window with negative coordinates" do
121
+ title = /calculator/i
122
+ lambda {Win32::Screenshot.window_area(title, 0, 0, -1, 100) {|width, height, bmp| check_image('calc2')}}.
123
+ should raise_exception("specified coordinates (0, 0, -1, 100) are invalid! cannot have any less than zero")
124
+ end
125
+
126
+ it "doesn't allow to capture area of the window if coordinates are the same" do
127
+ title = /calculator/i
128
+ lambda {Win32::Screenshot.window_area(title, 10, 0, 10, 20) {|width, height, bmp| check_image('calc4')}}.
129
+ should raise_exception("specified coordinates (10, 0, 10, 20) are invalid! cannot have x1 > x2 or y1 > y2")
130
+ end
131
+
132
+ it "doesn't allow to capture area of the window if second coordinate is smaller than first one" do
133
+ title = /calculator/i
134
+ lambda {Win32::Screenshot.window_area(title, 0, 10, 10, 9) {|width, height, bmp| check_image('calc5')}}.
135
+ should raise_exception("specified coordinates (0, 10, 10, 9) are invalid! cannot have x1 > x2 or y1 > y2")
136
+ end
137
+
138
+ it "doesn't allow to capture area of the window with too big coordinates" do
139
+ title = /calculator/i
140
+ lambda {Win32::Screenshot.window_area(title, 0, 0, 10, 10000) {|width, height, bmp| check_image('calc3')}}.
141
+ should raise_exception("specified coordinates (0, 0, 10, 10000) are invalid! max is 212,264")
142
+ end
143
+
144
+ it "captures by window with handle" do
145
+ title = /calculator/i
146
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(title)
147
+ Win32::Screenshot.hwnd(hwnd) do |width, height, bmp|
148
+ check_image(bmp, 'calc_hwnd')
149
+ dimensions = Win32::Screenshot::BitmapMaker.dimensions_for(hwnd)
150
+ width.should == dimensions[2]
151
+ height.should == dimensions[3]
152
+ end
153
+ end
154
+
155
+ it "captures area of the window with handle" do
156
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(/calculator/i)
157
+ Win32::Screenshot.hwnd_area(hwnd, 30, 30, 100, 150) do |width, height, bmp|
158
+ check_image(bmp, 'calc_hwnd_area')
159
+ width.should == 70
160
+ height.should == 120
161
+ end
162
+ end
163
+
164
+ it "doesn't allow to capture area of the window with handle with invalid coordinates" do
165
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(/calculator/i)
166
+ lambda {Win32::Screenshot.hwnd_area(hwnd, 0, 0, -1, 100) {|width, height, bmp| check_image('desktop2')}}.
167
+ should raise_exception("specified coordinates (0, 0, -1, 100) are invalid! cannot have any less than zero")
168
+ end
169
+
170
+ it "captures based on coordinates" do
171
+ hwnd = Win32::Screenshot::BitmapMaker.hwnd(/calculator/i)
172
+ bmp1 = bmp2 = nil
173
+ Win32::Screenshot.hwnd_area(hwnd, 100, 100, 170, 220) do |width, height, bmp|; bmp1 = bmp; end
174
+ Win32::Screenshot.hwnd_area(hwnd, 0, 0, 70, 120) do |width, height, bmp|; bmp2 = bmp; end
175
+ bmp1.length.should == bmp2.length
176
+ bmp1.should_not == bmp2
177
+ end
178
+
179
+ after :all do
180
+ Process.kill 9, @notepad
181
+ Process.kill 9, @iexplore rescue nil # allow for a pre-existing IE to have been used.
182
+ Process.kill 9, @calc
183
+ end
184
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rdp-win32screenshot
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 6
10
+ version: 0.0.6
11
+ platform: ruby
12
+ authors:
13
+ - Jarmo Pertman
14
+ - "Aslak Helles\xC3\xB8y"
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-07-14 00:00:00 -06:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: ffi
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 13
45
+ segments:
46
+ - 1
47
+ - 2
48
+ - 9
49
+ version: 1.2.9
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: os
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ type: :development
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: rmagick
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ type: :development
79
+ version_requirements: *id004
80
+ description: Capture Screenshots on Windows with Ruby
81
+ email:
82
+ - jarmo.p@gmail.com
83
+ - aslak.hellesoy@gmail.com
84
+ executables: []
85
+
86
+ extensions: []
87
+
88
+ extra_rdoc_files:
89
+ - LICENSE
90
+ - README.rdoc
91
+ files:
92
+ - .document
93
+ - .gitignore
94
+ - History.rdoc
95
+ - LICENSE
96
+ - README.rdoc
97
+ - Rakefile
98
+ - VERSION
99
+ - lib/win32/screenshot.rb
100
+ - lib/win32/screenshot/bitmap_maker.rb
101
+ - lib/win32screenshot.rb
102
+ - spec/spec.opts
103
+ - spec/spec_helper.rb
104
+ - spec/win32_screenshot_spec.rb
105
+ has_rdoc: true
106
+ homepage: http://github.com/jarmo/win32screenshot
107
+ licenses: []
108
+
109
+ post_install_message:
110
+ rdoc_options:
111
+ - --main
112
+ - README.rdoc
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ hash: 3
121
+ segments:
122
+ - 0
123
+ version: "0"
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ requirements: []
134
+
135
+ rubyforge_project:
136
+ rubygems_version: 1.3.7
137
+ signing_key:
138
+ specification_version: 3
139
+ summary: Capture Screenshots on Windows with Ruby
140
+ test_files:
141
+ - spec/spec_helper.rb
142
+ - spec/win32_screenshot_spec.rb