win32screenshot 0.0.2 → 0.0.4
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 +5 -0
- data/.gitignore +6 -0
- data/History.rdoc +23 -0
- data/LICENSE +20 -0
- data/README.rdoc +51 -0
- data/Rakefile +48 -46
- data/VERSION +1 -0
- data/lib/win32/screenshot.rb +36 -0
- data/lib/win32/screenshot/bitmap_maker.rb +168 -0
- data/lib/win32screenshot.rb +3 -130
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +68 -0
- data/spec/win32_screenshot_spec.rb +91 -0
- metadata +105 -50
- data/History.txt +0 -7
- data/Manifest.txt +0 -9
- data/README.txt +0 -3
- data/lib/win32screenshot/version.rb +0 -9
- data/setup.rb +0 -1585
- data/test/test_helper.rb +0 -2
- data/test/win32screenshot_test.rb +0 -43
data/.document
ADDED
data/History.rdoc
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
= 0.0.4 2010-05-27 - A Complete Overhaul
|
2
|
+
* Fixed a bug where taking of screenshots failed on some sizes of windows (thanks for the tip from Tony Popiel)
|
3
|
+
* Blocks should be used when taking screenshots for cleaning up resources after usage (Aslak Hellesøy)
|
4
|
+
* Changed library structure - it is now needed to require 'win32/screenshot' (Aslak Hellesøy)
|
5
|
+
* Replaced Ruby::DL with Ruby-FFI for better VM support and less segfaults (Jarmo Pertman)
|
6
|
+
* Added Ruby 1.9.1 support (Jarmo Pertman)
|
7
|
+
* Win32::Screenshot.window restores window if it's minimized before taking screenshots and brings it to the foreground (Jarmo Pertman)
|
8
|
+
* Changed some internal method names (Jarmo Pertman)
|
9
|
+
* Replaced Test::Unit with RSpec and made specs more robust (Jarmo Pertman)
|
10
|
+
|
11
|
+
PS! This version is not backwards compatible due to different method names and usage, but upgrading should be relatively easy nevertheless.
|
12
|
+
|
13
|
+
= 0.0.3 2007-01-18
|
14
|
+
* Fixed bug with too many callbacks
|
15
|
+
* Added get_hwnd(Regexp)
|
16
|
+
|
17
|
+
= 0.0.2 2006-12-02
|
18
|
+
* Added desktop method (patch from Ryan Schuft)
|
19
|
+
* Added HTTP server example (patch from Ryan Schuft)
|
20
|
+
* Added window(regexp) method
|
21
|
+
|
22
|
+
= 0.0.1 2006-11-29
|
23
|
+
* 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,51 @@
|
|
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 screen
|
21
|
+
Win32::Screenshot.desktop do |width, height, bmp|
|
22
|
+
File.open("picture2.bmp", "wb") {|file| file.puts bmp}
|
23
|
+
end
|
24
|
+
|
25
|
+
# take a screenshot of the window, which has a text part of it's title
|
26
|
+
Win32::Screenshot.window("Internet Explorer") do |width, height, bmp|
|
27
|
+
File.open("picture3.bmp", "wb") {|file| file.puts bmp}
|
28
|
+
end
|
29
|
+
|
30
|
+
# take a screenshot of the window, which matches regexp against it's title
|
31
|
+
Win32::Screenshot.window(/Internet Explorer/) do |width, height, bmp|
|
32
|
+
File.open("picture4.bmp", "wb") {|file| file.puts bmp}
|
33
|
+
end
|
34
|
+
|
35
|
+
# take a screenshot of the window with specified window handle
|
36
|
+
Win32::Screenshot.hwnd(window_handle) do |width, height, bmp|
|
37
|
+
File.open("picture5.bmp", "wb") {|file| file.puts bmp}
|
38
|
+
end
|
39
|
+
|
40
|
+
# convert a screenshot to the png format with RMagick
|
41
|
+
require 'rmagick'
|
42
|
+
|
43
|
+
Win32::Screenshot.hwnd(window_handle) do |width, height, bmp|
|
44
|
+
img = Magick::Image.from_blob(bmp)
|
45
|
+
png = img[0].to_blob {self.format = 'PNG'}
|
46
|
+
File.open("picture6.png", "wb") {|file| file.puts png}
|
47
|
+
end
|
48
|
+
|
49
|
+
== Copyright
|
50
|
+
|
51
|
+
Copyright (c) 2010 Jarmo Pertman, Aslak Hellesøy. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,50 +1,52 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
1
3
|
require 'rubygems'
|
2
4
|
require 'rake'
|
3
|
-
|
4
|
-
|
5
|
-
require '
|
6
|
-
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gem|
|
9
|
+
gem.name = "win32screenshot"
|
10
|
+
gem.summary = %Q{Capture Screenshots on Windows with Ruby}
|
11
|
+
gem.description = %Q{Capture Screenshots on Windows with Ruby}
|
12
|
+
gem.email = ["jarmo.p@gmail.com", "aslak.hellesoy@gmail.com"]
|
13
|
+
gem.homepage = "http://github.com/jarmo/win32screenshot"
|
14
|
+
gem.authors = ["Jarmo Pertman", "Aslak Hellesøy"]
|
15
|
+
|
16
|
+
gem.rdoc_options = ["--main", "README.rdoc"]
|
17
|
+
|
18
|
+
gem.add_dependency "ffi"
|
19
|
+
|
20
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
21
|
+
gem.add_development_dependency "rmagick"
|
22
|
+
end
|
23
|
+
Jeweler::GemcutterTasks.new
|
24
|
+
rescue LoadError
|
25
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'spec/rake/spectask'
|
29
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
35
|
+
spec.libs << 'lib' << 'spec'
|
36
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
37
|
+
spec.rcov = true
|
38
|
+
end
|
39
|
+
|
40
|
+
task :spec => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :spec
|
43
|
+
|
7
44
|
require 'rake/rdoctask'
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
EMAIL = "aslak.hellesoy@gmail.com"
|
16
|
-
DESCRIPTION = "Capture Screenshots on Windows with Ruby"
|
17
|
-
GEM_NAME = "win32screenshot"
|
18
|
-
RUBYFORGE_PROJECT = "win32screenshot"
|
19
|
-
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
20
|
-
RELEASE_TYPES = %w( gem ) # can use: gem, tar, zip
|
21
|
-
|
22
|
-
|
23
|
-
NAME = "win32screenshot"
|
24
|
-
REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
25
|
-
VERS = ENV['VERSION'] || (Win32screenshot::VERSION::STRING + (REV ? ".#{REV}" : ""))
|
26
|
-
CLEAN.include ['**/.*.sw?', '*.gem', '.config']
|
27
|
-
RDOC_OPTS = ['--quiet', '--title', "win32screenshot documentation",
|
28
|
-
"--opname", "index.html",
|
29
|
-
"--line-numbers",
|
30
|
-
"--main", "README",
|
31
|
-
"--inline-source"]
|
32
|
-
|
33
|
-
# Generate all the Rake tasks
|
34
|
-
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
35
|
-
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
36
|
-
p.author = AUTHOR
|
37
|
-
p.description = DESCRIPTION
|
38
|
-
p.email = EMAIL
|
39
|
-
p.summary = DESCRIPTION
|
40
|
-
p.url = HOMEPATH
|
41
|
-
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
42
|
-
p.test_globs = ["test/**/*_test.rb"]
|
43
|
-
p.clean_globs = CLEAN #An array of file patterns to delete on clean.
|
44
|
-
|
45
|
-
# == Optional
|
46
|
-
#p.changes - A description of the release's latest changes.
|
47
|
-
#p.extra_deps - An array of rubygem dependencies.
|
48
|
-
#p.spec_extras - A hash of extra values to set in the gemspec.
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "Win32::Screenshot #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
49
52
|
end
|
50
|
-
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.4
|
@@ -0,0 +1,36 @@
|
|
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(hwnd, &proc)
|
12
|
+
end
|
13
|
+
|
14
|
+
# captures desktop
|
15
|
+
def desktop(&proc)
|
16
|
+
hwnd = BitmapMaker.desktop_window
|
17
|
+
BitmapMaker.capture(hwnd, &proc)
|
18
|
+
end
|
19
|
+
|
20
|
+
# captures window with a *title_query* and waits *pause* (by default is 0.5)
|
21
|
+
# seconds after trying to set window to the foreground
|
22
|
+
def window(title_query, pause=0.5, &proc)
|
23
|
+
hwnd = BitmapMaker.hwnd(title_query)
|
24
|
+
raise "window with title '#{title_query}' was not found!" unless hwnd
|
25
|
+
hwnd(hwnd, pause, &proc)
|
26
|
+
end
|
27
|
+
|
28
|
+
# captures by window handle
|
29
|
+
def hwnd(hwnd, pause=0.5, &proc)
|
30
|
+
BitmapMaker.prepare_window(hwnd, pause)
|
31
|
+
BitmapMaker.capture(hwnd, &proc)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,168 @@
|
|
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', 'kernel32', '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 :set_focus, :SetFocus,
|
42
|
+
[:long], :bool
|
43
|
+
|
44
|
+
# kernel32.dll
|
45
|
+
attach_function :current_thread_id, :GetCurrentThreadId,
|
46
|
+
[], :long
|
47
|
+
|
48
|
+
# gdi32.dll
|
49
|
+
attach_function :create_compatible_dc, :CreateCompatibleDC,
|
50
|
+
[:long], :long
|
51
|
+
attach_function :create_compatible_bitmap, :CreateCompatibleBitmap,
|
52
|
+
[:long, :int, :int], :long
|
53
|
+
attach_function :select_object, :SelectObject,
|
54
|
+
[:long, :long], :long
|
55
|
+
attach_function :bit_blt, :BitBlt,
|
56
|
+
[:long, :int, :int, :int, :int, :long, :int, :int, :long], :bool
|
57
|
+
attach_function :di_bits, :GetDIBits,
|
58
|
+
[:long, :long, :int, :int, :pointer, :pointer, :int], :int
|
59
|
+
attach_function :delete_object, :DeleteObject,
|
60
|
+
[:long], :bool
|
61
|
+
attach_function :delete_dc, :DeleteDC,
|
62
|
+
[:long], :bool
|
63
|
+
attach_function :release_dc, :ReleaseDC,
|
64
|
+
[:long, :long], :int
|
65
|
+
|
66
|
+
EnumWindowCallback = Proc.new do |hwnd, param|
|
67
|
+
title_length = window_text_length(hwnd) + 1
|
68
|
+
title = FFI::MemoryPointer.new :char, title_length
|
69
|
+
window_text(hwnd, title, title_length)
|
70
|
+
title = title.read_string
|
71
|
+
if title =~ Regexp.new(param.read_string) && window_visible(hwnd)
|
72
|
+
param.write_long hwnd
|
73
|
+
false
|
74
|
+
else
|
75
|
+
true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
module_function
|
80
|
+
|
81
|
+
def hwnd(window_title)
|
82
|
+
window_title = window_title.to_s
|
83
|
+
window_params = FFI::MemoryPointer.from_string(window_title)
|
84
|
+
enum_windows(EnumWindowCallback, window_params)
|
85
|
+
if window_title != window_params.read_string
|
86
|
+
# hwnd found
|
87
|
+
window_params.read_long
|
88
|
+
else
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
SW_SHOW = 5
|
94
|
+
|
95
|
+
def prepare_window(hwnd, pause)
|
96
|
+
restore(hwnd) if minimized(hwnd)
|
97
|
+
set_foreground(hwnd)
|
98
|
+
show_window(hwnd, SW_SHOW)
|
99
|
+
sleep pause
|
100
|
+
end
|
101
|
+
|
102
|
+
SW_RESTORE = 9
|
103
|
+
|
104
|
+
def restore(hwnd)
|
105
|
+
show_window(hwnd, SW_RESTORE)
|
106
|
+
end
|
107
|
+
|
108
|
+
def set_foreground(hwnd)
|
109
|
+
if foreground_window != hwnd
|
110
|
+
foreground_thread = window_thread_process_id(current_thread_id, nil)
|
111
|
+
other_thread = window_thread_process_id(hwnd, nil)
|
112
|
+
attach_thread_input(foreground_thread, other_thread, true)
|
113
|
+
set_foreground_window(hwnd)
|
114
|
+
set_focus(hwnd)
|
115
|
+
attach_thread_input(foreground_thread, other_thread, false)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def dimensions_for(hwnd)
|
120
|
+
rect = [0, 0, 0, 0].pack('L4')
|
121
|
+
client_rect(hwnd, rect)
|
122
|
+
x1, y1, x2, y2 = rect.unpack('L4')
|
123
|
+
end
|
124
|
+
|
125
|
+
def capture(hwnd, &proc)
|
126
|
+
hScreenDC = dc(hwnd)
|
127
|
+
x1, y1, x2, y2 = dimensions_for(hwnd)
|
128
|
+
__capture(hScreenDC, x1, y1, x2, y2, &proc)
|
129
|
+
end
|
130
|
+
|
131
|
+
SRCCOPY = 0x00CC0020
|
132
|
+
DIB_RGB_COLORS = 0
|
133
|
+
|
134
|
+
def __capture(hScreenDC, x1, y1, x2, y2, &proc)
|
135
|
+
w = x2-x1
|
136
|
+
h = y2-y1
|
137
|
+
|
138
|
+
hmemDC = create_compatible_dc(hScreenDC)
|
139
|
+
hmemBM = create_compatible_bitmap(hScreenDC, w, h)
|
140
|
+
select_object(hmemDC, hmemBM)
|
141
|
+
bit_blt(hmemDC, 0, 0, w, h, hScreenDC, 0, 0, SRCCOPY)
|
142
|
+
bitmap_size = w * h * 3 + w % 4 * h
|
143
|
+
lpvpxldata = FFI::MemoryPointer.new(bitmap_size)
|
144
|
+
|
145
|
+
# Bitmap header
|
146
|
+
# http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html
|
147
|
+
bmInfo = [40, w, h, 1, 24, 0, 0, 0, 0, 0, 0, 0].pack('L3S2L6')
|
148
|
+
di_bits(hmemDC, hmemBM, 0, h, lpvpxldata, bmInfo, DIB_RGB_COLORS)
|
149
|
+
|
150
|
+
bmFileHeader = [
|
151
|
+
19778,
|
152
|
+
bitmap_size + 40 + 14,
|
153
|
+
0,
|
154
|
+
0,
|
155
|
+
54
|
156
|
+
].pack('SLSSL')
|
157
|
+
|
158
|
+
bmp_data = bmFileHeader + bmInfo + lpvpxldata.read_string(bitmap_size)
|
159
|
+
proc.call(w, h, bmp_data)
|
160
|
+
ensure
|
161
|
+
lpvpxldata.free
|
162
|
+
delete_object(hmemBM)
|
163
|
+
delete_dc(hmemDC)
|
164
|
+
release_dc(0, hScreenDC)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
data/lib/win32screenshot.rb
CHANGED
@@ -1,130 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require 'dl/import'
|
5
|
-
|
6
|
-
module Win32
|
7
|
-
module Screenshot
|
8
|
-
extend DL::Importable
|
9
|
-
|
10
|
-
dlload "kernel32.dll","user32.dll","gdi32.dll"
|
11
|
-
|
12
|
-
USER32 = DL.dlopen("user32")
|
13
|
-
EnumWindows = USER32['EnumWindows', 'IPL']
|
14
|
-
GetWindowTextLength = USER32['GetWindowTextLengthA' ,'LI' ]
|
15
|
-
GetWindowText = USER32['GetWindowTextA', 'iLsL' ]
|
16
|
-
|
17
|
-
SRCCOPY = 0xCC0020
|
18
|
-
GMEM_FIXED = 0
|
19
|
-
DIB_RGB_COLORS = 0
|
20
|
-
|
21
|
-
typealias "HBITMAP","unsigned int"
|
22
|
-
typealias "LPRECT","unsigned int*"
|
23
|
-
|
24
|
-
extern "HWND GetForegroundWindow()"
|
25
|
-
extern "HWND GetDesktopWindow()"
|
26
|
-
extern "BOOL GetWindowRect(HWND, LPRECT)"
|
27
|
-
extern "BOOL GetClientRect(HWND, LPRECT)"
|
28
|
-
extern "HDC GetDC(HWND)"
|
29
|
-
extern "HDC GetWindowDC(int)"
|
30
|
-
extern "HDC CreateCompatibleDC(HDC)"
|
31
|
-
extern "int GetDeviceCaps(HDC, int)"
|
32
|
-
extern "HBITMAP CreateCompatibleBitmap(HDC, int, int)"
|
33
|
-
extern "long SelectObject(HDC, HBITMAP)"
|
34
|
-
extern "long BitBlt(HDC, long, long, long, long, HDC, long, long, long)"
|
35
|
-
extern "void* GlobalAlloc(long, long)"
|
36
|
-
extern "void* GlobalLock(void*)"
|
37
|
-
extern "long GetDIBits(HDC, HBITMAP, long, long, void*, void*, long)"
|
38
|
-
extern "long GlobalUnlock(void*)"
|
39
|
-
extern "long GlobalFree(void*)"
|
40
|
-
extern "long DeleteObject(unsigned long)"
|
41
|
-
extern "long DeleteDC(HDC)"
|
42
|
-
extern "long ReleaseDC(long, HDC)"
|
43
|
-
extern "BOOL SetForegroundWindow(HWND)"
|
44
|
-
|
45
|
-
module_function
|
46
|
-
def capture(hScreenDC, x1, y1, x2, y2)
|
47
|
-
w = x2-x1
|
48
|
-
h = y2-y1
|
49
|
-
|
50
|
-
# Reserve some memory
|
51
|
-
hmemDC = createCompatibleDC(hScreenDC)
|
52
|
-
hmemBM = createCompatibleBitmap(hScreenDC, w, h)
|
53
|
-
selectObject(hmemDC, hmemBM)
|
54
|
-
bitBlt(hmemDC, 0, 0, w, h, hScreenDC, 0, 0, SRCCOPY)
|
55
|
-
hpxldata = globalAlloc(GMEM_FIXED, w * h * 3)
|
56
|
-
lpvpxldata = globalLock(hpxldata)
|
57
|
-
|
58
|
-
# Bitmap header
|
59
|
-
# http://www.fortunecity.com/skyscraper/windows/364/bmpffrmt.html
|
60
|
-
bmInfo = [40, w, h, 1, 24, 0, 0, 0, 0, 0, 0, 0].pack('LLLSSLLLLLL').to_ptr
|
61
|
-
|
62
|
-
getDIBits(hmemDC, hmemBM, 0, h, lpvpxldata, bmInfo, DIB_RGB_COLORS)
|
63
|
-
|
64
|
-
bmFileHeader = [
|
65
|
-
19778,
|
66
|
-
(w * h * 3) + 40 + 14,
|
67
|
-
0,
|
68
|
-
0,
|
69
|
-
54
|
70
|
-
].pack('SLSSL').to_ptr
|
71
|
-
|
72
|
-
data = bmFileHeader.to_s(14) + bmInfo.to_s(40) + lpvpxldata.to_s(w * h * 3)
|
73
|
-
|
74
|
-
globalUnlock(hpxldata)
|
75
|
-
globalFree(hpxldata)
|
76
|
-
deleteObject(hmemBM)
|
77
|
-
deleteDC(hmemDC)
|
78
|
-
releaseDC(0, hScreenDC)
|
79
|
-
|
80
|
-
return [w, h, data]
|
81
|
-
end
|
82
|
-
|
83
|
-
def capture_hwnd(hwnd)
|
84
|
-
hScreenDC = getDC(hwnd)
|
85
|
-
|
86
|
-
# Find the dimensions of the window
|
87
|
-
rect = DL.malloc(DL.sizeof('LLLL'))
|
88
|
-
getClientRect(hwnd, rect)
|
89
|
-
x1, y1, x2, y2 = rect.to_a('LLLL')
|
90
|
-
|
91
|
-
capture(hScreenDC, x1, y1, x2, y2)
|
92
|
-
end
|
93
|
-
|
94
|
-
module_function
|
95
|
-
def foreground
|
96
|
-
hwnd = getForegroundWindow
|
97
|
-
capture_hwnd(hwnd)
|
98
|
-
end
|
99
|
-
|
100
|
-
module_function
|
101
|
-
def desktop
|
102
|
-
hwnd = getDesktopWindow
|
103
|
-
capture_hwnd(hwnd)
|
104
|
-
end
|
105
|
-
|
106
|
-
module_function
|
107
|
-
def window(title_query, delay=0.1)
|
108
|
-
hwnd = nil
|
109
|
-
|
110
|
-
proc = DL.callback('ILL') do |curr_hwnd, lparam|
|
111
|
-
textLength, a = GetWindowTextLength.call(curr_hwnd)
|
112
|
-
captionBuffer = " " * (textLength+1)
|
113
|
-
t, textCaption = GetWindowText.call(curr_hwnd, captionBuffer, textLength+1)
|
114
|
-
text = textCaption[1].to_s
|
115
|
-
if text =~ title_query
|
116
|
-
hwnd = curr_hwnd
|
117
|
-
0
|
118
|
-
else
|
119
|
-
1
|
120
|
-
end
|
121
|
-
end
|
122
|
-
EnumWindows.call(proc, 0)
|
123
|
-
|
124
|
-
raise "Couldn't find window with title matching #{title_query}" if hwnd.nil?
|
125
|
-
setForegroundWindow(hwnd)
|
126
|
-
sleep(delay)
|
127
|
-
capture_hwnd(hwnd)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
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"
|