rdp-win32screenshot 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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